Ubuntu – Reassigning modifier keys with xkb

keyboardkeyboard-layoutshortcut-keysxkbxorg

does somebody have good instructions for how the modifier keys can be changed in xkb (via placing the modified xkb file in /usr/share/X11/xkb).

To explain: I'm able to make the layout I want in xmodmap. This is the standard US layout (for laptops), but with the modifier keys swapped round (the usual ctrl vs. capslock; alt vs. windows etc, see below). However, when I output this layout with xkbcomp the resulting keyboard layout seems to be incomplete (and has errors too): I.e. rebooting and reloading that layout isn't the same as running xmodmap again. Not sure why that is – but I reckon the simplest might be just writing this from scratch for xkb (rather than going via xmodmap -> xkb).

So – does anybody have clear instructions on how you can reassign the modifier keys in an xkb file? I basically want to take the US layout, and do the following swaps:

  • capslock –> hyper
  • (shift)
  • ctrl –> super
  • (fn)
  • windows –> alt/meta
  • alt –> control
  • (space)
  • altgr –> control
  • ctrl –> hyper
  • (arrow left)

In this list, the first label is meant to be the physical key on the laptop (going anti-clockwise from capslock towards the arrow keys); unmodified keys shown in (…); the second label is the desired function.

What I'd like to produce is the actual xkb file (i.e. US + those modifiers), that I can then place in /usr/share/X11/xkb and link from /usr/share/X11/xkb/rules/evdev.xml, so that I can simply swap to this layout when needed.

(The reason I want to do this in xkb and not in xmodmap is because xkb can deal with different layouts in different windows, and I've not found a way of doing that with xmodmap, which always seems to be systems wide.)

PS. In xmodmap this would be:

clear control
clear lock
clear mod1
clear mod2
clear mod3
clear mod4
clear mod5

! 66/CapsLk
! Shift
! 37/Ctrl - Fn - 133/Win - 64/Alt - Space - 108/AltGr - 105/Ctrl

keycode  66 = Hyper_L Hyper_L Hyper_L Hyper_L
keycode  37 = Super_L Super_L Super_L Super_L
keycode 133 = Alt_L Alt_L Alt_L Alt_L
keycode  64 = Control_L Control_L Control_L Control_L
keycode 108 = Control_R Control_R Control_R Control_R
keycode 105 = Hyper_R Hyper_R Hyper_R Hyper_R

add control = Control_L Control_R
add mod1 = Alt_R Alt_L
add mod2 = Num_Lock
add mod3 = Hyper_L Hyper_R
add mod4 = Super_L

So how do I achieve the same in xkb?

PPS. I am also confused about Alt vs. Meta – could somebody explain the significance wrt. xkb? (Or Ubuntu in general?) I had assumed that alt=meta (in emacs) but there seems to be a difference. What is it?

Edit. Having looked into this some more, I assume my xkb file (to go into /usr/share/X11/xkb/symbols) would look something like this:

partial alphanumeric_keys modifier_keys
xkb_symbols "basic" {

    include "us(basic)"
    name[Group1]= "enHT (English, US, Hyper-Terminal)";

    key <CAPS> { [ Hyper_L, Hyper_L ] };
// Map Ctrl to the left Alt key, Alt to the left Win key,
// and Super to the left Ctrl key.
    replace key <LALT> { [ Control_L, Control_L ] };
    replace key <LWIN> { [ Alt_L, Meta_L ] };
    replace key <LCTL> { [ Super_L ] };
    modifier_map Mod1    { <LWIN> };
    modifier_map Mod4    { <LCTL> };
    modifier_map Mod5    { <CAPS> };
    modifier_map Control { <LALT> };

};

However, the instructions in the file dont seem to work (even regarding the general US keyboard layout included). So probably something basic is wrong.

Best Answer

The answer provided in the Edit. section above is correct. If saved to /usr/share/X11/xkb/symbols under somename, setxkbmap somename will work correctly. I've written up the information here https://github.com/bjohas/Ubuntu-keyboard-map-like-OS-X and included key maps for xmodmap and xkb.

Here's why it wasn't clear to me that the maps worked:

Any insights on those follow-up questions would be appreciated!