Wednesday, August 31, 2016

New xserver driver sort order - evdev < libinput < (synaptics|wacom|...)

In the X server, the input driver assignment is handled by xorg.conf.d snippets. Each driver assigns itself to the type of devices it can handle and the driver that actually loaded is simply the one that sorts last. Historically, we've had the evdev driver sort low and assign itself to everything. synaptics, wacom and the other few drivers that matter sorted higher than evdev and thus assigned themselves to the respective device.

When xf86-input-libinput first came out 2 years ago, we used a higher sort order than all other drivers to assign it to (almost) all devices. This was of course intentional because we believe that libinput is the best input stack around, the odd bug non-withstanding. Now it has matured a fair bit and we had a lot more exposure to various types of hardware. We've been quirking and fixing things like crazy and libinput is much better for it.

Two things were an issue with this approach though. First, overriding xf86-input-libinput required manual intervention, usually either copying or symlinking an xorg.conf.d snippet. Second, even though we were overriding the default drivers, we still had them installed everywhere. Now it's time to start properly retiring the old drivers.

The upstream approach for this is fairly simple: the xf86-input-libinput xorg.conf.d snippet will drop in sort order to sit above evdev. evdev remains as the fallback driver for miscellaneous devices where evdev's blind "forward everything" approach is sufficient. All other drivers will sort higher than xf86-input-libinput and will thus override the xf86-input-libinput assignment. The new sort order is thus:

  • evdev
  • libinput
  • synaptics, wacom, vmmouse, joystick
evdev and libinput are generic drivers, the others are for specific devices or use-cases. To use a specific driver other than xf86-input-libinput, you now only have to install it. To fall back to xf86-inputlibinput, you uninstall it. No more manual xorg.conf.d snippets symlinking.

This has an impact on distributions and users. Distributions should ensure that other drivers are never installed by default unless requested by the user (or some software). And users need to be aware that having a driver other than xf86-input-libinput installed may break things. For example, recent GNOME does not support the synaptics driver anymore, installing it will cause the control panel's touchpad bits to stop working. So there'll be a messy transition period but once things are settled, the solution to most input-related driver bugs will be "install/remove driver $foo" as opposed to the current symlink/copy/write an xorg.conf.d snippet.


Sébastien Wilmet said...

And what if a user wants to install both GNOME and Xfce (for example), and choose the session at login time. Assuming that GNOME relies on libinput, and Xfce relies on synaptics and the other drivers.

I think this use case should still be supported, and ideally in a smart way: if both libinput and synaptics are installed, GNOME would choose libinput, and Xfce would choose synaptics. Isn't that possible?

Berend De Schouwer said...

This sounds wrong. Drivers go in /usr, config goes in /etc. Some installations have /usr read-only (can't add or remove a driver), and /etc read-write.

An example where this could break: LTSP, live DVDs.

Peter Hutterer said...

Sébastien: this is already a problem and won't change. You can't change the driver from the session, only from the xorg.conf so nothing really changes here. You already have to do manual symlinks to achieve this and you can still do it afterwards.

Berend: we've put the distribution-provided config snippets into /usr since 2008 or so, with the local configuration in /etc. nothing changes here except the filename for the libinput config snippet (and thus the sort order)

Lisandro Damián Nicanor Pérez Meyer said...

Interestingly enough yesterday I removed libinput in favor of evdev on an embedded system because it was not clear to me how to swap axis and invert one of them. I guess that would have to be done trough some matrix, but the easiest way out was to simply get libinput out of the way.