Monday, August 27, 2012

Xmodmap: a quick guide

If you use a variety of Linux/Unix machines and are confused between their different keyboard layouts, it might help to learn the xmodmap utility.

Xmodmap allows you to read the keyboard and mouse pointer bindings and to set them. You don't need root permission, and you can modify these without restarting the X session. This is very useful if you use different keyboards, or want to use the CAPS LOCK key for something useful.

The easiest way to use the xmodmap command is to print out its current config. Run
$ xmodmap -pke

This prints out all the keycodes that are assigned. Here is a sample line:
keycode  24 = q Q U094C U0914

This says that 
  1. Keyboard code 24 corresponds to the 'q' key. Pressing the key by itself without any modifiers produces the 'q' key.
  2. If you hold shift while pressing it, it produces the 'Q' key.
  3. If you hold the mode_switch key while pressing it, it produces the Unicode 094C character (in hex)
  4. With the mode_switch and the shift, it produces the Unicode 0914 character (in hex).
The mode_switch key is used on non-US keyboards to produce non-English text. If you don't know what it is, you don't need it.

But you do use the shift key. How do you know which key that is? Run:
$ xmodmap -pm

That command tells you what the modifier keys are. Looking for the 'shift' modifier, you can see that it is mapped to two different keys:
shift       Shift_L (0x32),  Shift_R (0x3e)

They have hex keycodes 0x32 and 0x3e. 0x32 is 32 in hex which is 50 in decimal. If you search for keycode 50 in the output of 'xmodmap -pke', you will see the following line:
keycode  50 = Shift_L ISO_Prev_Group Shift_L ISO_Prev_Group

So that's the left shift key.

All these keys can be remapped. The most common use is to remove a key you do not use, like the CAPS LOCK key. That is the 'lock' modifier. On my keyboard, the lock modifier is:
lock          Caps_Lock(0x42)

It is assigned to the Caps_Lock key. Let's remove this binding. To remove bindings, you can write commands as arguments to xmodmap -e, and you can supply many commands in succession, as follows:
$ xmodmap -e "command1" -e "command2"

To remove the Caps_Lock binding, we will remove the 'lock' modifier from it.
$ xmodmap -e "remove lock = Caps_Lock"

If that didn't produce any output, it was successful. Validate by running "xmodmap -pm" again. Now, the lock line should look like

Now Caps_Lock doesn't produce a shift lock anymore. You can also verify by opening a text window and pressing the caps lock key. It will not do anything.

Now, let us put the key to good use: how about assigning it to control? Run:
$ xmodmap -e "add Control = Caps_Lock"

Great, now your caps lock is an additional control. We can combine these two commands:
$ xmodmap -e "remove lock = Caps_Lock" -e "add Control = Caps_Lock"

Easy remapping, and it works independent of the window manager, the keyboard type, and the version of Linux.

In case you want to find what key code a specific key produces, run the 'xev' program. It tells you in great detail which keystrokes are pressed and released, and also all mouse events.  Here is a sample line:
KeyPress event, serial 36, synthetic NO, window 0x3e00001,
    root 0x15d, subw 0x0, time 1355682, (152,6), root:(783,52),
    state 0x4, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (01) " "
    XmbLookupString gives 1 bytes: (01) " "
    XFilterEvent returns: False

I pressed a key which produces keycode 38. Using this method you can narrow down on an unused key and put it to good use.