Difference between XTestFakeButtonEvent & XSendEvent Difference between XTestFakeButtonEvent & XSendEvent google-chrome google-chrome

Difference between XTestFakeButtonEvent & XSendEvent


XSendEvent produces events that are marked as sent. Events sent by the server are not marked.

   typedef struct {           int type;           unsigned long serial;            Bool send_event;        // <----- here           Display *display;           Window window;   } XAnyEvent;

Some applications ignore events that have this flag set, for security reasons. Think of malware that somehow gets access to your X11 server — it can trick any application into doing whatever it wants by sending those events.

It is perfectly OK to use the second variant on your own machine, but it relies on an extension that can be disabled (again, for security reasons) and so not necessarily works on other people's X11 servers.


On XCB you can use the following function to verify if event was sent via XSendEvent() / xcb_send_event() API:

static bool fromSendEvent(const void *event){    // From X11 protocol: Every event contains an 8-bit type code. The most    // significant bit in this code is set if the event was generated from    // a SendEvent request.    const xcb_generic_event_t *e = reinterpret_cast<const xcb_generic_event_t *>(event);    return (e->response_type & 0x80) != 0;}

AFACT, there is no way to tell if event was send via XTest extension.

You should use XTest as it will work better, XSendEvents don't know anything about internal X server state. Fom XSendEvent manual:

"The contents of the event are otherwise unaltered and unchecked by the X server except to force send_event to True".

So with XSendEvent you might have unexpected issues in some situations.


Although not by using Xlib directly, but through a python Xlib wrapper library as a proxy to Xlib, the first approach currently does work on all windows I currently have open on my desktop, other than with IntelliJ.

In this first approach, you are sending the event directly to a target window, and as others have noted, your event is also marked (tainted) with an attribute value marking it as a simulated one. The receiving window might act on it just the same, as many application windows do.

With the second approach however, you are emulating the actual thing happening ― per my understanding virtually indistinguishable from a user solicited event: the event goes through the fuller X11 flow of handling for a user input event (rather than being blindly dispatched directly to the target window) which means that it will trickle down to the window (or Gnome desktop widget) under the pointer as in the natural flow of events for real user solicited events.

As such, the second approach appears to be more broadly applicable than the first approach ― it will have the desired effect also for windows that opt not to act on the event sent to them through the first approach, as well as on e.g. Gnome desktop elements which are not ordinary windows per-se (such as the language and power widgets). You supply the coordinates without any mention of a window, and the click goes through.

If I had to come up with some kind of explanation for this duality of routes, I might think that XSendEvent is more of a general purpose event sending facility, whereas XTEST provides means for specifically simulating user input events.