0
votes

I'm trying to send key events by creating a XKeyEvent and sending it using XSendEvent (inspired by this post). The XKeyEvents are prepared as follows:

XKeyEvent createKeyEvent(Display *display, Window win, Window winRoot, _Bool press, int keycode, int modifiers) {
    XKeyEvent event;

    event.display     = display;
    event.window      = win;
    event.root        = winRoot;
    event.subwindow   = None;
    event.time        = CurrentTime;
    event.x           = 1;
    event.y           = 1;
    event.x_root      = 1;
    event.y_root      = 1;
    event.same_screen = True;
    event.keycode     = keycode;
    event.state       = modifiers;

    if (press) {
        event.type = KeyPress;
    } else {
        event.type = KeyRelease;
    }

    return event;
}

Then they are sent with XSendEvent(event.display, event.window, 1, KeyPressMask, (XEvent *)&event);

The key events are sent and the target program receives them (letters are entered, arrow keys work etc.). However, problems arise with modifier keys. Let's say the program sends a key-down event for the opt/alt key. In this scenario, the text in the menu bar is underlined until a key-up event is sent (indicating that the X-server has received and processed the key-down event).

However, when retrieving the the current state of the modifier keys, the modifier keys do not appear to be pressed at all. When calling XQueryPointer(self->display, winFocus, &root_return, &child_return, &root_x_return, &root_y_return, &win_x_return, &win_y_return, &keyboard_state_mask);, the keyboard_state_mask is 0. Checking the keyboard with xev gives the same result. Physically pressing the modifier keys does change the state mask, both in xev and in my code.

How do I properly change the current modifier-key state?

2
It's not quite clear to me but, are you expecting the X11 servers view of the keyboard modifiers state to be affected by the events you send?G.M.
Yes, I'm expecting that to happen.Walter Berggren

2 Answers

0
votes

Solved the problem by using the method int XTestFakeButtonEvent(display, button, is_press, delay) from the library <X11/extensions/XTest.h>. For some reason, this causes the keyboard modifier state to change when sending a modifier key (as I wanted), while the above-mentioned method does not.

0
votes

From xsendevent man pages:

"The contents of the event are otherwise unaltered and unchecked by the X server except except to force send_event to True in the forwarded event and to set the serial number in the event correctly."

I assume that you copied createKeyEvent() from the following place: http://www.doctort.org/adam/nerd-notes/x11-fake-keypress-event.html

And if you also copied the way this function is called:

createKeyEvent(display, winFocus, winRoot, false, KEYCODE, 0);

then it makes sense that "modifier" is not set to anything, as the last argument is "0". According to documentation you need to set the modifier state yourself.

I did not verify this information. If it does not work as documented, that it might be a documentation bug or a bug in X server's implementation.