Notes on keyboard configuration in X Windows: Keyboard layout, Modifier Key and Compose Key
March 23, 2021 1 Comment
Before I dive into X Windows, I need to mention Miguel Farah’s excellent and comprehensive Web pages on keyboard layouts and standards:
http://www.farah.cl/Keyboardery/
There are umpteen articles, blog and forum posts available on the Web covering keyboard configuration for X Windows, but my notes below may be of help to someone. I briefly cover keyboard layout configuration (non-persistent) from the command line in a pseudo terminal in an X Windows session, and also how to make the configuration persist. I also cover how to configure a ‘Modifier Key‘ and a ‘Compose Key‘, two different things.
1. Changing the layout
Look in the file /usr/share/X11/xkb/rules/xorg.lst to find out what settings are available in X Windows. The file is divided into four sections listing the different keyboard models, layouts, variants and options that X Windows allows:
user $ grep "^! " /usr/share/X11/xkb/rules/xorg.lst
! model
! layout
! variant
! option
For example, the following X Windows German-language keyboard layouts are available in the Linux installation I am using now:
user $ awk '/\!\ layout/{flag=1;next}/\!\ variant/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep German
at German (Austria)
de German
ch German (Switzerland)
And the following variants to those three keyboard layouts are available:
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "at: German"
nodeadkeys at: German (Austria, no dead keys)
sundeadkeys at: German (Austria, with Sun dead keys)
mac at: German (Austria, Macintosh)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "de: German"
deadacute de: German (dead acute)
deadgraveacute de: German (dead grave acute)
nodeadkeys de: German (no dead keys)
T3 de: German (T3)
dvorak de: German (Dvorak)
sundeadkeys de: German (with Sun dead keys)
neo de: German (Neo 2)
mac de: German (Macintosh)
mac_nodeadkeys de: German (Macintosh, no dead keys)
qwerty de: German (QWERTY)
deadtilde de: German (dead tilde)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "ch: German"
legacy ch: German (Switzerland, legacy)
de_nodeadkeys ch: German (Switzerland, no dead keys)
de_sundeadkeys ch: German (Switzerland, with Sun dead keys)
de_mac ch: German (Switzerland, Macintosh)
Let’s say I had a desktop machine with a 104-key Swiss German keyboard. By looking through the list of keyboard models in the models section of the file /usr/share/X11/xkb/rules/xorg.lst
, I think the following model best describes the keyboard:
user $ awk '/\!\ model/{flag=1;next}/\!\ layout/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep 104
pc104 Generic 104-key PC
To inform X Windows of the keyboard’s characteristics I could, for example, enter the following command in an X Windows terminal window, which would apply for that session only:
user $ setxkbmap -model pc104 -layout ch -variant legacy
and/or I could configure X Windows permanently by creating/editing a file /etc/X11/xorg.conf.d/00-keyboard.conf
containing the following:
Section "InputClass" Identifier "system-keyboard" MatchIsKeyboard "on" Option "XkbModel" "pc104" Option "XkbLayout" "ch" Option "XkbVariant" "legacy" EndSection
My laptop has a UK keyboard but, depending where I am, I sometimes connect an external US, Brazilian or Spanish keyboard to it.

Left side of HP UK keyboard

Left side of HP US keyboard

Left side of HP Brazilian keyboard

