Xorg Input Hotplugging
From ArchWiki
i18n |
---|
English |
Türkçe |
Rationale
Historically, the X server would be used on terminals, and later, on desktop computers. On those machines the X server would start once, upon when it would configure itself with regards to its rarely changing input and output peripherals: monitors, video cards, keyboards, mice, tablets, touchscreens...
With the advent of mobile computing, a given computer often sees its peripherals changing, while it is running. Obviously, restarting the whole OS is not an option, so the kernel hackers accommodated for this by implementing device hotplugging. Since devices are exposed to userspace as device nodes in /dev, the highly configurable udev was born in lieu of devfs (or manually maintained /dev).
Still, the X server is having issues with this, as it probes devices and opens device files upon startup. If the device was absent on X startup, it will remain unknown to X. If the device file was present at X startup, and the file disappears (e.g the device is disconnected), the file handle is lost, thus the device will remain unknown, even if replugged and the same device node is recreated (which is easy to do with udev). This is also true for gpm, a mouse daemon for VTs.
To overcome this issue, notably with the most widely encountered cases (that is, a laptop user with a touchpad and an external mouse), the kernel emulates a PS/2 mouse with all events coming from any mouse connected to the system. The device file is always present, and resides at /dev/input/mice (or /dev/psaux). This has a number of issues. First, being an emulated PS/2 mouse, the protocol is predefined, and has inherent limitations, overcome by various proprietary extensions, like ImPS/2 and ExplorerPS/2. What's more, events coming from all the mice have to be translated to this protocol, and thus untranslatable events are lost or misunderstood. What's more, it is impossible to have such an emulated device work in absolute coordinates since it would make no sense (as events can come from many devices). Also, relative button events (like for a wheel, where there's no press/release events) have to be a wheel axis in the PS/2 protocol, and you can't have much of them. Furthermore, all mice will have the same settings with regards to speed or button orders as set via e.g xset of xmodmap. This is an issue when you have a laser mouse which just flies across the screen when another one moves like a turtle.
In the end, it doesn't matter for many users out there who just want a mouse with a wheel and three buttons. Yet there is an increasing market of keyboards, mice and other special input devices with various extra buttons. While hardcore users will argue that this is useless and that everybody should use tiling WMs and screw the mouse, it is increasingly useful to perform many common tasks with either the keyboard or the mouse, depending on what you're currently doing.
The solution to enable all those extra buttons is to use the X input event driver (or evdev). Trouble is, this driver must have access to the exact event node matching your device, which resides in /dev/input/event*, and not some funky workaround device emulator sink. So evdev will work, but only if the device is plugged in at X startup, and never unplugged afterwards.
Rather than writing a routine monitoring /dev or listening to kernel events, which would have the additional nasty effect of tying X hotplugging to linux, the X devs decided to leverage the power of the HAL daemon. hald essentially builds a uniform database of the current hardware available on the system (together with any information it can deduce like device type and so on), and updates it live according to kernel events, while re-sensing device files. Now, thanks to the hard work of hald and dbus devs, all that X has to do is connect to hald (this is done via dbus), monitor device (dis)appearance, and take action if the device is relevant to X.
Current XInput status upstream
There's no other way to have real hotplugging. This is indeed what one might relate to XRandR for its display hotplugging ability, and it's called XInput. It is in the process of a huge revamp, first with this hotplug support, and next with MPX (multi-pointer X) in the near future. It is posing a number of problems, because many pieces of software (xmodmap, GTK...) are unaware of how to handle multiple devices, and them disappearing or reappearing.
Current status in Arch
Input hotplugging is enabled in the 1.5.x series of the xorg-server package, which is now included in the extra repo.
Requirements
To use input hotplugging, the xf86-input-evdev package is required. This module handles both keyboard and mouse configuration by default. Other drivers, like "xf86-input-vmmouse" and "xf86-input-synaptics", also contain hotplugging configuration files, which will cause these drivers to be used instead of evdev when your hardware supports them.
Besides installing a supported driver, both dbus and hal have to be running. Add the hal daemon to the DAEMONS array in /etc/rc.conf before anything related to X.Org is started. The hal daemon will load the dbus daemon automatically.
Configuration
Though input devices are hotplugged, especially keyboards need configuration. Currently there is no way to autoconfigure keymaps for hotplugged keyboards. The default keyboard layout has to be configured in a hal .fdi file. The keymap defaults to a standard US keyboard and is configured in "/usr/share/hal/fdi/policy/10osvendor/10-keymap.fdi", a configuration file included in the hal package. As this file is overwritten on every hal upgrade, this file should be copied to /etc/hal/fdi/policy/. Files placed inside this directory will override the files in /usr/share. The things you want to change are "input.xkb.layout" and "input.xkb.variant". Other options are "input.xkb.rules", "input.xkb.model" and "input.xkb.options". These options resemble the options you used to put in xorg.conf.
Other files worth looking at are "10-x11-input.fdi", which configures the default keyboard and mouse driver and "11-x11-synaptics.fdi", which configures your synaptics touchpad in case you have xf86-input-synaptics installed.
Note that hal needs a restart after changing .fdi files, or it will not autodetect any changes. X does not require any restart for this, it will keep listening for signals from hal. Reconfiguring devices that were already added before hal was reconfigured will keep running with the old configuration. To reconfigure these devices, X needs a restart afterall, but removing and adding the devices to the system will also reconfigure them. This is not very useful for laptops with an integrated keyboard or devices that don't support hotplugging (PS/2 mice and keyboards) though.
FAQ/Troubleshooting
I configured my mouse and/or keyboard in xorg.conf, but X will not use it
When input hotplugging is enabled, X will purge any devices setup in xorg.conf that are using the kbd and mouse driver.
After upgrading to xorg-server 1.5.3, X appears to freeze, I can no longer press keys or move my mouse
This is related to the problem above. Install the xf86-input-evdev driver, configure hal to use the kbd/mouse drivers anyways or disable input hotplugging. Later versions of xorg-server have xf86-input-evdev as dependency.
Using the evdev driver kills my arrow keys, printscreen is triggered instead
This is a known bug when your keyboard is setup as a specific model by applications like GNOME or KDE. The most simple solution is upgrading to xf86-input-evdev 2.1.0, which ignores any model settings and forces "evdev" as keyboard model. If you don't want to upgrade for some reason, be sure to set your keyboard model to "Evdev managed keyboard" in the keyboard preferences of your desktop.
Arrow keys don't work in Openbox
Arrow keys won't work in Openbox dialogs (like client-list-combined or client-menu), to workaround that reconfigure openbox:
openbox --reconfigure
It's an upstream bug, hopefully it will be fixed soon.
When I press a key, X thinks I pressed it multiple times
Since xf86-input-evdev 2.1.0, the evdev driver no longer locks the input device. If you have other drivers configured in xorg.conf, multiple keyboard devices will get configured, which means each device will process your input at the same time, resulting in multiple keypresses. X removes devices using the kbd and mouse drivers which are configured in xorg.conf. However, this only works if the "AllowEmptyInput" option is set. This is the default setting in xorg-server-1.5.3-4, but some users have this set to False in xorg.conf. Remove the option to solve this problem.
Modifying hal configuration
Copy the file:
/usr/share/hal/fdi/policy/10osvendor/10-keymap.fdi
to
/etc/hal/fdi/policy/10-keymap.fdi
and edit this copy there as follows (substitute NEW_LAYOUT with your layout, for instance fr):
<merge key="input.xkb.layout" type="string">NEW_LAYOUT</merge>
You can also toggle between layouts by adding a line similar to to the following:
<merge key="input.xkb.options" type="string">grp:TOGGLE</merge>
where TOGGLE might be menu_toggle, alt_shift_toggle, or any of the other recognized toggle switches. You can find a list of possible values in /usr/share/X11/xkb/rules/xorg.lst (options starting with "grp:")
Using setxkbmap
If previously something like the following snippet of the xorg.conf would deliver your keyboard layout (Option "XkbLayout" "<xkb_layout>"):
Section "InputDevice" Identifier "keyboard" Driver "kbd" ... Option "XkbLayout" "<xkb_layout>" EndSection
Then in a terminal test the following command:
setxkbmap <xkb_layout>
With the same layout as previously configured in the xorg.conf, and type some letters to see if it works correctly. A simple trick, instead of editing the policy file is to add a line to your $HOME/.xinitrc like this:
setxkbmap <xkb_layout>
That is, assuming that xinit is being used to start X, it will work nice. You may need to explicitely set the keyboard model to evdev (as in the Gnome/KDE/Openbox examples) by adding:
-model evdev
I don't want this crap, how do I turn it off?
To disable input hotplugging, add Option "AutoAddDevices" "False" to ServerFlags in /etc/X11/xorg.conf:
Section "ServerFlags" Option "AutoAddDevices" "False" Option "AllowEmptyInput" "False" EndSection
This will skip devices detected by hal and will use your keyboard/mouse configuration from xorg.conf. Remember to install xf86-input-keyboard and xf86-input-mouse, as by default they are not installed. Note, that while this should enable your input devices without requiring a running hal, the default configuration may not be what you expect. In particular you may want to take a look at the section below on the change in default tapping and sliding behaviour if your touch pad is still misbehaving.
My mouse is jerky/uncontrollable in SDL apps/games! WTF?
This was a long time since I started a game. It seems that with evdev, DGA gets broken in SDL: mouse jumps and moves down-right all the time.
To fix this you have to either set a var:
export SDL_VIDEO_X11_DGAMOUSE=0
which is sufficient for Neverball, or add this to your xorg.conf:
Section "Module" ... SubSection "extmod" Option "omit xfree86-dga" # don't initialise the DGA extension EndSubSection ... EndSection
which is mandatory for e.g Doom III
How can I make mouse button XYZ do FOO?
Well, currently it has to be implemented in the application (like e.g firefox next/previous) or in the WM. Configurable WM like compiz can do something with mouse buttons too. The sad thing is that this is per-button number and not per-device. There are also some interesting apps like EvRouter but the kernel event design makes it so that events are not 'consumed' by applications reading /dev/input/event0, thus catching an event won't prevent the event to be passed to X (which will produce a ButtonXYZ event, which results in a LeftClick if not handled specially by the application). Or I missed something somewhere.
Tapping and sliding doesn't work anymore with my touchpad!
Assuming you have configured X to use the synaptics driver, you have to explicitly tell it to enable the tapping functions. It wasn't necessary before: this is a change in the synaptics driver - which is now an officially xorg supported driver - and is not directly related to input hotplugging: see Touchpad Synaptics.
If you choose to disable hotplugging, you need to modify xorg.conf.
If on the contrary you use hotplugging, remove every eventual synaptic related configuration from your xorg.conf (usually the InputDevice "SynapticsTouchpad" line and relative Section "InputDevice" section), copy /usr/share/hal/fdi/policy/10osvendor/11-x11-synaptics.fdi to /etc/hal/fdi/policy/10osvendor/11-x11-synaptics.fdi and edit it. See http://bbs.archlinux.org/viewtopic.php?pid=456689#p456689 for a sample configuration that works. If this post does not work, try this one: http://bbs.archlinux.org/viewtopic.php?pid=456488#p456488
How can I check if I'm using the evdev driver?
First, you can check if hal found the evdev device. On the command line, one can run something like:
hal-device|grep -B 15 input.x11.driver
and check your mouse and/or keyboard is listed. For example:
50: udi = '/org/freedesktop/Hal/devices/usb_device_461_4d15_noserial_if0_logicaldev_input' linux.sysfs_path = '/sys/class/input/input1/event1' (string) info.subsystem = 'input' (string) info.parent = '/org/freedesktop/Hal/devices/usb_device_461_4d15_noserial_if0' (string) info.product = 'USB Optical Mouse' (string) info.category = 'input' (string) info.udi = '/org/freedesktop/Hal/devices/usb_device_461_4d15_noserial_if0_logicaldev_input' (string) info.capabilities = { 'input', 'input.mouse' } (string list) linux.hotplug_type = 2 (0x2) (int) linux.subsystem = 'input' (string) input.device = '/dev/input/event1' (string) linux.device_file = '/dev/input/event1' (string) input.product = 'USB Optical Mouse' (string) input.x11_driver = 'evdev' (string) input.originating_device = '/org/freedesktop/Hal/devices/usb_device_461_4d15_noserial_if0' (string)
and you can look for config/hal in /var/log/Xorg.0.log xorg log file to look for evdev device configuration.
(II) config/hal: Adding input device USB Optical Mouse (**) USB Optical Mouse: always reports core events (**) USB Optical Mouse: Device: "/dev/input/event1" (II) USB Optical Mouse: Found x and y relative axes (II) USB Optical Mouse: Found mouse buttons (II) USB Optical Mouse: Configuring as mouse (II) XINPUT: Adding extended input device "USB Optical Mouse" (type: MOUSE)