X's two ways to send events to X clients (more or less)

October 5, 2023

Once upon a time, the X11 protocol was shiny and new. One small part of the protocol (and the client library) was a way for one client program to send X events, such as key or mouse presses (or more routinely expected things)), to another program. In Xlib, this is XSendEvent() (also). When the target X client receives this event, it will have a special flag set in the X event structure to signal that it comes from a SendEvent request from another client. Such events are normally called synthetic events, because they were created synthetically by another X client, instead of naturally by the X server.

X11 wasn't (and isn't) the most secure windowing system (in an access control sense), with it being pretty easy for people to connect X clients to your X server session. Partly because of this, X programs like xterm either started out being able to ignore such synthetic events (for key and mouse events, at least) or soon added this feature. As covered in the xterm manual page, this is allowSendEvents and is described this way:

Specifies whether or not synthetic key and button events (generated using the X protocol SendEvent request) should be interpreted or discarded. The default is "false" meaning they are discarded. Note that allowing such events would create a very large security hole, therefore enabling this resource forcefully disables the allowXXXOps resources. The default is "false".

If you hang around people who automate things in their X session, you may have heard of xdotool. If you've tried it, you may have noticed that xdotool seems pretty successful in manipulating the windows of X programs, despite the general feelings about SendEvents, and so you might wonder what's going on here. The answer is that xdotool (and other automation programs) use a second mechanism to inject synthetic events, the XTEST extension (protocol). The original purpose of this extension is, to quote its documentation:

This extension is a minimal set of client and server extensions required to completely test the X11 server with no user intervention.

Events injected through XTEST don't carry the 'SendEvents mark of shame', and so programs like xterm won't automatically reject them. However, due to its origins (and also probably security concerns), XTEST has certain limitations, and so in some circumstances xdotool has to fall back to (X)SendEvent(s) and suffer the mark of shame and perhaps having things not work.

A nice description of the situation is in the xdotool manual page's SENDEVENT NOTES section:

If you are trying to send key input to a specific window, and it does not appear to be working, then it's likely your application is ignoring the events xdotool is generating. This is fairly common.

Sending keystrokes to a specific window uses a different API than simply typing to the active window. If you specify 'xdotool type --window 12345 hello' xdotool will generate key events and send them directly to window 12345. However, X11 servers will set a special flag on all events generated in this way (see XEvent.xany.send_event in X11's manual). Many programs observe this flag and reject these events.

It is important to note that for key and mouse events, we only use XSendEvent when a specific window is targeted. Otherwise, we use XTEST.

If you don't target a specific window and use XTEST, it's like you typed the keys at your keyboard. The 'typed' keys go to whatever window has keyboard focus at the time xdotool runs, or into the void if no window has keyboard focus at the time. With SendEvent you can type the keys to a specific identified window no matter what else is going on, but interesting programs will probably ignore you.

(Even if programs don't ignore you because of the SendEvent mark, they may ignore you for other reasons. For example, Gnome Terminal appears to accept SendEvent keyboard input, but only if it currently has keyboard focus.)

(This entry is a variation on part of something I wrote recently on the fvwm mailing list.)

Written on 05 October 2023.
« You can do Apache HTTP Basic Authentication through PAM
Understanding the orderless package for GNU Emacs »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Oct 5 22:53:47 2023
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.