How do I remap Caps Lock to Hyper Key in Ubuntu 18.04

In Ubuntu 16.04, I used xmodmap to remap the key and saved the script to a .sh file which was called every time Ubuntu was started. However, in Ubuntu 18.04 this doesn't work so well. When Ubuntu is started, it remaps the key as expected however, after suspending and logging in again, the keys are swapped to the original setup.

I've managed to make some progress by editing /usr/share/X11/xkb/symbols/pc as follows:

default  partial alphanumeric_keys modifier_keys
xkb_symbols "pc105" {

    key <ESC>  {    [ Escape        ]   };

    // 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> {  [ Caps_Lock     ]   };
    key <CAPS> {    [ Hyper_L       ]   };
    key <NMLK> {    [ Num_Lock      ]   };

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

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

    // Beginning of modifier mappings.
    modifier_map Shift  { Shift_L, Shift_R };
    //modifier_map Lock   { Caps_Lock };
    modifier_map Control{ Control_L, Control_R };
    modifier_map Mod2   { Num_Lock };
    modifier_map Mod4   { Super_L, Super_R };

So now my Left Shift key acts as Control key and my Left Control key acts as Shift. This is working fine every time I start Ubuntu or login again. But I can't make the Caps key to work as Hyper key. The result I get is that when I press Caps, the Super key is activated and I really don't understand why. Maybe is defined somewhere that Super and Hyper are working together, but I can't find where.


For this to work is also required to change modifiers. This can be done by changing the following parts of /usr/share/X11/xkb/symbols/pc: (the ones marked with comments on the right)

default  partial alphanumeric_keys modifier_keys
xkb_symbols "pc105" {

    key <ESC>  {    [ Escape        ]   };

    // 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> { [ Caps_Lock     ]   };         //remove caps lock mapping
    key <CAPS> {    [ Hyper_L       ]   };         //add Hyper_L mapping
    key <NMLK> {    [ Num_Lock      ]   };

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

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

    // Beginning of modifier mappings.
    modifier_map Shift  { Shift_L, Shift_R };
    //modifier_map Lock   { Caps_Lock };            //remove caps modifier
    modifier_map Control{ Control_L, Control_R };
    modifier_map Mod2   { Num_Lock };
    modifier_map Mod3   { Hyper_L, Hyper_R };      //add modifier for Hyper (Mod3)
    modifier_map Mod4   { Super_L, Super_R };

    // Fake keys for virtual<->real modifiers mapping:
    key <LVL3> {    [ ISO_Level3_Shift  ]   };
    key <MDSW> {    [ Mode_switch       ]   };
    modifier_map Mod5   { <LVL3>, <MDSW> };

    key <ALT>  {    [ NoSymbol, Alt_L   ]   };
    include "altwin(meta_alt)"

    key <META> {    [ NoSymbol, Meta_L  ]   };
    modifier_map Mod1   { <META> };

    key <SUPR> {    [ NoSymbol, Super_L ]   };
    modifier_map Mod4   { <SUPR> };

    key <HYPR> {    [ NoSymbol, Hyper_L ]   };
    modifier_map Mod3   { <HYPR> };                  //set Hyper modifier to Mod3
    // End of modifier mappings.

    key <OUTP> { [ XF86Display ] };
    key <KITG> { [ XF86KbdLightOnOff ] };
    key <KIDN> { [ XF86KbdBrightnessDown ] };
    key <KIUP> { [ XF86KbdBrightnessUp ] };
};

Leave the rest of the file as it is. For this to work you have to logout and login again. It doens't work if you just suspend or lock the screen.


As of a few days ago this is working:

  • Run Ubuntu on Wayland
  • Put this in your .bashrc
setxkbmap -option caps:hyper
setxkbmap -option caps:none