DISCLAIMER. English language used here only for compatibility (ASCII only), so any suggestions about my bad grammar (and not only it) will be greatly appreciated.

суббота, 25 апреля 2015 г.

XKB useModMapMods, remapping Ctrl+Esc to Win and xmonad

Contents:
1. What useModMapMods in XKB interpretations means exactly?
2. Map Ctrl+Esc to Win key (Mod4) using XKB.
3. Using Ctrl+Esc as xmonad modMask.


1. What useModMapMods in XKB interpretations means exactly?

It seems, that 'useModMapMods' in XKB configs corresponds (write_compat() function in https://github.com/xkbcommon/libxkbcommon/blob/master/src/xkbcomp/keymap-dump.c) to 'level_one_only' field of struct xkb_sym_interpret (defined in https://github.com/xkbcommon/libxkbcommon/blob/master/src/keymap.h) . Then in algorithm for binding interpretation to key (defined in function FindInterpForKey() from https://github.com/xkbcommon/libxkbcommon/blob/master/src/xkbcomp/keymap.c) if 'level_one_only' is set and level is not 0, we pretend, that there is no real modifiers binded to key (key's modmap is 0). That mean, that all conditions (in interpretation definitions) on modifiers, which require any modifier, will always fail, and that with condition on modifiers AnyOfOrNone, it does not matter whether useModMapMods enabled or not.

Example: if i bind ISO_Next_Group to CAPS, like:

key  {
        [ ISO_Next_Group, Caps_Lock ]
    };

(i.e. group switch occurs at level 0), then it does not matter how i define requirments on ISO_Next_Group interpretation:

interpret ISO_Next_Group+AnyOfOrNone(all) {
        useModMapMods=level1;
        ...
    }

or

interpret ISO_Next_Group+AnyOf(all) {
        useModMapMods=level1;
        ...
    }

either will work (i.e. regardless of whether modificator is required or not).

But if i bind ISO_Next_Group to CAPS on level 1, like:

key  {
        [ Caps_Lock, ISO_Next_Group ]
    };

, then group switch will only work, if no modificator is allowed in ISO_Next_Group interpetation:

interpret ISO_Next_Group+AnyOfOrNone(all) {
        useModMapMods=level1;
        ..
    }

or if 'useModMapMods' disabled (and any modificator is required):

interpret ISO_Next_Group+AnyOf(all) {
        ..
    }

, and will *not* work if both any modificator is required and 'useModMapMods' is enabled:

interpret ISO_Next_Group+AnyOf(all) {
        useModMapMods=level1;
        ..
    }

Note, that all examples, which require any modificator on key for interpret it as ISO_Next_Group, work with Caps only, because (and until) it is bound to real modificator Lock with:

modifier_map Lock {  };

, and if i remove this line, all conditions 'AnyOf(all)' will be always false. That confirms, that modmap is all real modificators bound to the key by xkb config (but not currently active real modificators or anything else).


2. Map Ctrl+Esc to Win key (Mod4) using XKB.
Something like

xkb_symbols {
    key  { type="PC_CONTROL_LEVEL2", [ Escape, Super_L ] };
};

In more details: there is two interpretations (in "complete" compat file) for Super_L: one -

interpret Super_L+AnyOf(all) 

, which matches only to keys, which have real modifiers bound to them (like ), and second -

interpret Super_L+AnyOfOrNone(all) 

, which matches to keys, which just mention Super_L . They differ slightly in action definition, but both of them will raise Super virtual modifier (in 'base' modifier state, i.e. modifier will be raised only while key is holded). Then, Super virtual modifier will be mapped to Mod4 real modifier through 'modifier_map' statements, which bind key symbols, like to Mod4 . Thus, raising Super will raise Mod4. Particularly note, that if my xkb config miss interpretation for Super_L without real modifiers (AnyOfOrNone), or does not map Super to Mod4 (with 'modifier_map), neither will work. And it does not matter through which key symbol Super had mapped to Mod4, i need at least one.


3. Using Ctrl+Esc as xmonad modMask.

Just note: xmonad always uses KeySym bound to level 0 (XKB shift level), because it calls `keycodeToKeysym dpy code 0` in KeyEvent handler (XMonad/Main.hsc): last argument of keycodeToKeysym specifies which level to use.

Also, aside from XKB part, which requires redefinition, there is xmonad part: xmonad requires exact (real, because virtual are invisible outside XKB) modifiers match for its keys to work. That means, that if i raise Mod4 by pressing Ctrl+Esc, it won't match with just 'mod4Mask' modMask in xmonad, because Ctrl modifier is also set. Thus, to make 'Ctrl+Esc' emulation to work, i need to use modMask 'mod4Mask .|. controlMask' in xmonad. Or i need to define each key in two flavors: one with mod4Mask and one with 'mod4Mask .|. controlMask' .

And, finally, i need to modify XKB configuration for one user: both `setxkbmap` and `xkbcomp` can search user-defined directories specified after '-I' option (with no space before argument), correct subdirectory structure required (i.e. 'symbols', 'types', etc the same as in /usr/share/X11/xkb/). But `setxkbmap` can't itself compile rules, using e.g. symbols from non-standard location, because it won't pass '-I' option to `xkbcomp`. So, i need to do this in two stages: first compose Kccgst definition using `setxkbmap` with adjusted rules and required options, like

setxkbmap -I"$xkb_user_dir" -rules my_rules -option ctrl_esc_to_super -print 

, and output it to stdout (note, that my_rules must define all current RMLVO settings, i.e. they must be copy of current rules (`setxkbmap -query`) with some adjustments), then invoke `xkbcomp` for compiling Kccgst from stdout to X server, like

xkbcomp -I"$xkb_user_dir" - "$DISPLAY" 

Комментариев нет:

Отправить комментарий