2

I've programmed a key to run xdotool when it's pressed. But for some unknown reason xdotool is only sending keystrokes when the binded key is released, except when a non-active window is sent the keystrokes with --window, in which case it (as I would like it to do for the active window instead) sends the keystrokes as the binded key is pressed as well as repeatly when held down.

Example code with the issue:

#include <stdio.h>
#include <stdlib.h>
#include <xcb/xcb.h>

int main() {
    xcb_connection_t *connection = xcb_connect(NULL, NULL);

    xcb_screen_t *screen = xcb_setup_roots_iterator(xcb_get_setup(connection)).data;

    xcb_grab_key(connection, 1, screen->root, XCB_NONE, 65, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);  // 65=space (on mine at least)

    xcb_flush(connection);

    xcb_generic_event_t *event;
    while ( (event = xcb_wait_for_event(connection)) ) {
        switch (event->response_type & ~0x80) {
            case XCB_KEY_PRESS: {

                // UNCOMMENT ONE OF THE LINES BELOW
                // system("xdotool key q");  // only on release :(
                // system("xdotool getactivewindow key --window %1 q");  // only on release :(
                // system("xdotool key --window 18874376 q");  // (replace 18874376 with one of your window's id, could use 'xdotool getactivewindow') works perfectly for me but only if the specified window is not active :(

                break;
            }
        }
        free(event);
    }
}

Please note above doesn't work with modifiers on, including Num Lock.

To compile it:

gcc c.c -lxcb

Do you experience the same and how do I get what I want?

4
  • I'm not familiar with this stuff as I used to. But I think you need to have DISPLAY env var exported maybe XAUTHORITY also. See similar question here. unix.stackexchange.com/q/68054/85046 Feb 10 '20 at 9:27
  • Ah, I see. You can successfully send a keystrokes. But the issue is the releasing them. Look here at the first comment under the question: unix.stackexchange.com/questions/214909/… Feb 10 '20 at 9:37
  • 1
    You should be doing all that stuff directly in C, instead of calling via system() to the clunky xdotool. Look for the X11 XTEST and xcb_test_fake_input().
    – mosvy
    Feb 10 '20 at 13:12
  • xdotool's only advantage is that it could be called from shell, where you have to put up with all kind of limitations and quirks. From C you can do much better, eg. handle multipointer/multifocus setups with XGetDeviceFocus() instead of XGetInputFocus(). For xdotool's getactivewindow, look for the EWMH's _NET_ACTIVE_WINDOW property.
    – mosvy
    Feb 10 '20 at 13:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.