Linux keymap hacking

I recently ran Debian GNU/Linux on a Macbook. Some aspects of its keyboard layout are a bit annoying, so I decided to “fix” them.

xmodmap is obsolete

This used to be the recommended way of modifying keymaps for Linux desktops, but it’s now deprecated, and doesn’t work in Wayland. Unfortunately, its former popularity makes it harder to find documentation about xkb.

xkb

AIUI xkb is not a replacement for xmodmap, but a lower-level way of managing keymaps. It is forwards compatible with Wayland, despite beginning with ‘x’. How to edit the config depends largely on what you’re trying to do, so it’s easiest to describe that first before showing what I did.

Remap right cmd to ctrl

OS X mostly uses the cmd keys instead of ctrl, so my Macbook is only supplied with one ctrl key (on the left), whereas Linux has almost no use for the cmd keys, so it’s helpful to remap right cmd to right ctrl.

Swap # and £ (UK version)

On UK Mac keyboards £ is shift-3 and # is right-alt-3. As a programmer and hacker I use # much more than £ so it was a nuisance having # in such an awkward place, so I decided to swap them. In OS X this can be done by selecting US layout, but doing that in Linux makes some undesirable changes too.

Shift-capslock

Not Mac-specific, but I like to have Capslock only work if I press shift at the same time, to guard against hitting it by accident, especially on my main PC’s keyboard, where the LED is stupidly (I’m looking at you, Ducky) obscured behind other keys.

Creating the mappings

I created /usr/share/X11/xkb/symbols/macbook for the two Mac-specific settings, containing:

partial alphanumeric_keys
xkb_symbols "pound" {
  // Put sterling on RAlt-3 and numbersign on Shift-3.
  key { [ 3, numbersign, sterling ] };
};

// Make right cmd key act as ctrl
partial modifier_keys
xkb_symbols "rcmdctrl" {
  key { [ Control_R ] };
  modifier_map Control { , };
  modifier_map Mod4 { };
};

and /usr/share/X11/xkb/symbols/shiftcaps for shift-capslock:

xkb_symbols "shiftcaps" {
  key  {
    type[Group1] = "TWO_LEVEL",
    symbols[Group1] = [ VoidSymbol, Caps_Lock ],
    actions[Group1] = [ NoAction(), LockMods(modifiers=Lock) ]
  };
};

Enabling the mappings as options

To make these mappings available as options I edited /usr/share/X11/xkb/rules/evdev, found the line

! option        =       symbols

and added:

  macbook:pound         =       +macbook(pound)
  macbook:rcmdctrl      =       +macbook(rcmdctrl)
  shiftcaps:shiftcaps   =       +shiftcaps(shiftcaps)

below it.

Similarly, to make these options available in GNOME 3 (via the ‘Typing’ section of gnome-tweak-tool), I edited /usr/share/X11/xkb/rules/evdev.xml, adding the following groups to its <optionList> section:

    <group allowMultipleSelection="true">
      <configItem>
        <name>macbook</name>
        <description>Macbook customisations</description>
      </configItem>
      <option>
        <configItem>
          <name>macbook:pound</name>
          <description>Hash on Shift-3, Sterling on AltGr-3</description>
        </configItem>
      </option>
      <option>
        <configItem>
          <name>macbook:rcmdctrl</name>
          <description>Right Cmd key acts as Ctrl</description>
        </configItem>
      </option>
    </group>
    <group allowMultipleSelection="false">
      <configItem>
        <name>shiftcaps</name>
        <description>Caps Lock with Shift</description>
      </configItem>
      <option>
        <configItem>
          <name>shiftcaps:shiftcaps</name>
          <description>Caps Lock requires Shift to toggle</description>
        </configItem>
      </option>
    </group>

Guarding against system upgrades

The evdev files may get overwritten by system upgrades, so I wrote a script to add my changes automatically.

See also

I worked most of this out by asking questions on StackExchange.

Linux console

I’ve forgotten exactly what I did, but what I do remember is that I used dumpkeys to show the existing keymap, saved it to a file and edited in my customisations, then set up a systemd service to load the map with loadkeys.

Leave a Reply