Xmodmap how to remap keys and disable the original ones

keyboardkeyboard shortcutskeyboard-layoutkeymapxmodmap

I'm considering getting a 60% keyboard and want to try out working with that layout before buying the actual keyboard.

I'm trying to map arrow keys to caps lock + ijkl and disable the real arrow keys. I've found out how to remap it, but when I try to disable the real arrow keys, the remapped ones break. Here's a working map:

keycode 66 = Mode_switch
keycode 31 = i I Up
keycode 44 = j J Left
keycode 45 = k K Down
keycode 46 = l L Right

To disable arrow up I add

keycode 111 =

And as soon as I do that, ijkl don't work as characters anymore, but act as arrows even without pressing the modifier(caps lock). How do I disable the arrow keys without breaking my previous mapping?

Best Answer

After reading in and getting some information around. It appears that the issue is that you have to delete the modifiers before actually doing the remapping.

To the answer :

After changing the settings my xmodmap looks like:

xmodmap: up to 4 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
control     Control_L (0x25),  Control_R (0x69)
mod1        Alt_L (0x40),  Alt_R (0x6c),  Alt_L (0xcc),  Meta_L (0xcd)
mod2        Num_Lock (0x4d)
mod3        Mode_switch (0x42),  Mode_switch (0xcb)
mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce)

Investigation of Mode_switch brings us to the conclusion that Caps_Lock has been successfully mapped:

[smalltalk@localhost ~]$ xmodmap -pke | egrep -e '(Mode_switch)'
keycode  66 = Mode_switch NoSymbol Mode_switch
keycode 203 = Mode_switch NoSymbol Mode_switch

Now xmodmap the excerpt from the man pages:

       keycode NUMBER = KEYSYMNAME ...
               The list of keysyms is assigned to the indicated keycode (which
               may be specified in decimal, hex or octal and can be determined
               by running the xev  program).   Up  to  eight  keysyms  may  be
               attached  to  a  key, however the last four are not used in any
               major X server implementation.  The first keysym is  used  when
               no  modifier  key  is pressed in conjunction with this key, the
               second with Shift, the third when the Mode_switch key  is  used
               with  this  key  and  the  fourth when both the Mode_switch and
               Shift keys are used.

The following configuration works but you have to hold Caps_Lock while using the i,j,k,l (exactly as written in the man pages):

Edit vim ~/.Xmodmap:

! make Capslock the "Mode_switch" key
clear Lock

! All Mod must be cleared
clear Mod1
clear Mod2
clear Mod3
clear Mod4
clear Mod5

! clearning current Caps_Lock assigment and assigning it new one
keycode 66 =
keycode 66 = Mode_switch

! setting all the modification keys
add Mod1 = Alt_L Alt_R Meta_L
add Mod2 = Num_Lock
add Mod3 = Mode_switch
add Mod4 = Super_L Super_R Hyper_R

! Clear must be done before configuring it
keycode 31 =
keycode 44 =
keycode 45 =
keycode 46 =

! Configuration (first column normal type, second with shift and second with Mod_switch)
keycode 31 = i I Up
keycode 44 = j J Left
keycode 45 = k K Down
keycode 46 = l L Right

! Clearing the arrow keys and some functional keys like home
keycode 111 =
keycode 113 =
keycode 114 =
keycode 116 =
keycode 112 =
keycode 117 =

Now to the big question:

How to make the i,j,k,l keys work while Caps_Lock on? You will probably have to make changes to xkb, which I have to think over.


Yes, you can. I have figured it out.

Note: this applies to all keyboards, all layouts, thus is good for testing. If you want to do it via xkb properly you have to create your own layout and have a group1 and group2 + do the mapping.

The bellow is a hack ideal for testing your keyboard(s) (don't forget to backup your ../basic file!):

Warning this applies to all keyboards, all variants.

Edit file: sudo vim /usr/share/X11/xkb/compat/basic

# Add  Caps_Lock to virtual modifiers
    virtual_modifiers  NumLock,AltGr,Caps_Lock;

# change FROM:
    interpret Mode_switch {
        useModMapMods= level1;
        virtualModifier= AltGr;
        action= SetGroup(group=+1);

# TO:
    interpret Mode_switch {
        useModMapMods= level1;
        virtualModifier= Caps_Lock;
        action= LockGroup(group=+1);

# change from
    group 2 = AltGr;
    group 2 = Caps_Lock;

Note: If you have multiple layout it can interfere with those.