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?

quack quixote
  • 43,504

8 Answers8

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!

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.

basic6
  • 2,837
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.

Stanislav
  • 128
Huon
  • 141
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
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 :)

gacrux
  • 2,181
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.

sgtpep
  • 276
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.