Best Way to Remap Caps Lock to Esc with Wayland

Hello! I am using NixOS 23.11 with Gnome, and according to Gnome Settings I’m using Wayland. I also use the Colemak keyboard layout.

By default, the Capslock key with my layout backspaces. I would prefer that it act as an ESC key. I don’t see a way to do this with Gnome keyboard settings. I have also tried the following command:

  • setxkbmap -option caps:escape

But I get an error saying that I’m running setxkbmap against an Xwayland server. Also it simply doesn’t work.

I tried using keyd (couldn’t get it to start due to group errors) and kanata also, but these seem like overkill and have a very large learning curve. All I want to do is remap a single key.

Does anyone know how to do this on a system that isn’t using Xwindows?

I love xremap: GitHub - k0kubun/xremap: Key remapper for X11 and Wayland

> cat .config/xremap/config.yml
modmap:
  - name: CapsLock to RightCtrl/Esc
    remap:
      CapsLock:
        held: Ctrl_R
        alone: Esc
        alone_timeout: 500

keymap:
  - name: RightCtrl+hjkl to Arrows
    remap:
      Ctrl_R-h: Left
      Ctrl_R-l: Right
      Ctrl_R-j: Down
      Ctrl_R-k: Up
  - name: RightCtrl + Esc to "~ and `"
    remap:
      Ctrl_R-Esc: Grave
      Ctrl_R-S-Esc: S-Grave
      Ctrl_R-Grave: Grave
      Ctrl_R-S-Grave: S-Grave
1 Like

Kanata is cross platform, and can do this and much more stuff (in particular, most similar linux tools don’t support chording (mapping simultaneous keypresses — for instance, I have mapped qw to esc))

1 Like

In GNOME, you should use xkb-options setting from the org.gnome.desktop.input-sources GSettings schema.

See Strange xkbOptions behavior (GNOME) - #5 by jtojnar for an example how to set GSettings keys directly in a dconf database using NixOS option.

You can also set the value in the xserver config, since that is needed if you want to apply it to TTY with console.useXkbConfig, and then refer to it within the dconf definitions similarly to how it is done here Setting caps lock as ctrl not working - #5 by jtojnar

1 Like

Kanata does look very cool. I am definitely putting it on my list of things to dive into when I have some more time.

Slightly different, since this does escape on tap and control on chord, but you might like it. This should be layout-neutral.

services.interception-tools =
  let
    itools = pkgs.interception-tools;
    itools-caps = pkgs.interception-tools-plugins.caps2esc;
  in
  {
    enable = true;
    plugins = [ itools-caps ];
    # requires explicit paths: https://github.com/NixOS/nixpkgs/issues/126681
    udevmonConfig = pkgs.lib.mkDefault ''
      - JOB: "${itools}/bin/intercept -g $DEVNODE | ${itools-caps}/bin/caps2esc -m 1 | ${itools}/bin/uinput -d $DEVNODE"
        DEVICE:
          EVENTS:
            EV_KEY: [KEY_CAPSLOCK, KEY_ESC]
    '';
  };

I set -m 1 here which only remaps caps lock, but there are a few different modes..

1 Like

I used tools like setxkbmap in the past. They’re clunky and not always work, as they alter X11 events. I recommend Kmonad which alters kernel input events. It is much more configurable, supporting afaict arbitrary configurations, and is cross platform.

1 Like

That’s exactly why I recommend kanata! It very much feels like a spiritual successor to kmonad, which lacks some important features I’m interested in.

I was able to get Kanata to work! Here’s how I did it.

First, I added the following to my configuration.nix file:

environment.systemPackages = with pkgs; [
  ...
  kanata
  ...
];
  services.kanata = {
    enable = true;
    keyboards = {
      "logi".config = ''
(defsrc
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    e    r    t    y    u    i    o    p    [    ]    \
  caps a    s    d    f    g    h    j    k    l    ;    '    ret
  lsft z    x    c    v    b    n    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)

(deflayer colemak
  grv  1    2    3    4    5    6    7    8    9    0    -    =    bspc
  tab  q    w    f    p    g    j    l    u    y    ;    [    ]    \
  esc  a    r    s    t    d    h    n    e    i    o    '    ret
  lsft z    x    c    v    b    k    m    ,    .    /    rsft
  lctl lmet lalt           spc            ralt rmet rctl
)
  '';
    };
  };

Logi is just an arbitrary name that I’m using since I have a Logitech keyboard.

I then ran sudo nixos-rebuild switch and now I’m able to remap my caps lock key as esc!

Here’s a few notes:

  • The colemak deflayer isn’t a true colemak keyboard. The only difference is that I replaced the caps key with esc.
  • Of course this didn’t work the first time :slight_smile: . I had a typo and nothing seemed to change on my keyboard after running nixos-rebuild. The good news is that the log file (that I could see with sudo journalctl -fu kanata-logi.service) did a good job telling me where the typo was.
  • I had to use the gnome keyboard switcher to switch to a US QWERTY layout first to make this work.

Thanks again for the suggestions and the help!

2 Likes

Yeah, one feature I miss from kmonad is config checking before the unit was actually restarted.