Thursday, April 7, 2016

Why libinput doesn't have a lot of config options

Most days, at least one of the bugs I deal with requests something along the lines of "just add $FOO as a config option". In this post, I'll explain why this is usually a bad solution. First, read and keep those arguments in mind. Generally, there are two groups of configuration options - hardware options and user options. Hardware options are those that deal with specific quirks needed on some hardware, but not on other hardware. User options are those that deal with user preferences such as tapping or two-finger vs. edge scrolling.

In the old synaptics driver, we added options whenever something new came up and we tried to make those options generic. This was a big mistake. The driver now has over 70 configuration options resulting in a test matrix with a googolplex of combinations. In other words, it's completely untestable. To make a device work users often have to find the right combination of options from somewhere, write out a root-owned config file and then hope this works. Why do we still think this is acceptable? Even worse: some options are very specific to hardware but still spread in user forum examples like an STD during spring break.

In libinput, we're having none of that. When hardware doesn't work we expect a user to file a bug, we get it fixed upstream for the specific model and thus automatically fix it for all users of that device. We're leaning heavily on udev's hwdb which we have extended to correct devices when the firmware announces wrong information. This has the advantage that there is only one authoritative source of quirks a device needs to work. And we can update this as time goes by without having to worry about stale configuration options. One good example here is the custom acceleration profile that Lenovo X230 touchpads have in libinput. All in all, there is little pushback for the lack of hardware-specific configuration options and most users are fine with it once they accept the initial waiting period to get the patch into their distribution.

User-specific options are more contentious. In our opinion, some features should be configurable and others should not. Where to draw that line is of course quite undefined. For example, tapping on or off was one of the first configuration options available and that was never a cause for arguments either way (except whether the default should be on or off). Other options are more contentious. Clickpad software buttons are always on the bottom edge and their size is hardcoded (synaptics allowed almost free positioning of those buttons). Other features such as changing a two-finger tap to some other button event is not supported at all in libinput. This effectively comes down to cost. You see, whenever you write "it's just 5 lines of code to make this an option", what I think is "once the patch is reviewed and applied, I'll spend two days to write test cases and documentation. I'll need to handle any bug reports related to this, and I'm expected to make sure this option works indefinitely. Any addition of another feature may conflict with this option, so I need to make sure the right combination is possible and test cases are written." So your work ends after writing a 5 line patch, my work as maintainer merely starts. And unless it pays off long-term, the effort is not worth it. Some features make that cut, others don't if they are too much of a niche feature.

All this is of course nothing new and every software project needs to make these decisions. Input isn't even a special case here, it pales in comparison with e.g. the decisions UI designers need to make. However, in FOSS we have a tendency to think that because something is possible, it should be done. Legally, you have freedom to do almost anything with the software, so you can maintain a local fork of libinput with that extra feature applied. If that isn't acceptable, why would it be acceptable to merge the patch and expect others to shoulder the costs?


Simon Geard said...

Yes, it's always a balancing act. A new option might be just 5 lines of code, but it's at least one new conditional element, adding to all the permutations that need to be covered by testing, which need to be documented, which need to be checked when the entire area gets rewritten at a later date. Actually writing code is often quite a small part of a developer's job, and the more experienced the developer, the smaller that proportion.

And yes, sometimes options are worth the effort - your example of "tap to click' is a perfect illustration, since some people love it, some people hate it, and some people want to turn it on and off regularly depending on what they're doing, so in that case, you can't pick a single option that pleases a majority, much less everyone.

But you have to draw a line somewhere... you can't accept every option that's proposed; at some point, figuring out how to configure all the options becomes the most complicated part of the system. I've seen more than a few apps where the Preferences window requires a search function to use, and in general, that's a bad sign.

Unknown said...

I'm not big on configuration settings, many times configuration is just workarounds instead of fixing the root cause.
However, when you write "Clickpad software buttons are always on the bottom edge and their size is hardcoded" it feels a little narrow. I have a Lenovo T431s, which requires soft buttons. However, since they have a trackpoint they also assume the buttons to be on top. They even have markings for the buttons at the top of the trackpad.
And I don't want to have this configurable, but for a computer like the Lenovo T431s libinput really needs to be able to have the soft buttons on top (preferably without any configuration).

Peter Hutterer said...

The T431 should have top software buttons enabled. See
If those buttons don't work, please file a bug so we can fix it.

This is the best example for internal hardware-specific handling that previously was exposed through config options in synaptics but now just works out of the box.

Robert K said...

I just want to make sure I understand it correctly, you said:

"Other features such as changing a two-finger tap to some other button event is not supported at all in libinput."

And can I infer from this, that libinput won't support button remapping? I presume a two-finger tap is no different from any other button event? I don't think I can get my button-map accepted upstream, because it is more of a preference than a hardware quirk, so I guess I should run a patched whatever to remap buttons?

Unknown said...

Ok, if 431 have top buttons enabled, I'm happy. And I then obviously read the quote "Clickpad software buttons are always on the bottom edge and their size is hardcoded" to strict.
And I'm all for having things like that just work, instead of doing it the synaptic way (which was googling the internet for someone else that had simmilar problems, take their config and modifying it by trial and error... and after 4 hours of googling and modifying different files in /etc/ it behaved as expected... just to break the next time you upgraded the distribution).

Peter Hutterer said...

RĂ³bert: yeah, we don't support button remapping outside of hardware specifics and left-handed setting. True remapping would have to be handled in the caller. You'd have to have a pretty good use-case.

Unknown said...

Great post, Peter. I appreciate also the work to make it clean upstream and the udev hwdb as consolidated point of tweaks. What you're saying probably also applies to Gnome compared to KDE - I loved all the knobs that KDE provided me, w/o thinking of the maintenance complexity there. I've been adjusting to Gnome's minimalist interface, so appreciate the reminder of the hidden values to it.

sjakub said...


Not sure if that' the right place to ask this question,
but it feels relevant enough ;)

I have always used left wheel tilt as a middle button (by switching
those two "buttons" using "ButtonMapping" in xorg configuration file).
I did that because the regular middle button on most mouses is hard to press, and tilting the wheel is much easier and faster for me. And I use it A LOT.

Since qt switched to xinput2, it ignores that mapping.
All the other buttons work fine, but not the wheel events.
According to this:
it is because the wheel is treated differently.
Is there a way to achieve what I am trying to do?