OneDeadKey / kalamine

Keyboard Layout Maker
MIT License
112 stars 29 forks source link

[xkb] ignored 1dk layer when used along with a 4-level keyboard layout #118

Open fabi1cazenave opened 9 months ago

fabi1cazenave commented 9 months ago

On an XOrg setup :

setxkbmap "fr,custom" -option grp:shift_caps_toggle

Both layouts work okay for the base and altgr layers, but the custom layout’s 1dk layer (= levels 5 and 6) is ignored.

Reversing the order works around this issue :

setxkbmap "custom,fr" -option grp:shift_caps_toggle
fabi1cazenave commented 9 months ago

Quick hack, it seems that on my distro (Ubuntu 22.04), patching xkb/symbols/pc might do the trick :

    // Fake keys for virtual<->real modifiers mapping:
    key <LVL3> {    [ ISO_Level3_Shift    ]    };
    key <MDSW> {    [ Mode_switch         ]    };
    modifier_map Mod5   { <LVL3>, <MDSW> };

In this section, replacing Mode_switch by ISO_Level5_Shift seems to make it work. If that’s confirmed, maybe xkalamine could patch this section somehow.

wismill commented 9 months ago

I think the correct mapping is:

key <LVL3> {    [ ISO_Level3_Shift    ]    };
key <MDSW> {  [ ISO_Level5_Shift ]    };
modifier_map Mod5   { <LVL3> };
modifier_map Mod3   { <MDSW> };

i.e. you need different real modifiers for each modifier.

This should not be an issue for xkeyboard-config ≥ 2.36

fabi1cazenave commented 9 months ago

Following our discussion, it looks like it could be fixed on the xkb_custom side with this :

    virtual_modifiers LevelFive;
    replace key <MDSW> {
        virtualmodifiers = LevelFive
    };
    modifier_map Mod3 { <MDSW> };
nivopol commented 9 months ago

Hi! I’ll try to explain my take on this problem:

My system

Debian stable, X11 X.Org version: 1.21.1.7, xkb-data 2.35.1-1, XFCE, XIM.

On pb description

ignored 1dk layer when used along with a 4-level keyboard layout

I have the feeling it’s a lot more generic than that. It’s the same using a two-level, and as fas as our investigation goes any layout not using <MDSW> keysym, wich are about all layouts except rare old vendor specific ones. Optimot has 6 levels and 1dk is also KO. By the way, better speak about 8 levels, even if level 7 and 8 are unused, they exist.

Both layouts work okay for the base and altgr layers, but the custom layout’s 1dk layer (= levels 5 and 6) is ignored.

Yes. We have also the specific interaction with Bépo & Optimot which is a related problem, but I feel it needs it’s own issue as the bug attribution is shared with them: #119

Explanation

As reported by @wismill and me, this arises due to usage of <MDSW> keysym to link ISO_Level5_Shift with Mod3 in 1dk layouts. When multiple layouts are loaded in a configuration, the resulting key declaration is:

The declaration can’t be partial on the left, if there is a group 2, then the group 1 must exist. So, as other layouts do not define key <MDSW>, the Xkb rules default to pc(pc105) declaration as Mode_switch.

nivopol commented 9 months ago

 Xkb-config (un)affected versions

Versions from xkeyboard-config-2.36 (June 2022) should solve the issue, due to this commit, changing the pc105 declaration from

    key <LVL3> {[  ISO_Level3_Shift  ]};
    key <MDSW> {[  Mode_switch  ]};
    modifier_map Mod5  { <LVL3>, <MDSW> };

to

    key <LVL3> {[  ISO_Level3_Shift  ]};
    modifier_map Mod5  { <LVL3> };

    key <MDSW> {[  ISO_Level5_Shift  ]};
    modifier_map Mod3  { <MDSW> };

in order to solve the exact same issue for german layout Neo.

nivopol commented 9 months ago

Proposed solutions for older version

Patching symbols/pc system file

As proposed by @fabi1cazenave and @wismill in upper comments. This is essentially backporting 2.36 change.

Use a virtual modifier to catch the <MDSW> binding

As proposed by @wismill on Bépo help channel, this redefinition in Kalamine-generated symbol section should solve the issue from at minimum version 2.32:

    virtual_modifiers LevelFive;
    replace key <MDSW> {
        virtualmodifiers = LevelFive
    };
    modifier_map Mod3 { <MDSW> };

Nevertheless it doesn’t seem to do the trick for me on 2.35.1. Could this be that the method in exclusive to modern libxkbcommon and can’t be used on old X11 ?

Not using <MDSW> at all and defining custom action in layout

This snippet solve the issue on my system (example taken with Ergo‑L):

    virtual_modifiers  LevelFive;
    //[...] some Ergo‑L keys
    key <AD09> { virtualmodifiers=LevelFive,
    symbols[group1]=[VoidSymbol     , VoidSymbol      , apostrophe      , dead_acute      , dead_diaeresis  , dead_diaeresis  , VoidSymbol      , VoidSymbol      ],
    actions[group1]=[LatchMods(modifiers=LevelFive), LatchMods(modifiers=LevelFive), NoAction(), NoAction()   , NoAction()    , NoAction(), NoAction(), NoAction()] }; // sym: *¨ *¨ ¨ ¨ ' ´ act:Lvl5latch, Lvl5latch, ø, ø, ø, ø, ø, ø
    modifier_map Mod3  { <AD09> };

So we declare a virtual modifier first, then we use it directly on the relevant key for 1dk. Then on this key we redefine the action to latch to level 5 on the relevant levels. Finally we map the modifier on it.

nivopol commented 9 months ago

 Xkb-config (un)affected versions

Versions from xkeyboard-config-2.36 (June 2022) should solve the issue, due to this commit […] [solving] the exact same issue for german layout Neo.

Well, well, fortunately pc file was patched, because the fact that the 1dk layouts were OK when loaded first was in itself a Xkb-config bug, where the default was only apply to group 1. So probably we should have tested and noticed that secondary layout could be missing some of their technical keys when loaded after Ergol.

There is an issue by P. Hutterer to fix exactly this, and he’s currently blocked by the fact that group-switch keys are relying on this bug to work!