Sway keysym

Article ID: 21

Under the Sway Wayland compositor, we could set set xkb_layout and xkb_options for keyboards in order to do weird key mapping related things. Many people use caps:ctrl_modifier and caps:escape in xkb_options (see xkeyboard-config(7) for other options) to make Caps Lock function as an extra Ctrl or Esc key.

If all you want to do is do a relatively common modification like that, chances are that xkb_variant and xkb_options already has what you want, and you should just set that.


But if what you want isn't covered in the standard XKB files, hear my story. I personally wanted Caps Lock to function as an additional Shift key, which isn't covered in xkb_options. (caps:shift doesn't differ much from normal Caps Lock, make it confusingly documented and doesn't make the Caps Lock function as an extra Shift.)

On X11, I would simply use xmodmap -e "keysym Caps_Lock = Shift_L". Now my Caps Lock functions as an extra Left Shift. Works just alright.

But now that I switched to Wayland, Sway in particular, xmodmap for X11 isn't going to work. What I ended up doing was the following:

$HOME/.xkb/symbols/gbcustom

default partial alphanumeric_keys
xkb_symbols "basic" { // leave "basic" in-tact unless you know what you're doing
    include "gb" // or whatever base layout you use, most likely "us"
    name[Group1] = "English (UK) Customized";
    key <CAPS> { [ Shift_L, Shift_L, Shift_L, Shift_L ] };
};

Note that here, the "key" lines are in the form key <X> { [ A, B, C, D ] } ;, where "X" is the keycode symbolic name of the physical key you want to press. In my case, it is CAPS. Check /usr/share/X11/xkb/symbols/pc and /usr/share/X11/xkb/symbols/latin, or the relevant files for your keyboard configuration, to look up the keycode symbolic name from the name you're used to. (Looking up Shift_L in symbols/pc gets you to LFSH, which is what you would use in place of "X". A is triggered when X is pressed alone, B when it's pressd with Shift, C with AltGr, and D with both AltGr and Shift.

$HOME/.config/sway/config

input "1:1:AT_Translated_Set_2_keyboard" {
    xkb_layout "gbcustom"
}

Of course, replace "1:1:AT_Translated_Set_2_keyboard" with your actual keyboard identifier listed in swaymsg -t get_inputs. And reload Sway.

There might be better ways to do so, but I've got this to work. For these unusual setups, it is a bit complicated and not as straightforward as adding a xmondmap line to .xinitrc. Hopefully things would get better as Wayland matures.

This GitHub issue and jman's article on this were extremely helpful. Thanks to brocellous for pointing out the solution involving custom options.


Another, potentially better method involving defining custom xkb_options, propsed by brocellous:

$HOME/.xkb/symbols/customsymbol

// Remap caps to Shift_L
partial modifier_keys
xkb_symbols "caps_lshift" {
    replace key  {
        type[group1] = "ONE_LEVEL",
        symbols[group1] = [ Shift_L ],
        actions[group1] = [ SetMods(modifiers=Shift) ]
    };
};

$HOME/.xkb/rules/evdev

! option = symbols
  custom:caps_lshift = +customsymbol(caps_lshift)

! include %S/evdev

$HOME/.config/sway/config

input "1:1:AT_Translated_Set_2_keyboard" {
    xkb_layout "gb"
    xkb_options "custom:caps_lshift"
}