Thursday, July 24, 2008

Input configuration in a nutshell.

Once upon a time, we had a number of free operating systems. Linux, BSDs, emacs, XFree86, you name it. Then one of them chose to be less like one and become a windowing system instead (which was supposed to it's job from the beginning, albeit it kinda forgot about it halfway there). The principle of DTRT was embraced and the almighty xorg.conf file was given the handshake and shown the door. These days, X starts without a config file these days, and everything just works.

Most of the time. When it doesn't it's usually ugly. So here's a guide on how to configure input devices with recent servers. This guide includes
  • a quick overview of the evdev input driver
  • how to set up input hotplugging.
  • what to do in the xorg.conf
First, if you're not running Linux you can stop reading. Keep your config file, make sure you reference your input devices in the ServerLayout section, and start porting the evdev kernel module to your OS of choice.


A quick overview of the evdev input driver
xf86-input-evdev is the hotplugging-capable input driver to be used for mice and keyboards (and other devices, if appropriate). One main difference is that it uses devices files such as /dev/input/event0 instead of /dev/input/mouse0 (like the mouse driver does for example). The other big difference is that it can query the kernel about the capabilities about each device and set up itself correctly. So if you point a device to /dev/input/event0, it will automatically set itself up as mouse or keyboard, as appropriate.
The second important thing is that it puts a grab on the device file (not the same as a pointer/keyboard grab in X!). This grab gives us two benefits: the device will not send events to the collector devices (e.g. /dev/input/mice) anymore. And if anyone else tries to grab the device they will fail. So we can ensure that only one process receives events from this device.

What does all this mean to us now?
We can change our mice and keyboards in the xorg.conf to use the evdev driver instead. As device, we can either specify /dev/input/eventX, but these numbers may change on reboot. Look into the /dev/input/by-id and /dev/input/by-path directory. I recommend to always use /dev/input/by-id/MyMouseName-event-mouse as device instead of the eventX files. Note that you'll find MyMouseName-mouse and MyMouseName-event-mouse, of which only the latter will work with evdev. Ignore the former.
The big benefit is simply that you can configure multiple devices quite easily now. Simply set up InputDevice sections for each device and the X server will treat them as different devices. This is quite useful if you're using MPX.


How to set up input hotplugging

Writing xorg.conf sections is not only boring, it's also quite pointless in most cases. So let's let the server find input devices automagically. The two ingredients are HAL and DBus. At startup, the server queries HAL over DBus for a list of devices and adds them one-by-one.

All you need to do is configure HAL so the server adds the devices with the right options.
You must merge the key input.x11_driver. Look at x11-input.fdi. This file should reside in /etc/hal/fdi/policy/, and it tells HAL to merge the evdev driver for each mouse and keyboard It also merges some Xkb options for keyboards.
Important: the server will not add devices unless they have input.x11_driver set. If you end up with no devices at all, then your HAL setup is probably broken.

To test your installation, run hal-device to obtain a list of all devices and look for the input.x11* keys. If they are not present, modify the fdi file and restart HAL.

Your X server is now hot-plug capable. It will add all mice and keyboards automatically, even if you add/remove them at runtime. There's modified fdi files floating around to add hotplug for wacom tablets and synaptics touchpad, finding them is left as an exercise for the reader.

What to do with the xorg.conf
We have two configuration files now. Yay. One is xorg.conf, the other one is the fdi file. And they both don't know about each other, leading to interesting results. The server parses xorg.conf first, then gets the devices through HAL. And here we have a big culprit: if add a InputDevice section with the mouse driver, it will conflict with the evdev driver. Evdev grabs the files, remember? So when all mice are added through the HAL evdev hotplugging mechanism, all mice stop sending to the /dev/input/mice file. So although you still have a valid input device in the server, it will never emit any events.
The only solution here? Either stop hotplugging alltogether by adding Option "AutoAddDevices" "off" in your ServerLayout, or modify the fdi file that it doesn't merge input.x11_driver for the specific mice you don't want hotplugged (or all mice).

Troubleshooting list:
  • I have no input devices and compiled the server myself. Install libhal-dev and libdbus-dev, re-run configure and recompile.
  • I have no input devices. HAL setup needs to be configured. Make sure the x11-input.fdi file is in /etc/hal/fdi/policy, and that hal-device lists mice and keyboards with input.x11_driver = "evdev".
  • My xorg.conf settings are ignored. HAL adds your devices without settings, and evdev grabs all devices away. Modify the fdi and add your settings there, or add Option "AutoAddDevices" "off" to your ServerLayout. Note that this will stop input hotplugging.
  • I'm getting a "Grab failed" in the logs. You have two evdev input devices pointing to the same device file. This usually only happens if you have a xorg.conf entry with an evdev, and then HAL tries to add the same device again. You can ignore this warning.
  • I have devices in my xorg.conf but still don't get any devices. Your ServerLayout doesn't reference the input devices and your HAL setup is broken. Add Option "AllowEmptyInput" "off" to your ServerLayout or simply reference the InputDevice sections in the ServerLayout. While you're at it, you may also want to configure HAL.
  • My touchpad is slow. Check the logs if the touchpad is added with the evdev driver. If so, modify the fdi file to merge synaptics as input.x11_driver, or add a InputDevice section in your xorg.conf (must be referenced by the ServerLayout).
  • Evdev doesn't support option "XYZ". Add a feature request to X.Org Bug 16699. Bugs with patches get preference.

Thursday, July 10, 2008

Input Device Properties

Another big feature was just pushed to git - input device properties.

You may know about window properties, you may know about RandR output properties. Now we have input device properties too, which are little more than a copy of the above two.

IDP allow you to attach properties to a device. These properties can be of arbitrary type and can be changed without the server having to know their details.
So who uses IDP?
- Drivers: the evdev driver now attaches two properties to enable middle mouse button support at runtime, and to change the middle button timeout. When a client changes such a property, the driver is notified and adjusts accordingly.
- The server: Simon Thum has been working on improved mouse pointer acceleration for a while now [1]. With IDP, the server can attach parameters to the device and use them for smoother acceleration.
- Clients: A client may label the device that is controlled by the dominant hand accordingly, and other clients can utilise this for their interaction methods.

And here's the mandatory "screenshots":

Changing the MB timeout from the default to 500ms.

whot@emu:~$ xinput --list-props "USB Optical Mouse"
Device 'USB Optical Mouse':
Middle Button Emulation: 2
valid values: 0 1 2
Middle Button Timeout: 50
whot@emu:~$ xinput --set-int-prop "USB Optical Mouse" "Middle Button Timeout" 16 500
whot@emu:~$ xinput --list-props "USB Optical Mouse"
Device 'USB Optical Mouse':
Middle Button Emulation: 2
valid values: 0 1 2
Middle Button Timeout: 500


Creating a client-defined property

whot@emu:~$ xinput --set-int-prop "USB Optical Mouse" "foobar" 8 2
whot@emu:~$ xinput --list-props "USB Optical Mouse"
Device 'USB Optical Mouse':
Middle Button Emulation: 2
valid values: 0 1 2
Middle Button Timeout: 500
foobar: 2
[client]

Note the [client] marks this property as created by a client, so you know that changing this property probably won't change anything in the driver/server.

Disclaimer: IDP weren't actually my idea, daniels has been talking about them for a while and I've seen them pop up elsewhere. I merely found the time to implement them.

[1] http://bugs.freedesktop.org/show_bug.cgi?id=8583

Wednesday, July 9, 2008

compiz with mpx support

Part two of my June work for the Uni/CSIRO was to modify compiz to support multiple input devices.

Get it now from git://people.freedesktop.org/~whot/compiz.git, checkout the mpx branch.

The current state: compiz core supports XI2, and the move, resize and annotate plugin support multiple devices. So you can wobble two windows at once if you feel like it - just for extra bling. Likewise, you can resize a window into 4 directions at once (I think so, only tested it with two).

The approach I took was fairly simple: in core, replace some functions (e.g. pushScreenGrab) with a device-specific one (pushDeviceGrab). This was done throughout the whole of compiz, and instead of core events, compiz now listens for XI events. In the plugins, replace the single variables with arrays/lists large enough for each device.

For the move/resize plugins I had to use an additional hack - the window decorator tells compiz over ICCCM that a resize/move operation has started. The ICCCM message doesn't include device ids and doesn't have any free bytes to stuff them in. The solution I found was to simply query all devices and find the one closest to the reported position - with the button 1 down.

In theory, the mpx-aware compiz should also work on a non-XI2 server but I haven't tested it.
The work is not finished with many details missing, but the core is there. I won't be able to continue on it as it was a project written under quite some time pressure and that time is up now.

I encourage you to take it and finish it off, it would be good to see a real window manager supporting XI2. If you have any questions about how to continue, pop me an email.

gnome-device-setup

For the month of June, I was employed by the University of South Australia (through CSIRO) to work on some MPX-related goodies. Today I received the confirmation that I may publish the results. So here is number one.

gnome-device-setup is a simple graphical configuration tool to modify the input device hierarchy.



Usage is simple, drag-and-drop rearranges the devices, apply applies the currently configured hierarchy. Right-click on a master device removes it (instantly).

As a side note, this was the first time I used GTK and after dabbling around with Xlib for 2 years, GTK was soothing my soul...

Get it from

http://people.freedesktop.org/~whot/gnome-device-setup

git://people.freedesktop.org/~whot/gnome-device-setup

As usual, patches are welcome.