1

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.

Animesh Sahu
  • 7,445
  • 2
  • 21
  • 49
  • @MikeCAT sure – Animesh Sahu Jan 05 '21 at 11:40
  • What are the values of `focusedWindow` and `focusRevert` after calling the function `XGetInputFocus`? `XSendEvent` can generate errors, do you have an error handler? Return of non zero means, that there was no '_conversion to wire protocol format_' error, but the server can still generate `BadValue` and `BadWindow` errors. – Erdal Küçük Jan 05 '21 at 12:26
  • @ErdalKüçük Hi, `focusedWindow` is `44040203`, `focusRevert` is `2`, and `XSendEvent` returns 1. And by the way returning non-zero value is success as stated in [docs](https://www.x.org/releases/X11R7.5/doc/man/man3/XSendEvent.3.html). – Animesh Sahu Jan 05 '21 at 12:38
  • @Animesh Sahu `XSendEvent` returns zero **if the conversion to wire protocol format failed** and returns nonzero otherwise **AND** `XSendEvent` can generate `BadValue` and `BadWindow` errors. The 'client' can give you a nonzero value, but the 'server' can still generate these errors. – Erdal Küçük Jan 05 '21 at 12:48
  • I tried setting up the handler as [this](https://stackoverflow.com/a/20122051/11377112), and there's no errors. – Animesh Sahu Jan 05 '21 at 13:32

1 Answers1

0

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?

e.g.

event.root = RootWindow(display, DefaultScreen(display));
XSendEvent(display, event.root, 0, mask, (XEvent *)&event);
Erdal Küçük
  • 4,810
  • 1
  • 6
  • 11
  • The code doesn't compile as RootWindow takes another parameter. I've tried `XDefaultRootWindow(display)`, but results are the same, nothing changed. I also tried setting a handler as [this](https://stackoverflow.com/a/20122051/11377112) no output (no errors). Any suggestions, why isn't it working? – Animesh Sahu Jan 05 '21 at 13:29
  • @Animesh Sahu Yeah, you're right. RootWindow wants a screen too, i've updated that. Honestly, i don't know what you are trying to accomplish. I suppose, you want to send a key event to the actual focused window (hence a call to XGetInputFocus). Have you tried to write 2 clients, which are sending events to each other, before you went global? – Erdal Küçük Jan 05 '21 at 13:42
  • Nope, haven't wrote such clients. But since there's no error and I'm trying to do this similar to what docs stated, I expect this should've been working. I'm not able to understand what's the problem here . – Animesh Sahu Jan 05 '21 at 14:14