Left side of HP Iberian Spanish keyboard
To be able to switch the layout to the keyboard I am currently using, the following two methods achieve the same effect in X Windows:
Current session only
user $ setxkbmap -layout gb,us,br,es -model pc105 -option grp:alt_shift_toggle
Persistent
The file /etc/X11/xorg.conf.d/00-keyboard.conf
contains:
Section "InputClass" Identifier "system-keyboard" MatchIsKeyboard "on" Option "XkbLayout" "gb,us,br,es" Option "XkbModel" "pc105" Option "XkbOptions" "grp:alt_shift_toggle" EndSection
Either of the above methods will enable me to toggle between UK, US, Brazilian and Iberian Spanish keyboard layouts in X Windows by pressing Alt+Shft. If the laptop had, say, a Brazilian keyboard instead of a UK keyboard then I could change the order of the layouts to ‘br,gb,us,es
‘ or whatever order I prefer.
In fact, even when an external keyboard is not connected to my laptop I select the layout using Alt+Shft if I want to type in English, Portuguese or Spanish. For example, to type ‘ã‘ (the letter ‘a‘ with a tilde accent) I press Alt+Shft to switch to the Brazilian Portuguese layout then press the '
(apostrophe) key followed by the A key on the laptop’s UK keyboard. Transparent key-cap stickers can be purchased for various language layouts so that users can see which keys on the keyboard correspond to keys in another layout. However I don’t bother with key-cap stickers because I can remember the layouts for the few languages I use.
2. Using a Modifier Key and/or a Compose Key
If you do not connect external keyboards with different layouts, or you want to be able to type letters with accents – or type different symbols – that are not on the keyboard, a Modifier Key and/or a Compose Key can be used. These are two different things. You might use a Modifier Key to add an accent to a letter, for example. If you were to configure, say, AltGr as the Modifier Key, pressing AltGr and the ` (grave accent) key simultaneously then releasing them and pressing the A key could – depending on which keyboard layout you are using – result in à (‘a‘ with the grave accent) being displayed. The ` (grave accent) key is a ‘dead key’ in this case because it is not displayed by itself when pressed in conjunction with the AltGr key; it is only displayed when the next key is pressed, i.e. à, not `a, is displayed on the screen.
You might use a Compose Key to display a symbol that is not on the keyboard. If you were to configure, say, the Pause key as the Compose Key, pressing and releasing the Pause key, then the O key and then the C key could – depending on which keyboard layout you have specified – result in the © (copyright) symbol being displayed.
Let’s say that you want a US keyboard layout with AltGr dead keys, and the Windows key as the Compose key. The setxkbmap
command would be:
user $ setxkbmap -layout us -variant altgr-intl -option compose:lwin
Alternatively, the file /etc/X11/xorg.conf.d/00-keyboard.conf
to make that configuration permanent would contain:
Section "InputClass" Identifier "keyboard" MatchIsKeyboard "yes" Option "XkbModel" "pc105" Option "XkbLayout" "us" Option "XkbVariant" "altgr-intl" Option "XkbOptions" "compose:lwin" EndSection
However, the problem with specifying the Windows key as the Compose Key is that the Windows key is usually the key that makes a desktop environment display the applications menu, so an alternative Compose Key needs to be chosen.
You can play around with the XkbModel
, XkbLayout
, XkbVariant
and XkbOptions
options to see what works. Look in the file /usr/share/X11/xkb/rules/xorg.lst
to find out what are permissible/available.
Using the example of a generic US International keyboard layout with AltGr dead keys, let’s check what options for the model, layout, variant, option and Compose Key are available:
model
user $ awk '/\!\ model/{flag=1;next}/\!\ layout/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep Generic
pc101 Generic 101-key PC
pc102 Generic 102-key PC
pc104 Generic 104-key PC
pc104alt Generic 104-key PC with L-shaped Enter key
pc105 Generic 105-key PC
layout
user $ awk '/\!\ layout/{flag=1;next}/\!\ variant/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep "US"
us English (US)
variant
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "us:"
intl us: English (US, intl., with dead keys)
dvorak-intl us: English (Dvorak, intl., with dead keys)
altgr-intl us: English (intl., with AltGr dead keys)
workman-intl us: English (Workman, intl., with dead keys)
option
user $ tac /usr/share/X11/xkb/rules/xorg.lst | awk '/\!\ option/ {exit} 1' | tac | grep ralt
lv3:ralt_switch Right Alt
lv3:ralt_switch_multikey Right Alt; Shift+Right Alt as Compose
lv3:ralt_alt Right Alt never chooses 3rd level
ctrl:rctrl_ralt Right Ctrl as Right Alt
compose:ralt Right Alt
lv5:ralt_switch Right Alt chooses 5th level
lv5:ralt_switch_lock Right Alt chooses 5th level and acts as a one-time lock if pressed with another 5th level chooser
lv5:ralt_switch Right Alt chooses 5th level
lv5:ralt_switch_lock Right Alt chooses 5th level and acts as a one-time lock if pressed with another 5th level chooser
korean:ralt_hangul Make right Alt a Hangul key
korean:ralt_hanja Make right Alt a Hanja key
Compose Key
user $ grep "compose:" /usr/share/X11/xkb/rules/base.lst
compose:ralt Right Alt
compose:lwin Left Win
compose:lwin-altgr 3rd level of Left Win
compose:rwin Right Win
compose:rwin-altgr 3rd level of Right Win
compose:menu Menu
compose:menu-altgr 3rd level of Menu
compose:lctrl Left Ctrl
compose:lctrl-altgr 3rd level of Left Ctrl
compose:rctrl Right Ctrl
compose:rctrl-altgr 3rd level of Right Ctrl
compose:caps Caps Lock
compose:caps-altgr 3rd level of Caps Lock
compose:102 The "<Less/Greater>" key
compose:102-altgr 3rd level of "<Less/Greater>" key
compose:paus Pause
compose:prsc PrtSc
compose:sclk Scroll Lock
(Not all keyboard layouts have a ‘<Less/Greater>’ key, a single key with both < and > symbols on it.)
The following works for me in LXQt with a US keyboard layout:
user $ setxkbmap -layout us -variant altgr-intl -option compose:paus
With the above configuration, I press:
AltGr+a to get á
AltGr+` then a to get à
AltGr+~ then a to get ã
AltGr+e to get é
AltGr+` then e to get è
AltGr+^ then e to get ê
AltGr+~ then e to get ẽ
AltGr+o to get ó
AltGr+n to get ñ
AltGr+c to get ©
AltGr+< to get ç
AltGr+s to get ß
AltGr+? to get ¿
and so on, and I press:
Pause then o then o to get °
Pause then o then c to get ©
Pause then ~ then a to get ã
Pause then ~ then e to get ẽ
Pause then ^ then 2 to get ²
Pause then _ then 2 to get ₂
Pause then 8 then 8 to get ∞
Pause then E then = to get €
Pause then . then . to get …
Pause then – then > to get →
Pause then < then – to get ←
Pause then < then 3 to get ♥
Pause then CCCP to get ☭
and so on. Notice that some characters are available using either method (©, ã and ẽ are three examples shown above). A full list of Compose Key characters can be found in the file /usr/share/X11/locale/<locale>/Compose
in your installation. For the US layout keyboard the list is in the file /usr/share/X11/locale/en_US.UTF-8/Compose
. Various lists of Compose Key sequences and the resulting symbols can also be found on the Web.
To make the configuration in the aforementioned setxkbmap
command permanent I would edit the file /etc/X11/xorg.conf.d/00-keyboard.conf
to contain the following:
Section "InputClass" Identifier "keyboard" MatchIsKeyboard "yes" Option "XkbModel" "pc105" Option "XkbLayout" "us" Option "XkbVariant" "altgr-intl" Option "XkbOptions" "compose:paus" EndSection
Let’s say I want to be able to switch between British (gb
), US (us
), Brazilian (br
) and Iberian Spanish (es
) keyboard layouts by using Alt+Shft on my laptop with a UK keyboard. I could use the command:
user $ setxkbmap -model pc105 -layout gb,us,br,es -variant ,altgr-intl,, -option grp:alt_shift_toggle,compose:paus
The commas in the -variant
option means the ‘altgr-intl
‘ option applies solely to the US layout. The Compose Key option in the -option
options will work for all layouts.
I could make that configuration permanent in /etc/X11/xorg.conf.d/00-keyboard.conf
:
Section "InputClass" Identifier "keyboard" MatchIsKeyboard "yes" Option "XkbModel" "pc105" Option "XkbLayout" "gb,us,br,es" Option "XkbVariant" ",altgr-intl,," Option "XkbOptions" "grp:alt_shift_toggle,compose:paus" EndSection
Note that I would not be able to specify ‘altgr-intl
‘ as a variant for the gb
, br
and es
layouts I use because the variant ‘altgr-intl
‘ is not available in those layouts:
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "gb:"
intl gb: English (UK, intl., with dead keys)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "br:"
nodeadkeys br: Portuguese (Brazil, no dead keys)
user $ awk '/\!\ variant/{flag=1;next}/\!\ option/{flag=0}flag' /usr/share/X11/xkb/rules/xorg.lst | grep dead | grep "es:"
nodeadkeys es: Spanish (no dead keys)
deadtilde es: Spanish (dead tilde)
sundeadkeys es: Spanish (with Sun dead keys)
3. Virtual Terminal (TTY console) keyboard configuration
Although this post is about keyboard configuration for X Windows, I should briefly mention that configurations for X Windows do not apply to virtual terminals (TTY consoles).
If you’re using a Linux distribution running OpenRC, you specify the persistent console keymap in the file /etc/conf.d/keymaps
. You can find out which console keymaps are available by examining the directories under /usr/share/keymaps/
. For example, the following console keymaps are available for US keyboards in Gentoo Linux:
user $ ls /usr/share/keymaps/i386/qwerty/us*
/usr/share/keymaps/i386/qwerty/us-acentos.map.gz
/usr/share/keymaps/i386/qwerty/us.map.gz
/usr/share/keymaps/i386/qwerty/us1.map.gz
so you would be able to specify one of the following in /etc/conf.d/keymaps
:
keymap="us-acentos"
keymap="us"
keymap="us1"
It is also possible to change the console keymap (non-persistent) from the command line. For example, to switch to a UK keyboard layout for a TTY console:
root # loadkeys uk
(notice it is not ‘gb
‘ in the case of TTY consoles), or to switch to an Italian Apple Macintosh keyboard layout for a TTY console:
root # loadkeys mac-it
and so on.
If you’re using a Linux distribution running systemd, see my 2020 blog post ‘Reconfiguring the time zone, locales and keymaps in Sabayon Linux‘ for the commands to list and configure TTY console keymaps. The persistent TTY console keymap is specified in the file /etc/vconsole.conf
, which can be edited directly and is also edited by the ‘localectl set-keymap
‘ command mentioned in that post. The loadkeys
command can also be used as described above to change (non-persistent) the keyboard layout for the TTY console.