Spotlight on: XModMap
XModMap is a tool for modifying keyboardlayouts.
From time to time you want to type letters which are not available on your keyboard. A common way to solve this issue is to use applications like gucharmap. Far easier would be to directly be able to type them, therefore I’m going to introduce XModMap to you.
I. Some theory
First of all the get the list of all modifiers (special keys which are only useful in combination with other keys like Ctrl, Alt or Shift & Co.):
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap -pm
[/codesyntax]
The output will be similar to the following
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap: up to 4 keys per modifier, (keycodes in parentheses): shift Shift_L (0x32), Shift_R (0x3e) lock Caps_Lock (0x42) control Control_L (0x25), Control_R (0x69) mod1 Alt_L (0x40), Meta_L (0xcd) mod2 Num_Lock (0x4d) mod3 mod4 Multi_key (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf) mod5 ISO_Level3_Shift (0x5c), Mode_switch (0xcb)
[/codesyntax]
A keyboard has four levels
- level 1 is reached by simply the pressing the key
- level 2 is reached by pressing the key + shift
- level 3 is reached by pressing the key + ISO_Level3_Shift (normally AltGr)
- level 4 is reached by pressing the key + Shift + ISO_Level3_Shift
by default levels 5 ’till 8 are not reachable, so I’m (mostly) going to ignore them, for more infos on that, read this.
That makes the output of xmodmap self-explaining.
- first column: the key on the keyboard
- second column: symbol on level 1
- third column: symbol on level 2
- fourth column: symbol on level 3
- fifth column: symbol on level 4
logically not all levels must be set.
Next get our current configuration
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap -pke
[/codesyntax]
here’s a snippet of mine
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
keycode 19 = 0 equal 0 equal braceright degree braceright keycode 20 = ssharp question backslash U1E9E backslash U1E9E keycode 21 = dead_acute dead_grave dead_acute dead_grave dead_cedilla dead_ogonek dead_cedilla keycode 22 = BackSpace NoSymbol BackSpace NoSymbol BackSpace keycode 23 = Tab ISO_Left_Tab Tab ISO_Left_Tab Tab ISO_Left_Tab keycode 24 = q Q q Q at Greek_OMEGA at keycode 25 = w W w W lstroke Lstroke lstroke Lstroke
[/codesyntax]
in the first column you’ll find the key, in the others it’s setup: it’s either a keycode (decimal, eg: keycode 25), a keysym-name (alpha, eg: keysym w) or a keysym (hexadecimal, eg: keysym 0×0077). A full list of them can be found either locally in /usr/include/X11/keysymdef.h or online.
Configuration can be either made temporarly or permanent. In the first example we want the key “e” to print “€” on the third and “ε” on the fourth level.
temporary
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap -e "keysym e = e E EuroSign Greek_epsilon EuroSign Greek_epsilon"
[/codesyntax]
(As I said levels 5 – 8 aren’t supported by default, but my keyboard doesn’t respond to 3 and 4, but to 5 and 6, so those are copies of the former)
permanent
put the command without “xmodmap -e” into $HOME/.Xmodmap
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
keysym e = e E Eurosign Greek_epsilon Eurosign Greek_epsilon
[/codesyntax]
the file can be loaded via
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap $HOME/.Xmodmap
[/codesyntax]
GNOME for example will search for that file on session startup and if found ask you wether to use it.
But now to some more practically relevant examples.
II. capital sharp-s (ẞ)
Compared to the english alphahbet, the german got four letters more: ä ö ü and ß. For the first free there are also capital ones Ä Ö Ü, but not for the ß, that is because it can never begin a word. This leads to a phonetic disaster: when you write the word groß (big) in capital letters it becomes GROSS. But: ß is pronounced like sz, not like ss, therefore the word would be spoken different (if we wouldn’t know that SS means ß). There have been approaches for the capital ß to become part of the german alphabet in the early 20th century, with no luck.
Well… in 2008 the ẞ became part of the unicode standard and all modern systems shipp fonts which are able to display it. Therefore we can finally write GROẞ instead of GROSS.
Now setup ẞ as level 4 on the ß-key
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap -e "keysym ssharp = ssharp question backslash U1E9E backslash U1E9E"
[/codesyntax]
That’s it!
III. Multi_key
The Multi_key –also known as Compose– is a special modifier which composes characters by special keystrokes. For example if you use an english layout but want to be able to type german or scandinavik letters you would do
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
Multi_key + " + a = ä Multi_key + a + e = æ
[/codesyntax]
In our example we set the left Window-Logo-Key as Multi_key
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap -e "keysym Super_L = Multi_key"
[/codesyntax]
Here you can find a list of all possible combinations.
IV. Pointer_EnableKeys
To be able to move the pointer with the keyboard, several windowmanagers allow that by using the numpad, then the Num_Lock is off. This has one major drawback: you want be able to use them as Pos1, PageUp and so on. By using XModMap you get the option of using Pointer_EnableKeys, which works like that:
- Num_Lock on: keys produce 1 2 3 4…
- Num_Lock off: keys produce End Down PageDown Left…
- Num_Lock + Shift: keys move the pointer
- Num_Lock + Shift (again): keys work normally again
set it up
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap -e "keysym Num_Lock = Num_Lock Pointer_EnableKeys"
[/codesyntax]
V. More stuff
We can use /usr/include/X11/keysymdef.h to access practically every character available. In the example we bind club (the cross on playing cards) as third and fourth level “c”. Checking the include file we find
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
#define XK_club 0x0aec /* U+2663 BLACK CLUB SUIT */
[/codesyntax]
As you can see we get the keysym-name (club, XK_ stripped off) and the keysym (0x0aec), though I recommend using keysym-names as they’re much more intuitive.
[codesyntax lang="bash" lines="fancy" lines_start="0" container="none" tab_width="8"]
xmodmap -e "keysym c = c C club club club club"
[/codesyntax]
Now pressing third or fourth level “c” results in “♣”. You’ll no longer need gucharmap & Co.
Have Fun!
The german version of this article has been released on ProLinux.