types: separate ctx

Separate the ctx object to its own field in CompatInfo, instead of doing
keymap->ctx.

The compilation functions should not have direct access to the keymap;
instead they should process the files with their own independent state
(in the *Info structs) as much as possible, and only at the end should
they be copied (i.e. commited) to the keymap. If the compilation fails,
it leaves no by-products. It's also just good form.

This was seemingly the original author's intention, but I suppose he cut
a few corners (mostly with the handling of virtual modifiers, which are
threaded through types -> compat -> symbols).

This commit is the first step and may look artificial; however the
'keymap' field will be removed shortly.

Signed-off-by: Ran Benita <ran234@gmail.com>
compat: separate ctx

Same as was done for types.

Signed-off-by: Ran Benita <ran234@gmail.com>
symbols: separate ctx

Same as was done for compat and types.

Signed-off-by: Ran Benita <ran234@gmail.com>
Make the effective mod mask calculation available to other files

We will want to use that function in state.c as well.

Signed-off-by: Ran Benita <ran234@gmail.com>
state: support querying whether virtual modifiers are active

This allows the user to query directly whether "NumLock", "Super",
"Meta", "Alt" etc. are active, rather than resorting to the real
modifiers or just guessing. This should help e.g. toolkits which have
things like Meta in the modifier masks they report.

Demo:

$ sudo ./test/interactive
keysyms [ Caps_Lock ] unicode [   ] group [ English (US) (0) ] mods [ ] leds [ ]
keysyms [ A         ] unicode [ A ] group [ English (US) (0) ] mods [ -Lock ] leds [ Caps Lock ]
keysyms [ Num_Lock  ] unicode [   ] group [ English (US) (0) ] mods [ Lock ] leds [ Caps Lock ]
keysyms [ KP_1      ] unicode [ 1 ] group [ English (US) (0) ] mods [ Lock -Mod2 -NumLock ] leds [ Caps Lock Num Lock ]
keysyms [ Shift_R   ] unicode [   ] group [ English (US) (0) ] mods [ Lock Mod2 NumLock ] leds [ Caps Lock Num Lock ]
keysyms [ a         ] unicode [ a ] group [ English (US) (0) ] mods [ Shift Lock Mod2 NumLock ] leds [ Caps Lock Num Lock ]
keysyms [ Meta_L    ] unicode [   ] group [ English (US) (0) ] mods [ -Shift Lock Mod2 NumLock ] leds [ Caps Lock Num Lock ]
keysyms [ Meta_L    ] unicode [   ] group [ English (US) (0) ] mods [ -Shift Lock Mod2 NumLock ] leds [ Caps Lock Num Lock ]
keysyms [ a         ] unicode [ a ] group [ English (US) (0) ] mods [ Shift Lock Mod1 Mod2 NumLock Alt Meta ] leds [ Caps Lock Num Lock ]
keysyms [ Super_L   ] unicode [   ] group [ English (US) (0) ] mods [ Shift Lock Mod1 Mod2 NumLock Alt Meta ] leds [ Caps Lock Num Lock ]
keysyms [ a         ] unicode [ a ] group [ English (US) (0) ] mods [ Shift Lock Mod1 Mod2 Mod4 NumLock Alt Meta Super ] leds [ Caps Lock Num Lock ]
keysyms [ Control_L ] unicode [   ] group [ English (US) (0) ] mods [ Shift Lock Mod1 Mod2 Mod4 NumLock Alt Meta Super ] leds [ Caps Lock Num Lock ]
keysyms [ a         ] unicode [ a ] group [ English (US) (0) ] mods [ Shift Lock Control Mod1 Mod2 Mod4 NumLock Alt Meta Super ] leds [ Caps Lock Num Lock ]

Previously, NumLock, Alt, Meta, Super would not be here.

To facilitate this support, we also add #defines for the names of the
Meta, Super, Hyper and NumLock modifiers. These are set freely in
xkeyboard-config, but are essentially treated as ABI there. Also, the
standard explicitly recommends the names for NumLock, Alt and Meta:
http://www.x.org/releases/X11R7.6/doc/libX11/specs/XKB/xkblib.html#conventions
We also change the define of Alt from "Mod1" to "Alt"; this is more
correct, and safe. "Mod1" should continue to work as before.

One case that needs special consideration are the
xkb_state_mod_indices_are_active() and mod_names_are_active() functions.
By default, they perform an exclusive match on the modifiers that are
passed to them. With virtual modifiers in the mix, you often get
unexpected modifiers as well, which break it. I'm not really sure have
exclusive-by-default is a good idea, because it also breaks when the
user just pressed Num Lock of Caps Lock. However, for now we just revert
to the old behavior of real-mods-only for these functions, which should
be fine in most cases. We can revisit this later, when something more
clever comes to mind.

***

To get the virtual modifiers in, we essentially change just two things:
1. When SetMods/LockMods(modifiers=modMapMods) is used, we also add the
   modifiers in the key's vmodmap (in addition the key's modmap). The
   vmodmap of a key is set by virtualMod fields in interprets, or
   directly in the 'key' statements in xkb_symbols. It essentially
   contains the virtual modifiers that are bound to this key.

2. We no longer mask out virtual modifiers from the effective modifier
   masks in types, actions and indicators. This means mostly that if a
   type specifies e.g. "map[NumLock+LevelThree] = Level4", the active
   modifier mask in the state will in fact be matched against the
   NumLock and LevelThree modifiers. Together with 1, this works out
   nicely, and our tests all pass.

Signed-off-by: Ran Benita <ran234@gmail.com>
vmod: bring back support for direct vmod -> real mod mapping

This brings back the functionality that was removed in
b9c87eb710ba4a86455601ca8c5a516b25e20366. Though it is not used in
xkeyboard-config, from our current perspective it can be quite useful to
be able to set the mappings directly, thus sidestepping the ugly and
legacy-ridden modifier_map statement.

Here's an example of how to get rid of modifier_map statements (though
that would break core-X11 applications, since they must have the
mappings through keysyms):
    virtual_modifiers NumLock = Mod2;
    virtual_modifiers Alt = Mod1;
    // Would be nice to map these to Alt, but that would be
    // incompatible with xkbcomp and somewhat complicated
    virtual_modifiers LAlt = Mod1;
    virtual_modifiers RAlt = Mod1;
    virtual_modifiers LevelThree = Mod5;
    virtual_modifiers RControl = Control;
    virtual_modifiers LControl = Control;
    virtual_modifiers Super = Mod4;
    virtual_modifiers Meta = Mod1;
    virtual_modifiers Hyper = Mod4;
    virtual_modifiers AltGr = Mod5;
    virtual_modifiers LShift = Shift;
    virtual_modifiers RShift = Shift;

Signed-off-by: Ran Benita <ran234@gmail.com>
state: support directly setting LED state

See the comments for an explanation and the API (note the disclaimers).

Going from leds to modifier/group state is not generally possible. This
commit only implements the most basic case of a LED which is bound to a
locked modifier (or modifiers). The tests suggest this works fine for
Caps Lock and Num Lock, which should cover about 99% of the uses of
this function. For anything else we just do nothing; if someone
complains we can look into it.

Signed-off-by: Ran Benita <ran234@gmail.com>