I wanted to add more levels to my keyboard layouts, so I decided to enable level5 key. I’ve already had level3 on Menu
, and would like to map RAlt to ISO_Level5_Shift.
However, setxkbmap
has no option for that. /usr/share/X11/xkb/rules/evdev.lst
contains only the following options in regard to lv5 switch:
lv5:lsgt_switch_lock
lv5:ralt_switch_lock
lv5:lwin_switch_lock
lv5:rwin_switch_lock
As if mapping a simple key is not possible. This already hinted on troubles.
Knowing what setxkbmap
does internally, it’s easy to construct an option to enable lv5 switch and set to right Alt
:
-option "lv5:ralt_switch"
And, despite that setxkbmap
takes this option and returns with success, there’s no mapping.
After finding an answer to a similar question here I’ve constructed a custom xkbcomp
file.
xkb_keymap {
xkb_geometry {
include "pc(pc104)"
};
xkb_keycodes {
include "evdev"
include "aliases(qwerty)"
};
xkb_types {
include "complete"
};
xkb_compatibility {
include "complete"
include "ledscroll(group_lock)"
};
xkb_symbols {
include "pc+us+ru:2+inet(evdev)"
include "group(rctrl_rshift_toggle)"
include "ctrl(swapcaps)"
include "keypad(oss)"
include "kpdl(dot)"
include "terminate(ctrl_alt_bksp)"
include "level3(modifier_mapping)"
include "level3(menu_switch)"
include "level5(modifier_mapping)"
include "level5(ralt_switch)"
key <AB06> {
type= "EIGHT_LEVEL",
symbols[Group1]= [ n, N, n, n, u, i, o, p ],
symbols[Group2]= [ Cyrillic_te, Cyrillic_TE, n, n, u, i, o, p ]
};
};
};
This should assign Menu key to be ISO_Level3_Shift and RAlt to be ISO_Level5_Shift. And the keys are assigned, but there is an error:
$ xkbcomp ~/new.xkbcomp.xkb :0
Error: Key <MDSW> added to map for multiple modifiers
Using Mod3, ignoring Mod5.
xkbcomp
returns with code 0, despite that there was an error.
The mapping on key N
should have made levels 5 to 8 “u”, “i”, “o” and “p”, but instead RAlt sends the usual n and N on all eight levels (if levels >4 actually work).
In attempt to determine, how to solve this error, I’ve found, that <MDSW>
is set in… the very rules file for “pc”.
/usr/share/X11/xkb/symbols/pc
:
xkb_symbols "pc105" {
…
// Fake keys for virtual<->real modifiers mapping:
key <LVL3> { [ ISO_Level3_Shift ] };
key <MDSW> { [ Mode_switch ] };
modifier_map Mod5 { <LVL3>, <MDSW> };
…
};
And here is another weird thing: I include pc104 keyboard model, but this code refers to pc105 and shouldn’t be sourced at all. However… xkb_symbols "pc104"
is nowhere to be found. And this “symbols/pc” file is the only other file in /usr/share/X11/xkb/
that sets or modifies <MDSW>
assignment to Mod* keys. The other file being “symbols/level5” file, which does it in xkb_symbols "modifier_mapping"
.
// Ensure a mapping to a real modifier for LevelFive.
partial modifier_keys
xkb_symbols "modifier_mapping" {
replace key <MDSW> {
type[Group1] = "ONE_LEVEL",
symbols[Group1] = [ ISO_Level5_Shift ]
};
modifier_map Mod3 { <MDSW> };
};
I think, that this conflict may prevent both lv3 switch and lv5 switch to work at the same time, but I’m not sure. It’s concerning, that in another answer, Mode_switch
key is present among Mod* keys, and after loading my new.xkbcomp.xkb
I don’t see it anywhere:
$ xmodmap -pm
xmodmap: up to 4 keys per modifier, (keycodes in parentheses):
shift Shift_L (0x32), Shift_R (0x3e)
lock Caps_Lock (0x25)
control Control_L (0x42), Control_R (0x69)
mod1 Alt_L (0x40), Meta_L (0xcd)
mod2 Num_Lock (0x4d)
mod3 ISO_Level5_Shift (0xcb)
mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf)
mod5 ISO_Level3_Shift (0x5c)
Best Answer
Here is my working solution for putting ISO_Level5_Shift on Control_R. You would need to apply the same logic.
xev
to find the keycode of the key you want to associate with ISO_Level5_Shift. Move the mouse cursor over the little scare in the window, press a key to see its keycode in the output. In my case the code was 105.xmodmap
. I saw that Control_R was associated with mod4.xmodmap -e "clear mod4
to free the key. Note that it frees all keys so you may need to associate the other keys back if you need them.xmodmap -e "keycode 105 = ISO_Level5_Shift"
to associate Control_R with the modifier.xmodmap -e "add mod3 = ISO_Level5_Shift"
to enable level 5.