8

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).

  • 1
    In .xinitrc: setxkbmap -option caps:escape – jasonwryan Apr 29 '15 at 0:57
  • 1
    Running xmodmap in .xinitrc should work. It’s what I do. Maybe map something unusual, to make sure that it’s actually running when you start x? Also, what window manager/desktop environment do you use? KDE periodically “corrects” my keyboard mapping without me telling it to. Maybe check your desktop settings to make sure that nothing is running xmodmap behind your back. – yellowantphil Apr 29 '15 at 4:20
  • jasonwryan: Tried that in both the .xinitrc; didn't work. It did work from the command line! So there's a start. I think yellowantphil is right-- ~/.xinitrc isn't getting run. I'm using i3wm and no DE right now, though the same thing was happening in Pantheon when I tried. As far as I can tell, i3 doesn't mess with the xinitrc or load its own (but I'm a noob, so what do I know?). – ethanmad Apr 30 '15 at 1:09
  • You may as well try to include Option "XkbOptions" "caps:escape" in a X keyboard config file, e.g. /etc/X11/xorg.conf.d/10-keyboard.conf – don_crissti Nov 24 '15 at 15:12
4

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 "clear lock"
xmodmap "keycode 9 = Caps_Lock NoSymbol Caps_Lock"
xmodmap "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!

  • in your i3 config: exec --no-startup-id setxkbmap -layout whatever -variant whatever -option caps:escape – quixotic Feb 26 '18 at 20:35
  • note your changes to the system ...xkb/symbols/pc file will be overwritten the next time xkeyboard-config or xkb-data packages are updated. – quixotic Feb 26 '18 at 20:37
1

Two possibilities:

1) .xinitrc isn't being run - it's used by xinit, startx, and a few other methods for starting up X sessions, but isn't universally supported - you may be using a display manager that doesn't run it. Adding something to .xinitrc such as touch /tmp/xinitrc-was-run can help determine if that's the case.

2) Xorg automatically resets to default settings when no clients are connected - if the .xinitrc finishes before the window manager or anything else starts running, then the xmodmap or setxkbmap changes will be lost.

If there is an XKB option already defined that you want to use, instead of running programs to change the setting every time Xorg starts, you can just tell Xorg to start up with the right settings already. For instance, in order to enable the Ctrl-Alt-Backspace keys to kill my Xserver, I have installed a file named /etc/X11/xorg.conf.d/90-zap.conf which contains:

# This configuration snippet enables the Ctrl-Alt-Backspace server kill key
# 
# To use it, link or copy into /etc/X11/xorg.conf.d/
#
# Note that only the last XkbOptions setting seen for a device will be used,
# so to use multiple options, copy this file and add options into the Option
# string, such as "terminate:ctrl_alt_bksp,ctrl:swapcaps"

Section "InputClass"
    Identifier "keyboard zap by default"
    MatchIsKeyboard "on"

    Option "XKbOptions" "terminate:ctrl_alt_bksp"
EndSection

You can read more about this in the X.Org docs at https://www.x.org/releases/X11R7.7/doc/xorg-docs/input/XKB-Config.html.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.