How to permanently remap caps lock to esc in X11

keyboardxmodmapxorg

I want to remap caps lock to escape in X11 (i.e. pressing the physical caps lock button will be interpreted as esc by applications and esc's behavior will not change). The solution must survive an X restart. xmodmap and setxkbmap are acceptable solutions (as are similar programs). I don't want to deal with a GUI, as I want the solution to be portable and a part of my dotfiles. If I'm missing a better/easier/more obvious solution, please tell me, though do note that I am not using a DE (trying out i3wm).

So far I've tried using xmodmap and setxkbmap with little success.

Here's my attempt at using xmodmap:

# ~/.xinitrc
xmodmap ~/.xmodmap

and

# ~/.xmodmap
remove Lock = Caps_Lock
keysym Caps_Lock = Escape

Running $ xmodmap ~/.xmodmap from the command line works and does what I want. The issue is that this gets reset every time x restarts. That's where I expect the xinitrc to come in–shouldn't it load every time x starts and run the xmodmap command? If the command works, why doesn't it do anything when read from a file?

I've tried a couple of things with setxkbmap, neither of which worked. The two attempts below were in the file at separate times.

# ~/.xinitrc
setxkbmap -option caps:esc     # attempt 1
setxkbmap -option esc:nocaps   # attempt 2

Neither command did anything perceptible from the command line, so I'm assuming that I've got the command wrong. I like the idea of this solution because it's a one-liner and does not require anything in some other file. If only it worked.

Is .xinitrc the wrong file to be using? I know startx is loading from ~/.xinitrc.

I request that possible solutions contain the whole file(s), not just one line (if more than one is required in the file) so I don't mess up some intermediary step. For example, if I need something in .xinitrc and something in .xcapsrebind, please show both files and all of the required contents (I can also handle being told to append something to the end, but if an & or similar may be required, please tell me).

Best Answer

EDIT: As a helpful user has pointed out, my initial solution will not survive an update. His solution in the comments should work. If you prefer to swap Caps Lock and Escape instead, I would recommend adding the following commands from either your .xinitrc or from i3 config:

.xinitrc:

xmodmap -e "clear lock"
xmodmap -e "keycode 9 = Caps_Lock NoSymbol Caps_Lock"
xmodmap -e "keycode 66 = Escape NoSymbol Escape"

i3 config file (typically located at .config/i3/config or at .i3/config)

# swap caps lock and escape
exec_always --no-startup-id xmodmap -e "clear lock"
exec_always --no-startup-id xmodmap -e "keycode 9 = Caps_Lock NoSymbol Caps_Lock"
exec_always --no-startup-id xmodmap -e "keycode 66 = Escape NoSymbol Escape"

I realise this question is quite old, but thought I might add an answer for those of us still trying to figure this out.

After having similar issues with some DEs not loading ~/.xinitrc, I avoided xmodmap altogether, went to /usr/share/X11/xkb/symbols and modified the key=>symbol mapping directly.

To do so, I edited the config file for my keyboard located at /usr/share/X11/xkb/symbols. For most keyboards, this should be the pc file.

After opening the file, I manually switched around Escape and Caps_Lock for their respective keys the result is shown below). As this affects how X maps the hardware to the key Symbol, it should work regardless of whether you're on GNOME or i3 or anything like that.

A snippet of my resulting file is as follows:

default  partial alphanumeric_keys modifier_keys

xkb_symbols "pc105" {

    key <ESC>  {        [ Caps_Lock             ]       };

    // The extra key on many European keyboards:
    key <LSGT> {        [ less, greater, bar, brokenbar ] };

    // The following keys are common to all layouts.
    key <BKSL> {        [ backslash,    bar     ]       };
    key <SPCE> {        [        space          ]       };

    include "srvr_ctrl(fkey2vt)"
    include "pc(editing)"
    include "keypad(x11)"

    key <BKSP> {        [ BackSpace, BackSpace  ]       };

    key  <TAB> {        [ Tab,  ISO_Left_Tab    ]       };
    key <RTRN> {        [ Return                ]       };

    key <CAPS> {        [ Escape                ]       };
    key <NMLK> {        [ Num_Lock              ]       };

    key <LFSH> {        [ Shift_L               ]       };
    key <LCTL> {        [ Control_L             ]       };
    key <LWIN> {        [ Super_L               ]       };

    key <RTSH> {        [ Shift_R               ]       };
    key <RCTL> {        [ Control_R             ]       };
    key <RWIN> {        [ Super_R               ]       };
    key <MENU> {        [ Menu                  ]       };

This worked like a charm for me.

On looking around the related files, I found repeated mentions and partial implementations of some kind of flag used to switch around certain keys, such as swapping Escape and Caps Lock. I assume this is what the Gnome Tweak Tool and setxkbmap use; however, I couldn't figure out how to keep these flags on with i3 window manager. The above solution should work fine.

Hope this fixes the problem!