Keyboard Layout – Changing Keyboard Layout on Console and X

keyboardkeyboard-layout

I've been able to change the keyboard layout/mapping when the X Window System is running using ~/.Xmodmap (and I suppose you could also do it through the X protocol directly, eg. using libxcb as a wrapper around X protocol calls).

I've been able to do the same (somewhat) on the console/tty (ie. when X is not running) using loadkeys.

Is there a way to customize the keyboard layout similarly, but from a single source, in such a way that it affects both X and the console, ie. in a way that is "X-and-console agnostic"?

(The only way I can think of is by writing a "keyboard driver" that talks to the kernel's input interface, evdev, and sends the input you want (through uinput?), or something, but I don't know if this even makes sense, or if there's an easier way.)

Best Answer

Yes, there is a way, and this is indeed how Debian's console-setup package does it.

  • Keyboard layouts are specified in XKB terms (model, layout, variant, and options) by the administrator in a file named keyboard, usually /etc/default/keyboard. This is the single source. It can be edited with a text editor.
  • The setxkbmap program is given these same XKB settings and configures an X11 server accordingly.
    • The keyboard-configuration package's post-installation maintainer script runs setxkbmap directly, with the /etc/default/keyboard settings, if it finds itself with an X11 display. Thus dpkg-reconfigure keyboard-configuration run from an X11 GUI terminal emulator will affect the X11 keyboard layout.
  • The setupcon script takes these XKB settings, passes them through the ckbcomp utility to generate a keyboard map, and loads that keyboard map into the kernel virtual terminals with loadkeys/kbdcontrol.
    • This script is run at system bootstrap by a service.
    • It can also be run manually elsewhen.

Other systemd operating systems work differently but also have a single source.

  • The XKB layout, variant, and options are stored in in /etc/X11/xorg.conf.d/00-keyboard.conf. This is the single source.
    • This file is directly read by the X11 server at startup and sets the X11 keyboard map directly.
    • This file is parsed by systemd-localed at startup. The file cannot be usefully edited with a text editor whilst systemd-localed is running, because the service will blithely overwrite it with its own in-memory information.
    • To change the XKB information, one runs localectl, which talks to another server which in turn talks to systemd-localed.
  • systemd-localed converts the XKB settings to a virtual terminal keyboard map name using the mappings in /usr/share/systemd/kbd-model-map, which it then writes out to /etc/vconsole.conf. Unlike the Debian system, it does not generate maps on the fly from the XKB information, but selects only pre-supplied static maps listed in the map file.
  • systemd-vconsole-setup runs at bootstrap, reads /etc/vconsole.conf, and loads the keyboard map into the kernel virtual terminals by running loadkeys.

Further reading

Related Question