Mapping Super+hjkl to arrow keys under X

I'm trying to map:

Super+h -> Left
Super+j -> Down
Super+k -> Up
Super+l -> Right

globally under X. The idea is I don't want to leave my home row that often to use the arrow keys, so I'll use the Super modifier + hjkl to emulate the arrow keys under X. Is there any way to do this?

One thing I've tried is xbindkeys + xte using this configuration:

"xte 'keydown Up' 'keyup Up'"
  Mod4+k

"xte 'keydown Down' 'keyup Down'"
  Mod4+j

"xte 'keydown Left' 'keyup Left'"
  Mod4+h

"xte 'keydown Right' 'keyup Right'"
  Mod4+l

but there seems to a large delay between me pressing the key and noticing any result, and most of the time nothing happens at all.

Is there a more elegant way of doing this that actually works with no delay?


Solution 1:

Capslock + HJKL to arrow keys

  1. Create ~/.Xmodmap and put this inside:

    clear Lock 
    keycode 66 = ISO_Level3_Shift
    
  2. Add Left, Down, Up, Right as a third item to the h,j,k,l key entries in /usr/share/X11/xkb/symbols/us (the first section):

    key { [ h, H, Left, Left ] }; 
    key { [ j, J, Down, Down ] };
    key { [ k, K, Up, Up ] }; 
    key { [ l, L, Right, Right ] };
    
  3. run xmodmap ~/.Xmodmap

Alternative: Capslock as Control and Control_L + HJKL to arrow keys

This is my current setup. I unmapped Control_L as a control key and use it as a special modifier (ISO_Level3_Shift), which corresponds to the third entry in the /usr/share/X11/xkb/symbols/us file for the hjkl mappings.

  1. I modified the first stanza of /usr/share/X11/xkb/symbols/us like before:

    key { [ h, H, Left, Left ] }; 
    key { [ j, J, Down, Down ] };
    key { [ k, K, Up, Up ] }; 
    key { [ l, L, Right, Right ] };
    
  2. Then I put this in my ~/.Xmodmap file:

    clear Control
    keycode 66 = Control_L
    add Control = Control_L
    add Control = Control_R
    keycode 37 = ISO_Level3_Shift
    

keycode 66 is capslock and keycode 37 is left control

  1. run xmodmap ~/.Xmodmap

With this setup I can use arrows keys with Control_L + hjkl as well as skip over words with Control_L + caps + hl. Easy!

Solution 2:

The above mentioned changes in /usr/share/X11/xkb/symbols/us do NOT work for me:
Error loading new keyboard description

But after looking through lots of contradicting howtos, I've come up with a solution, which maps the left super key (left windows key / Mod4) in combination with hjkl to Left, Down, Up, Right. This is a system-wide setting.

Add this block to the end of the first section (right before };) of your /usr/share/X11/xkb/symbols/us:

//hjkl
//AltGr + hjkl
key <AC06> {        [         h, H, Left            ]       };
key <AC07> {        [         j, J, Down            ]       };
key <AC08> {        [         k, K, Up              ]       };
key <AC09> {        [         l, L, Right           ]       };
//Super_L -> Alt Gr
key <LWIN> { [ ISO_Level3_Shift ] }; //see below!

The first key line maps AltGr+h to Left.
The last key line makes the left super key behave like AltGr.
Here you go:

Super + h -> Left
Super + j -> Down
Super + k -> Up
Super + l -> Right

In order to apply the new settings, run setxkbmap or restart your system.

Important: This obviously disables the super key, so if you're actually using your super key for other purposes (i.e. moving a window to another workspace), you shouldn't remap it like this.
In order to use Caps Lock instead of Super, change the last key line with:

key <CAPS> { [ ISO_Level3_Shift ] };

Here's the complete first section of my config file:

default
partial alphanumeric_keys modifier_keys
xkb_symbols "basic" {

    name[Group1]= "English (US)";

    // Alphanumeric section
    key <TLDE> {        [     grave,    asciitilde      ]       };
    key <AE01> {        [         1,    exclam          ]       };
    key <AE02> {        [         2,    at              ]       };
    key <AE03> {        [         3,    numbersign      ]       };
    key <AE04> {        [         4,    dollar          ]       };
    key <AE05> {        [         5,    percent         ]       };
    key <AE06> {        [         6,    asciicircum     ]       };
    key <AE07> {        [         7,    ampersand       ]       };
    key <AE08> {        [         8,    asterisk        ]       };
    key <AE09> {        [         9,    parenleft       ]       };
    key <AE10> {        [         0,    parenright      ]       };
    key <AE11> {        [     minus,    underscore      ]       };
    key <AE12> {        [     equal,    plus            ]       };

    key <AD01> {        [         q,    Q               ]       };
    key <AD02> {        [         w,    W               ]       };
    key <AD03> {        [         e,    E               ]       };
    key <AD04> {        [         r,    R               ]       };
    key <AD05> {        [         t,    T               ]       };
    key <AD06> {        [         y,    Y               ]       };
    key <AD07> {        [         u,    U               ]       };
    key <AD08> {        [         i,    I               ]       };
    key <AD09> {        [         o,    O               ]       };
    key <AD10> {        [         p,    P               ]       };
    key <AD11> {        [ bracketleft,  braceleft       ]       };
    key <AD12> {        [ bracketright, braceright      ]       };

    key <AC01> {        [         a,    A               ]       };
    key <AC02> {        [         s,    S               ]       };
    key <AC03> {        [         d,    D               ]       };
    key <AC04> {        [         f,    F               ]       };
    key <AC05> {        [         g,    G               ]       };
    key <AC06> {        [         h,    H               ]       };
    key <AC07> {        [         j,    J               ]       };
    key <AC08> {        [         k,    K               ]       };
    key <AC09> {        [         l,    L               ]       };
    key <AC10> {        [ semicolon,    colon           ]       };
    key <AC11> {        [ apostrophe,   quotedbl        ]       };

    key <AB01> {        [         z,    Z               ]       };
    key <AB02> {        [         x,    X               ]       };
    key <AB03> {        [         c,    C               ]       };
    key <AB04> {        [         v,    V               ]       };
    key <AB05> {        [         b,    B               ]       };
    key <AB06> {        [         n,    N               ]       };
    key <AB07> {        [         m,    M               ]       };
    key <AB08> {        [     comma,    less            ]       };
    key <AB09> {        [    period,    greater         ]       };
    key <AB10> {        [     slash,    question        ]       };

    key <BKSL> {        [ backslash,         bar        ]       };
    // End alphanumeric section

    //hjkl
    //AltGr + hjkl
    key <AC06> {        [         h, H, Left            ]       };
    key <AC07> {        [         j, J, Down            ]       };
    key <AC08> {        [         k, K, Up              ]       };
    key <AC09> {        [         l, L, Right           ]       };
    //Super_L -> Alt Gr
    key <LWIN> { [ ISO_Level3_Shift ] };


};

I hope this helps somebody out there...

If anyone has a better solution, please let me know.

Edit: Tested on Fedora.