简体   繁体   中英

X11 how to properly send event using XSendEvent?

I'm trying to send a key press event to the X11 display but the events are not getting sent.

Here's my current attempt:

void sendEvent(int scanCode, bool isPressed) {
    unsigned long focusedWindow;
    int focusRevert;
    int mask = isPressed ? KeyPressMask : KeyReleaseMask;

    XGetInputFocus(display, &focusedWindow, &focusRevert);

    XKeyEvent event;
    memset(&event, 0, sizeof(XKeyEvent));
    event.keycode = scanCode + 8;
    event.type = isPressed ? KeyPress : KeyRelease;
    event.root = focusedWindow;
    event.display = display;

    XSendEvent(display, focusedWindow, 1, mask, (XEvent *)&event);
    XSync(display, 0);
}

I tried debugging, XSendEvent return value is 1 which is for success, but the events didn't registered, as for example I tried sending a CapsLock key event, but seems like the toggle state of the key was as it was (no changes).

I also tried to add a sleep so if anything asynchronous happens before function exits, I can catch up.

So I'm totally confused what is the problem in the code, and why is it not sending the event correctly.

According to the documentation :

To determine which clients should receive the specified events, XSendEvent uses the propagate argument as follows:

  • If event_mask is the empty set, the event is sent to the client that created the destination window. If that client no longer exists, no event is sent.
  • If propagate is False, the event is sent to every client selecting on destination any of the event types in the event_mask argument.
  • If propagate is True and no clients have selected on destination any of the event types in event-mask, the destination is replaced with the closest ancestor of destination for which some client has selected a type in event-mask and for which no intervening window has that type in its do-not-propagate-mask. If no such window exists or if the window is an ancestor of the focus window and InputFocus was originally specified as the destination, the event is not sent to any clients. Otherwise, the event is reported to every client selecting on the final destination any of the types specified in event_mask.

What happens if you set propagate to False and the window to root ?

eg

event.root = RootWindow(display, DefaultScreen(display));
XSendEvent(display, event.root, 0, mask, (XEvent *)&event);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM