35

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?

3

8 Answers 8

19

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!

7
  • 1
    This works on Arch Linux too, but not immediately after the xmodmap command. After reboot, works almost perfectly. Just cannot do CTRL+SHIFT+arrow with CTRL+SHIFT+CAPS+hjkl, usually for seleting words. Any idea how to do this?
    – koss
    May 24, 2012 at 0:56
  • Hmm you're right, best I could do is add Left, Down, Up, Right again into another column. This doesn't make highlighting work but it will skip words like normal. I'll have to look into this more. May 25, 2012 at 17:17
  • This works well enough for me. The only problem I have, it does not work in Chrome and that is a nuisance.
    – Mood
    Aug 3, 2012 at 19:42
  • You may need to clear the cached xkb files in /var/lib/xkb/*.xkm for the changes to /usr/share/X11/xkb/symbols/us to take effect.
    – solo
    Apr 2, 2015 at 2:24
  • 1
    This works on Ubuntu 14.04. I had to make xmodmap /home/alex/.Xmodmap a startup application, and remove all *.xkm files form /var/lib/xkb. Warning: I trashed one Ubuntu VM doing this last step and then my keyboard wouldn't work at all any more, so be careful and have a backup ready :-) Shift+Control+Caps+hjkl to select text works well in Firefox and Thunderbird, but in some applications it does not (Chrome for example) Oct 22, 2015 at 17:46
9

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.

3
  • 1
    I've done this approach myself, but it's not working for all applications! xev clearly says Left and it works for most applications. But some programs only react to the "real" arrow keys, like sublime text editor and others.
    – Tarrasch
    Feb 17, 2012 at 8:18
  • 1
    Works as described on Redhat 6.2. My sore wrists thank you! Feb 21, 2013 at 15:53
  • 1
    Thank you basic6, it works on Ubuntu after the steps described below. There is an issue on Ubuntu (tested on Ubuntu 14.04) that .xkm files are not recompiled, and thus changes in /usr/share/X11/xkb/symbols/* have no effect. In order to improve it remove all *.xkm files from /var/lib/xkb and reboot system. After that the *.xkm files will be recompiled. For more information please have a look: ubuntuforums.org/showthread.php?t=1589744
    – MPtr
    Jul 24, 2014 at 7:54
4

This one works for me on Arch. It remaps Caps+hjkl to arrow keys, and Shift+Caps to Caps.

Put the following in ~/.Xmodmap:

! Remap Caps Lock to special modifier, but still allow Shift+Caps to toggle Caps Lock
clear lock
clear mod5
add lock = Mode_switch
keycode 66 = Mode_switch Caps_Lock NoSymbol NoSymbol
keycode 43 = h H Left Left
keycode 44 = j J Down Down
keycode 45 = k K Up Up
keycode 46 = l L Right Right

Reboot or set it with xmodmap ~/.Xmodmap

If you get an error like:

X Error of failed request:  BadValue (integer parameter out of range for operation)

It probably means that you need to clear something other than mod5 (whatever is currently set to Mode_switch). Check your current modifier mappings with xmodmap.

2
  • xmodmap: unknown command on line /home/nh/.Xmodmap:2
    – Arnold Roa
    May 3, 2021 at 11:10
  • @arnold-roa there was typo - redundant new line char in the comment text of the first line
    – Stanislav
    Aug 8, 2022 at 10:38
3

I haven't tried this myself but it looks like xkb might do what you want http://en.wikipedia.org/wiki/X_keyboard_extension.

I have a package in Ubuntu called x11-xkb-utils that sounds promising :)

1
  • xkb cannot work with the Super key as a modifier. xkb only works with (in order) Unmodified, Shift, AltGr, Shift-AltGr. Higher-level modifiers can also be assigned (such as in Bill Casarin's CapsLock example) but they do not come on a standard keyboard. Mapping Super to a higher modifier removes it from functioning as Super (as in basic6's example).
    – dotancohen
    Feb 3, 2012 at 23:06
3

No sudo needed, derivated from here, modified to make it work also when combined with Alt.

create a file w the following content:

! remove Caps Lock
clear lock
! remove Lock = Caps_Lock
! remove Shift = Caps_Lock
keycode 66 = NoSymbol NoSymbol
keycode 66 = ISO_Level3_Shift

keysym h = h H NoSymbol NoSymbol Left Left
keysym j = j J NoSymbol NoSymbol Down Down
keysym k = k K NoSymbol NoSymbol Up Up
keysym l = l L NoSymbol NoSymbol Right Right

! some sugar
keysym o = o O NoSymbol NoSymbol BackSpace NoSymbol
keysym i = i I NoSymbol NoSymbol Delete NoSymbol`

invoke

xmodmap file

It maps AltGr to Caps instead of Super, so you might rather set

keycode 66 = Super_L

(or watever xev gives you on hitting Super)

The sugar part gives backspace and Del as a special assignment to i and o, you might omit that, or see it as a bonus or motivation to expand/ adjust it on your own ;)

PS: if experiment with it, reset "default" mapping by invoking

setxkbmap
1
2

At last it seems that I found the solution that works with all modifiers (Ctrl+, Shift+, Ctrl+Shift+) and Sublime Text 2.

All glory goes to this gem configuration that I found recently http://www.spinics.net/lists/xorg/msg35931.html. It describes ijkl arrows, but it can be easily modified for hjkl navigation. You need to update your keyboard layout file(s) /usr/share/X11/xkb/symbols/* (personaly, I use /usr/share/X11/xkb/symbols/typo, which I include to my keyboard layout with Xkb option "misc:typo", so it works for any keyboard layout). Configuration assumes that modifier key send ISO_Level3_Shift (there are many ways how to bind Super or Alt to ISO_Level3_Shift).

Key definitions should look like (use NoSymbol if you're modifying ../symbols/typo):

key <AC07> {    
    type="MOD5_NAV",
    [NoSymbol, NoSymbol, Down, Down],   
    actions[Group1] = [NoAction(), NoAction(), RedirectKey(key=<DOWN>, clearmods=ISO_Level3_Shift)]
};

Also you need to edit /usr/share/X11/types/basic and declare type "MOD5_NAV":

type "MOD5_NAV" {
    modifiers = Shift+Mod5;
    map[None] = level1;
    map[Shift] = level2;
    map[Mod5] = level3;
    map[Mod5+Shift] = level3;
    level_name[Level1] = "Base";
    level_name[Level2] = "Caps";
    level_name[Level3] = "Arrows";
};

As for Sublime Text 2 the solution is more tricky and hackish. As mentioned above, Sublime Text 2 reads keycodes directly from the device and so ignores some features of Xkb (and xkb trick with arrows has no effect). There is an almost abandoned but still working project, Gizmo Daemon http://gizmod.sourceforge.net/. After some struggling and googling I successfully compiled it on my Debian Wheezy. Then I created this gizmod script and placed it to ~/.gizmod/modules.d/010-KeyboardViMode-SublimeText2.py http://pastebin.com/HNQgGEwD

P.S. On Linux I miss KeyboardRemap4MacBook sometimes. This great peace of OS X software can enable such navigation (and a lot of other things) with just few checkboxes.

1

I am a HHKB user on Debian/Ubuntu and this solution works for me.

use Left Ctrl to active key.

$ vi ~/.Xmodmap
keycode 37 = ISO_Level3_Shift

Add this code under // End alphanumeric section in the basic block in /usr/share/X11/xkb/symbols/us

//hjkl
//Ctrl + hjkl
key <AC06> {    [   h,  H,  Left    ]   };
key <AC07> {    [   j,  J,  Down    ]   };
key <AC08> {    [   k,  K,  Up      ]   };
key <AC09> {    [   l,  L,  Right   ]   };

Now, you should be able to use left, down, up and right key with Ctrl + h, j, k, l.

By the way, if you have used pentadactyl on Firefox, you can add this code in ~/.pentadactylrc

map -modes=i,c <C-down> <down>
map -modes=i,c <C-up> <up>
1

I found autokey and it is better for mapping.

I believe the link key binding - Emulate Keypad on Laptop - Ask Ubuntu might help you.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .