XKB mod3 keeps getting mapped to Mode_switch instead of ISO_Level5_Shift

Viewed 440

My system is Ubuntu 20.04, and it uses XKB layout files on /usr/share/X11/xkb/symbols.

I would like to use Level5 on my own keyboard layouts, in order to increase the number of symbols I can type with a single layout.

My own idea was to use it as an alternate capitalization system (in combination with CapsLock), and use Shift for alternate forms of letters instead.

However, as I use that layout, ISO_Level5_Shift seems to not work. As the following xmodmap command illustrates, it gets bound to Mode_switch instead:

$ xmodmap
xmodmap:  up to 4 keys per modifier, (keycodes in parentheses):

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Alt_L (0x40),  Meta_L (0xcd)
mod2        Num_Lock (0x4d)
mod3        Mode_switch (0xcb)
mod4        Super_L (0x85),  Super_R (0x86),  Super_L (0xce),  Hyper_L (0xcf)
mod5        ISO_Level3_Shift (0x5c)

(Edit: added mappings list with xkbcomp:)

$ xkbcomp $DISPLAY - > keyboard.xkb
$ grep modifier_map keyboard.xkb
    modifier_map Control { <LCTL> };
    modifier_map Shift { <LFSH> };
    modifier_map Shift { <RTSH> };
    modifier_map Mod1 { <LALT> };
    modifier_map Lock { <CAPS> };
    modifier_map Mod2 { <NMLK> };
    modifier_map Mod5 { <LVL3> };
    modifier_map Control { <RCTL> };
    modifier_map Mod4 { <LWIN> };
    modifier_map Mod4 { <RWIN> };
    modifier_map Mod3 { <MDSW> };
    modifier_map Mod1 { <META> };
    modifier_map Mod4 { <SUPR> };
    modifier_map Mod4 { <HYPR> };

I’ve tried different hacks, no solution. This is the one I use currently (it means, first I choose LSGT as a switch, then swap Left Shift and LSGT):

partial modifier_keys
xkb_symbols "e4_modifiers" {
    include "level5(lsgt_switch)"
    
    key <LSGT> {
        type[Group1] = "ONE_LEVEL",
        symbols[Group1] = [ Shift_L ]
    };

    key <LFSH> {
        type[Group1] = "ONE_LEVEL",
        symbols[Group1] = [ ISO_Level5_Shift ]
    };

};

This is the start of my own layout file:

