AltGr Keys – How to Make AltGr+i,j,k,l Work Properly as Cursor Keys

keyboard-layoutlinuxxkb

(I already asked this question on superuser but got no answer so I'll try here now.)

I would like to have the cursor keys and some others available as AltGr+c,h,t,n etc. (i,j,k,l if you have qwerty). I have made a custom keyboard layout file (see here). There I basically just took a layout file and modified the relevant lines to be like

key <AC09> { [ n, N, Right, Right ] };

I have this as /usr/share/X11/xkb/symbols/nonpop and I load it with setxkbmap nonpop in ~/.xinitrc (I'm not using any DE, just the Awesome WM).

And it works—almost.

  • In Firefox, for example, everything works nicely. For example AltGr+n moves the cursor right and Shift+AltGr+n selects text. Similarly in the main text area in LyX.
  • In MonoDevelop the cursor moves with AltGr+n, but Shift+AltGr+n also only moves the cursor instead of selecting. Shift+Right selects text normally.
  • In NetBeans and LyX dialogs pressing (Shift+)AltGr+n does absolutely nothing.

I guess these other programs read the AltGr state and decide it's a bad thing. So, is there any way to make things happen the way I want? It looks like overlays could be a solution but I didn't get them to work yet.

Best Answer

The problem is that when you use a common modifier like AltGr, programs actually see it as being pressed when you use the AltGr arrows. So Shift + AltGr + i actually appears to a program as if you are pressing Shift + Alt + Up and it's the addition of the extra Alt that confuses the program. You can avoid this by either adding more shortcuts to the program if possible, so Shift + Alt + Up does the same action as Shift + Up, or you can use an uncommon modifier that the program is not aware of.

There are other ways of doing this, but this was one of the simpler ways and works well for me. It creates a "Group2" overlay on the alphanumeric keys, such that when you switch to Group2 you will have arrows there instead of letters. You can switch to Group2 with a toggle (on/off like Caps Lock normally works) or a momentary (press to activate, like Shift normally works)

partial alphanumeric_keys
xkb_symbols "alpha_arrows" {
    key <AD07> {
        symbols[Group2]= [            Home ]  # u
    };
    key <AD08> {
        symbols[Group2]= [              Up ]  # i
    };
    key <AD09> {
        symbols[Group2]= [             End ]  # o
    };
    key <AD10> {
        symbols[Group2]= [           Prior ]  # p
    };
    key <AC07> {
        symbols[Group2]= [            Left ]  # j
    };
    key <AC08> {
        symbols[Group2]= [            Down ]  # k
    };
    key <AC09> {
        symbols[Group2]= [           Right ]  # l
    };
    key <AC10> {
        symbols[Group2]= [            Next ]  # ;
    };
    key <AB06> {
        symbols[Group2]= [          Delete ]  # n
    };
};

You can then pick a key to use as a Group2 activation key. You can see all the options (if you don't want to roll your own) with this:

$ grep grp /usr/share/X11/xkb/rules/base.lst

Then pick an option, for example this one activates the arrows only while Caps Lock is being held. It also adds a new combination Alt + Caps Lock to actually switch caps lock on and off:

$ setxkbmap -option grp:caps_switch

You can add this into your Xorg config file to make the change permanent - there are plenty of guides online about how to do this.

Note that:

  • key is used, as opposed to replace key because we want to add to the existing definition, not replace it.
  • If you actually have an alternate keyboard layout (possibly some international keyboards that can also type Latin/English letters), this method may not work for you. You will have to define a new type based on ALPHANUMERIC with extended modifiers (e.g. Hyper) to activate the arrow keys.
Related Question