Search code examples
keyboardkeypressxcb

Generate keypress with xcb xtest


I am just trying to generate a keypress to the active window with XCB. I have got some code that I think should work. There's seems to be about a 1/10 chance when I run it that the w key acts like it's held down until I press and release w, and the other 9/10 nothing happens at all. Here's the code:

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

int main() {
    xcb_connection_t *conn;

    conn = xcb_connect(NULL, NULL);
    if (xcb_connection_has_error(conn))
        puts("failed to connect\n");

    xcb_test_fake_input(conn, XCB_KEY_PRESS, 25, XCB_CURRENT_TIME, XCB_NONE, 0, 0, 0);

    xcb_flush(conn);
    xcb_disconnect(conn);
}

compile:

gcc c.c -lxcb -lxcb-xtest

Does it work for you? What am I doing wrong?


Solution

  • There's seems to be about a 1/10 chance when I run it that the w key acts like it's held down until I press and release w,

    Your program generates a key press, but no key release. Try another call with XCB_KEY_RELEASE.

    and the other 9/10 nothing happens at all.

    I would guess that this would be fixed by adding something like free(xcb_get_input_focus_reply(conn, xcb_get_input_focus(conn), NULL)); before the call to xcb_disconnect() should fix this.

    My theory here is that you race with the X11 server. The X11 server does not necessarily read pending data from the connection when poll() indicates that the other end hung up. Thus, by just sending your request and disconnecting, it could get lost.

    My proposed change sends another request and waits for the reply from the X11 server. This makes sure that everything before that was already handled.