The web site of Vas — 2020-03-29

Custom keyboard layout with xkb and ibus (the poor man’s QMK)

This guide will help you create a custom keyboard layout in xkb and configure ibus to play along nicely. Effectively you can configure any key on your keyboard to do anything you want, for example output curly quotes, em dashes, and mathematical symbols or to use something besides QWERTY. After forcing ibus to cooperate, you can retain your layout even in your input method editor, for example to write Chinese or Japanese using Dvorak. This is also for my personal reference because documentation on this subject is scarce at best. It works for X11 (GTK, Qt, xterm, whatever). I don’t know about Wayland.

The xkb layout

Layouts are in /usr/share/X11/xkb/symbols. It’s best to start with and existing layout. For example the basic QWERTY US keyboard layout is defined at the top of the us file and it should look like this:


default partial alphanumeric_keys modifier_keys
xkb_symbols "basic" { name[Group1]= "English (US)";

	key <TLDE> {        [     grave,    asciitilde      ]       };
	key <AE01> {        [         1,    exclam          ]       };
	key <AE02> {        [         2,    at              ]       };
	key <AE03> {        [         3,    numbersign      ]       };
	key <AE04> {        [         4,    dollar          ]       };
	key <AE05> {        [         5,    percent         ]       };
	key <AE06> {        [         6,    asciicircum     ]       };
	key <AE07> {        [         7,    ampersand       ]       };
	key <AE08> {        [         8,    asterisk        ]       };
	key <AE09> {        [         9,    parenleft       ]       };
	key <AE10> {        [         0,    parenright      ]       };
	key <AE11> {        [     minus,    underscore      ]       };
	key <AE12> {        [     equal,    plus            ]       };

	key <AD01> {        [         q,    Q               ]       };
	key <AD02> {        [         w,    W               ]       };
	key <AD03> {        [         e,    E               ]       };
	key <AD04> {        [         r,    R               ]       };
	key <AD05> {        [         t,    T               ]       };
	key <AD06> {        [         y,    Y               ]       };
	key <AD07> {        [         u,    U               ]       };
	key <AD08> {        [         i,    I               ]       };
	key <AD09> {        [         o,    O               ]       };
	key <AD10> {        [         p,    P               ]       };
	key <AD11> {        [ bracketleft,  braceleft       ]       };
	key <AD12> {        [ bracketright, braceright      ]       };

	key <AC01> {        [         a,    A               ]       };
	key <AC02> {        [         s,    S               ]       };
	key <AC03> {        [         d,    D               ]       };
	key <AC04> {        [         f,    F               ]       };
	key <AC05> {        [         g,    G               ]       };
	key <AC06> {        [         h,    H               ]       };
	key <AC07> {        [         j,    J               ]       };
	key <AC08> {        [         k,    K               ]       };
	key <AC09> {        [         l,    L               ]       };
	key <AC10> {        [ semicolon,    colon           ]       };
	key <AC11> {        [ apostrophe,   quotedbl        ]       };

	key <AB01> {        [         z,    Z               ]       };
	key <AB02> {        [         x,    X               ]       };
	key <AB03> {        [         c,    C               ]       };
	key <AB04> {        [         v,    V               ]       };
	key <AB05> {        [         b,    B               ]       };
	key <AB06> {        [         n,    N               ]       };
	key <AB07> {        [         m,    M               ]       };
	key <AB08> {        [     comma,    less            ]       };
	key <AB09> {        [    period,    greater         ]       };
	key <AB10> {        [     slash,    question        ]       };

	key <BKSL> {        [ backslash,         bar        ]       };
};

Give your layout an identifiable name, like “English (Paedosexual)”. The format is self-explanatory: there is an identifier for the name of the physical key, followed by and array of characters that define what the X Server sees when the key is pressed. Many characters have names. You can also use Unicode in this format: UXXXX where XXXX is a hexadecimal number. The basic layout has two elements in the array, one for the key by itself, and one for the second layer modifier key (the shift key). You can have two more modifier keys. The total number of layers is 2^N, so with 3 modifier keys, that’s a maximum of 8 characters per key. Modifier keys can also have layers.

You can see my configuration here: https://github.com/vaaas/dotfiles/blob/master/vlatin

I’ve defined right alt as layer 3, and right ctrl as layer 5. Caps lock is XCompose. The second layer of shift key is caps lock, so two shifts together is caps lock. I’ve used the layers to make various characters easier to type, like ellipsis or guillemets. I’ve also placed parentheses where the square brackets are because I use them more often when programming and in Lisp.

Save your layout in your dotfiles and symlink it to the xkb directory. Test the results with setxkbmap filename

ibus

In ibus-setup, on the advanced tab, the top option is Use system keyboard layout. By default, this is off, so ibus will overwrite any xkb / xmodmap configuration you do, or to be exact it will manage your xkb configuration for you. So if you add a Greek layout, when you change to it, ibus will configure your system so that your key presses output Greek letters.

ibus has its own configuration of valid layouts, separate from xkb. Navigate to /usr/share/ibus/component. There’s various XML files for your input engines. I use simple (just xkb) and kkc (for Japanese). Edit a file, for example the simple.xml file. The engines element has one or more engine children. The keyboard layout is defined in layout and it is your filename. You can change an engine or copy-paste and modify it. It’s best to give it an identifiable name.

Kill ibus-daemon and restart it. In ibus-setup, when you go to add a new engine, your custom engine and layout should show up with the names you’ve used for them under the language you’ve specified. Have fun.