Input events on X have an old world and a new world

June 15, 2020

The X Window System is now very old, and it never had what you could call 'protocol agility' in the core X protocol. As a result, over the years X has been extended through both conventions (such as modern X fonts) and X server extensions. In theory both forms of extension are optional and servers and clients may not support any specific one; in practice, various common things are now mandatory for any X server or client that wants to work right in the modern world.

(For instance, X servers increasingly don't have many old style X fonts available for you to use and they're often not very good looking.)

As part of X's evolution over time, input event handling has gone through a practical change, although one that is what you could call unevenly distributed. The original X protocol has input events, of course, which are sometimes now called core input events. You can see what core events are generated from various activities through the venerable xev program, and many straightforward X programs continue to interact only with core events.

However, core input events have limitations that date from X's origins. Core input events are only really designed to deal with straightforward keyboards and mice with buttons. Even mouse scroll wheels have an awkward representation in core X events; moving the scroll wheel actually generates mouse button events for pressing and releasing button 4 or 5 (for normal, implicitly vertical scroll wheels). I don't think there's anything in the X protocol that reserves these buttons for scroll wheels, it's just a convention that people came up with when they started needing to handle scroll wheels in X.

I suspect that what pushed people over the edge on X input handling was laptop touchpads and trackpads. You can pretend that a touchpad is a mouse and manufacture appropriate X events from finger touches and presses, but this isn't really a good representation of what is actually going on. More sophisticated programs might want to know all sorts of additional information that a touchpad can deliver, and then there's additional input devices like pens.

The solution to this is the X Input (Device) Extension. This extension understands that you may have multiple input devices connected, not just one (for example you may have both a touchpad and an external mouse) and it delivers a much richer event stream to programs that want to use it. It also generates core input events from this richer, more sophisticated input event stream. You can more or less see what XIE events are generated when you do things with 'xinput test-xi2', although you probably need to know more than you do to interpret xev output.

Programs using a modern toolkit like GTK+ will often attempt to use XIE (and may in practice require it). On Linux (and perhaps other Unixes), one sign of such programs is that they use the libXi shared library, which is the X client library for dealing with the X Input Extension. A C program that isn't using this shared library is very unlikely to be using XIE; a C program that has loaded it very likely is using XIE in preference to core input events, especially if it's using a toolkit like GTK+.

One of the important consequences of this split between core input events and XIE events is that events that look identical at the core input event level (for example, as shown by xev) may be different at the XIE level (as interpreted by libXi and then toolkit libraries, and perhaps as shown by xinput). This means that some programs will treat them exactly the same because they're indistinguishable and some programs may react to them differently. This can cause rather odd issues, but that's a story for another entry.

Written on 15 June 2020.
« Product code and utility code
A scrolling puzzle involving GTK+, XInput, and alternate desktops (on Fedora) »

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

Last modified: Mon Jun 15 23:17:02 2020
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.