Tuesday, June 14, 2011

A man page for xkeyboard-config

Command-line configuration of XKB keyboard maps usually involves setxkbmap:

setxkbmap -layout "foo" -variant "bar" -options "gobble:dygook"

The problem is though that you need to know your layout, your variant, and your options. And they're not always straightforward. What command would you use for a US querty and German Dvorak layout where the Meta key is on the left Windows key and Ctrl is mapped to the Caps Lock key? If you knew the answer [1] without looking it up first you're scaring me. Stay away from children please.

A few days ago Carl Worth asked a few XKB-configuration questions on IRC and amongst other things this led to yet another complaint about the lack of a man page. Which I answered with the usual "feel free to write one". Except that a few hours later I suddenly had the epiphany: we already have all this data - GNOME uses it just fine for its own keyboard configuration panel. A little later some XSL had been beaten into submission enough for me to proudly say that we now have a man page that lists every single option that you can pipe into setxkbmap. xkeyboard-config(7) for president!

This will be available in the next version, scheduled for September 27. Until then, see the git commit here. Fedora users: xkeyboard-config-2.3-2.fc16 and xkeyboard-config-2.3-2.fc15.


[1] setxkbmap -layout "us,de" -variant ",dvorak" \
-option "altwin:left_meta_win,ctrl:nocaps"
Obvious now, isn't it?

Wednesday, June 8, 2011

Using environment git trees

Despite the confusing title, this is not tree-hugger territory ;)

I have two main machines and several test boxes. More often than not, I end up installing a new machine and get new home directory. This is annoying, because I've gotten quite used to my zsh setup, my vim customisations and all the other little tweaks my systems have accumulated over the years.

Somewhen around last year, this really started pissing me off so I set up a git tree for all those configurations, but I have now split that git tree into two trees: one called environment and one called shellenv.

Here's the current list of files in shellenv:

:: whot@barra:~/shellenv (master)> git ls-files
.gitconfig
.screenrc
.ssh/authorized_keys2
.tigrc
.zsh/10-exports
.zsh/20-aliases
.zsh/30-chpwd
.zsh/30-compctl
.zsh/30-keybindings
.zsh/40-xinput-compctl
.zsh/90-prompt
.zsh/func.tmp
.zsh/func/_fedpkg
.zshrc
setup.sh


The list of files in environment includes my mutt setup, my $HOME/scripts directory with all scripts to automate various stuff, my irssi setups, etc. Both repositories have a setup.sh:


#!/bin/bash

pwd=$PWD
filename=`basename $0`
excludes=". .. .git $filename"

for file in `ls -a`; do
skip=0
for exclude in $excludes; do
if test $file = $exclude; then
skip=1
break
fi
done

if test $skip -eq 1; then
continue
fi

if ! test -e "$HOME/$file"; then
echo ln -s "$pwd/$file" "$HOME/$file"
ln -s "$pwd/$file" "$HOME/$file"
elif test -d "$file"; then
echo "$file already exists"
else
echo "$file already exists"
fi
done


All this does is to symlink the target file with the current file (provided if the target does not exist). The script used in my environment tree is a tad more complicated since it takes hostnames into account to populate the various /etc directories as well but you get the gist.

The result of all that? I can install a new test machine, run git clone and ./setup.sh and the machine has my shell environment. I get a new actual machine (or I update any of my local configuration) and I can run git clone or git pull and all my main boxes have the identical setup. Do try this at home.


Note: I know there are a few bugs in the symlink scripts. I always run them the same way though, they work for me and it's not really worth my time right now to try to make them perfect

Friday, June 3, 2011

Linking kernel and X devices

XI2 has made it possible to access any device the X server knows about and get events from those devices. Alas, one piece was missing: short of parsing the Xorg.log file it was so far impossible to link the system devices with kernel device. You had to guess that /dev/input/event3 was your "AT Translated Set 2 keyboard" with the X device ID of 6.

Why would one need this? Some properties of a device are not exported in X. These included for example anything in sysfs.

I've now pushed patches to evdev, synaptics and the wacom driver to export the device node as a simple string property. From this device node, a client can navigate to the matching sysfs dir, get other events out of the kernel or do whatever they like to do.

The property name is "Device Node" and it is a standard char* that contains the device path. The path is set by the driver, so even if you use e.g. auto-dev on synaptics, the value will be filled in correctly. On the downside, if the driver doesn't support it, the property will not be available on a device. If you write clients that require this information, ensure that you can cope with a missing property and remember that several X devices may share the same device node (e.g. wacom).

These patches do not require a new server, though we have added a #define XI_PROP_DEVICE_NODE to the server to make it easier for others to use this property without misspelling it.

Another property that was pushed in the same series was the "Device Product ID" property (#define XI_PROP_PRODUCT_ID once the new server is out). This property contains two unsigned 32-bit values: vendor ID and product ID. Having this information available makes it simpler for X clients to apply configuration based on specific devices. This can come in handy if you e.g. need different acceleration for a set of mice or you simply want to remap buttons on a specific device.
Again, the two values are set by the driver and all the above rules apply.

I may end up writing those patches for mouse and keyboard too but feel free to help me out with it.

The obligatory not-quite-a screenshot:

:: whot@barra:~> xinput list-props "SynPS/2 Synaptics TouchPad"
Device 'SynPS/2 Synaptics TouchPad':
[...]
Device Product ID (252): 2, 7
Device Node (253): "/dev/input/event4"



Update June 7 2011: As Peter pointed out in the comments, the device node is always local to the host the server runs on. It is up to the client to figure out if it runs on the same host.