default partial alphanumeric_keys
xkb_symbols "e4" {
    include "us"
    include "level3(ralt_switch)"
    
    // changes to modifiers
    include "kyme4(e4_modifiers)"
    name[Group1] = "Kaymoskvan (E4)";

    key.type[Group1] = "KYM_8_T1";

There follow some custom key types I made in order for my layout to work:

partial default xkb_types "default" {
    virtual_modifiers LevelThree,LevelFive,Alt;

    type "KYM_8_T1" {
        modifiers = Shift+Lock+LevelThree+LevelFive+Control;
        
        map[None] = Level1;
        map[Shift] = Level2;
        map[LevelThree] = Level3;
        map[Shift+LevelThree] = Level4;
        map[Lock] = Level5;
        map[Lock+Shift] = Level6;
        map[Lock+LevelThree] = Level3;
        map[Lock+Shift+LevelThree] = Level4;
        map[LevelFive] = Level5;
        map[LevelFive+Shift] = Level6;
        map[LevelFive+LevelThree] = Level7;
        map[LevelFive+Shift+LevelThree] = Level8;
        map[LevelFive+Lock] = Level1;
        map[LevelFive+Shift+Lock] = Level2;
        map[LevelFive+LevelThree+Lock] = Level8;
        map[LevelFive+LevelThree+Shift+Lock] = Level7;

        map[Control] = Level7;
        preserve[Control] = Control;
        map[Control+Shift] = Level8;
        preserve[Control+Shift] = Control;
        map[Control+LevelFive] = Level8;
        preserve[Control+LevelFive] = Control;
        map[Control+Shift+LevelFive] = Level7;
        preserve[Control+Shift+LevelFive] = Control;

        level_name[Level1] = "Base";
        level_name[Level2] = "Shift";
        level_name[Level3] = "Alt";
        level_name[Level4] = "Shift Alt";
        level_name[Level5] = "Caps";
        level_name[Level6] = "Shift Caps";
        level_name[Level7] = "Ascii";
        level_name[Level8] = "Shift Ascii";
    };

People on Internet suggested me to remap modifiers with xmodmap, but it binds the modifier indefinitely to a key until reboot, and I see all of this as too invasive. I have other layouts which don’t use Level5, and where the key I use as a modifier is bound to something else.

As for multiple groups, they don’t work on a single layout file.

Is there a way to fix this using XKB only?

1 Answers

Some suggestions that worked for me:

If you're going to write your own KYM_8_T1_LEVEL type, I suggest using Mod1, Mod2 ... for your modifiers:

modifiers= Shift+Mod3+Mod5;
    map[Shift]= Level2;
    map[Mod5]= Level3;
    map[Shift+Mod5]= Level4;
    map[Mod3]= Level5;
    map[Shift+Mod3]= Level6;
    map[Mod3+Mod5]= Level7;
    map[Shift+Mod3+Mod5]= Level8;

Regarding your modifier issue, dump your xkb configuration into a file:

xkbcomp $DISPLAY - > keyboard.xkb

Open it and scroll down to the modifier map section. Delete every line that has a modifier in it where the key doesn't exist on your keyboard or you don't want the key acting as a modifier. Then edit your modifiers to your liking. Mine currently looks like this:

modifier_map Control { <LCTL> };
modifier_map Control { <RCTL> };
modifier_map Shift { <LFSH> };
modifier_map Lock { <LFSH> };
modifier_map Shift { <RTSH> };
modifier_map Mod1 { <LALT> };
modifier_map Mod1 { <RALT> };
modifier_map Mod2 { <CAPS> };
modifier_map Mod3 { <SCLK> };
modifier_map Mod4 { <SUPR> };
modifier_map Mod5 { <LWIN> };

xmodmap shows my active modifiers as:

$ xmodmap -pm
xmodmap:  up to 2 keys per modifier, (keycodes in parentheses):

shift       Shift_R (0x3e)
lock        Shift_L (0x32)
control     Control_L (0x25),  Control_R (0x69)
mod1        Alt_L (0x40),  Alt_R (0x6c)
mod2        Mode_switch (0x42)
mod3        ISO_Level5_Shift (0x4e)
mod4        Super_L (0xce)
mod5        ISO_Level3_Shift (0x85)

Then modify your key bindings to your liking. My key <AE01> at the time of this posting looks like this:

key <AE01> {
    type[group1]= "GLEN_LEVEL",
    type[group2]= "FOUR_LEVEL",
    symbols[Group1]= [               1,          exclam,     onesuperior,    onesubscript,         onehalf,           U2153,      onequarter,           UFF11 ],
    symbols[Group2]= [               6,               7,               8,               9 ]
};

If you map Mode_switch to a key, you can use it to switch between layouts. If I don't use Mode_switch, the keys in symbols[Group1] are used. If I press and hold the Mode_switch key, <CAPS> on my pc, the symbols in symbols[Group2] are displayed.

Save your changes. Then add the following lines to your .xinitrc file so your configuration changes will load everytime you start X:

# Set keymapping, compose key, and level 8 symbols
if [ -s ~/keyboard.xkb ]; then
    xkbcomp keyboard.xkb $DISPLAY
fi

Once you're convinced you have all the bugs worked out, instead of loading keyboard.xkb every time, you can go through the xkb directory and edit all the files to match your keyboard.xkb configuration so you don't have to load a separate script as you requested in this post.

Related