How to bind AltGr+key to a symbol

keyboard-layoutx11xkbxmodmap

I want to bind AltGr+W to æ, and some other combinations, how can I do this? I also need AltGr+Shift+W to Æ.

I normally use setxkbmap to change the keymap.

Best Answer

You can accoplish that with custom XKB map. I recommend you to dump the current map with xkbcomp $DISPLAY dump.xkb, edit it and load it with xkbcomp newmap.xkb $DISPLAY. Dump file is pretty large and has a lot of superfluous information.

Easiest way to go about the editing is to look up how the altgr is used in your current map. It's usually ISO_LEVEL3 modifier. If your current keymap does not use altgr, you can try loading one that does to see how it can be done. For example -layout us -variant altgr-intl is pretty extensive and has most if not all european keys bound. Below is a short primer of what's going on.

xkb gets keycodes from kernel, sets a label for each and uses that label and modifier keys to decide what keysym it should output. Each key has a type assigned to it which defines what modifier keys it expects and what to output for each combination. Looking at the dump you got with xkbcomp: labels are defined in xkb_keycodes, types in xkb_types and label-to-keysym in xkb_symbols. Of these, xkb_symbols is the one you want to edit and reference the other two to know what to change. You can also just look at the xkb_symbols and find how it's currently done and edit as appropriate.

xkb_types section holds different modifier levels for key definitions and you'll want to one which has altgr and shift modes. Example:

type "FOUR_LEVEL_ALPHABETIC" {
    modifiers= Shift+Lock+LevelThree;
    map[Shift]= Level2;
    map[Lock]= Level2;
    map[LevelThree]= Level3;
    map[Shift+LevelThree]= Level4;
    map[Lock+LevelThree]= Level4;
    map[Shift+Lock+LevelThree]= Level3;
    level_name[Level1]= "Base";
    level_name[Level2]= "Shift";
    level_name[Level3]= "Alt Base";
    level_name[Level4]= "Shift Alt";
};

That means that key marked as FOUR_LEVEL_ALPHABETIC has four modes. Normal, shift/caps, altgr, altgr-shift which sounds like what you're looking for.

Now you want to find out what the keycode for w is if you don't know it already. xev | grep -A2 --line-buffered '^KeyRelease' | sed -n '/keycode /s/^.*keycode \([0-9]*\).* (.*, \(.*\)).*$/\1 \2/p' gives you the keycode for keys you press. grep is there to make the output more readable.

Cross-reference the keycode you got with xkb_keycodes section of the dump map you got earlier. For me, w gives keycode 25. less the dump and find the correct keycode in form of <LABEL> = ##;, example <AD02> = 25;. Or cat dump.xkb| grep ' = 25;' Label is just a name xkb uses to reference the key in later sections.

Now that you have the label, go to xkb_symbols which actually maps the labels to keysyms. The format is

key <AD02> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [  w, W, aring, Aring ]
    };

type= is the type you want from xkb_types section, symbols[Group1]= has one keysym for each of the modes required by the type. Again, normal, shift/caps, altgr, shift-altgr for this type. [Group1], as far as I've understood is a method of using multiple keymaps you can change on the fly with a lock key you set up. I don't use groups myself so everything is group1 for me.

to find all the different keysyms you can use here, check /usr/include/X11/keysymdef.h. The two symbols you're looking for are ae for æ and AE for Æ.

key <AD02> {
        type= "FOUR_LEVEL_ALPHABETIC",
        symbols[Group1]= [  w, W, ae, AE ]
    };

I may have rambled a bit. Check out Arch Wiki's page on XKB, it's good stuff no matter what OS or distro you're using.

Related Question