Custom keyboard layout in X11 and Wayland

This article shows how to make your own keyboard layout under X11 and Wayland. There's many layouts already built in every linux distro, but sometimes you might want to tweak an existing layout or make an entirely new one.

For me, the reason is that I switch between languages a lot and I don't really want to learn multiple layout for each language. My native language is Czech but I want US layout for programming. I also learn Finnish, Norwegian and hopefully Icelandic in the future. You can imagine how many keys there are for each language.

A few years ago I found out that there's a us(cz_sk_de) variant of the US layout. Czech, Slovak and German letters are accessible via right Alt (AltGr). For example: AltGr + a = á, etc.

This is very convenient as you don't have to switch layouts at all and write everything on one keyboard. Later, when I started learning other languages, I needed their regional characters and was lazy to switch layouts, so I tried to find a way to add them to my existing layout.

xkb layouts

All keyboard layouts are located under /usr/share/X11/xkb/symbols. If you look into the us file, there's a section named xkb_symbols "cz_sk_de". Each section describes additional combinations or overrides existing keys.

To get a basic idea about how these symbols are configured, you can read this article.

For overriding certain symbols, you would create a section and include the original layout, like so:

xkb_symbols "cz_sk_de" {
    include "us"
    name[Group1]="Czech Slovak and German (US)";

    // Key definitions go here

    include "level3(ralt_switch)"
}

This includes the original us layout and also enables the right Alt modifier key.

Key definitions also have a pretty straightforward syntax:

key <AC01>  { [         a,          A,     aacute,       Aacute   ] };

This says that key AC01 — the key that is usually under the letter A — will write:

  • a when pressed
  • A when pressed with Shift
  • á when pressed with right Alt
  • Á when pressed with Shift and right Alt at the same time

To get the key number for your configuration, you need two things:

  • /usr/share/X11/xkb/keycodes/evdev lists keys and their keycodes
  • The command xev lets you press a key and lists info about that key

So for example, with the A key: run xev and press a on your keyboard. The output we get is:

KeyPress event, serial 34, synthetic NO, window 0x1400001,
    root 0x538, subw 0x0, time 17855764, (163,-16), root:(1034,467),
    state 0x0, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XmbLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

We're interested in this part: keycode 38. If you open /usr/share/X11/xkb/keycodes/evdev, you can find this line: <AC01> = 38;. So keycode 38 corresponds with key <AC01>. This will help you remap all the keys you want.

Character names like aacute (á) or oslash (ø) can be found either on Wikipedia or on w3.org. If you copy or enter the character into Wikipedia, it lists its name to, for example Wikipedia article for Ø.

For reference I will link the layout I'm currently using: GitHub Gist.

Installation

X11

To set that layout to actually use it, all you have to do is to run setxkbmap "us(cz_sk_de)". It's always in the format <layout>(<variant>). You can put it in your .bashrc or ~/.config/fish/config.fish and also, most importantly in your startup commands in your chosen DE/WM.

Wayland

On Wayland there's a bit more work to be done. I found an article that talks about this issue. To make your layout visible in GNOME you have to edit this file: /usr/share/X11/xkb/rules/evdev.xml.

The article I linked talks about adding a completely new layout, but here I am talking about a new variant of an existing layout. So, to do that, find an existing <layout> section, under which there should be <variantList>.

For my layout I added this:

<variant>
  <configItem>
    <name>cz_sk_de</name>
    <shortDescription>cz_sk_de</shortDescription>
    <description>English (US) with CZ/SK/DE/FI/NO/IS keys</description>
    <languageList>
        <iso639Id>eng</iso639Id>
    </languageList>
  </configItem>
</variant>

Now if you restart gdm (sudo service gdm restart) and go into Region & Language, you should see the new variant under the US layouts.

  • <name> must correspond with the section name in the symbols file.
  • <shortDescription> will be the text you'll see in the keyboard layout switcher in your top bar in GNOME
  • <description> is what will appear in the selection dialog in Region & Language settings menu
  • <languageList> specifies under which languages this variant/layout will appear

And this is it! It took some time to figure everything out, but in the end this can speed up typing and the constant need to switch layouts and remember different layouts.