summaryrefslogtreecommitdiff
path: root/src/state.c
diff options
context:
space:
mode:
authorRan Benita <ran234@gmail.com>2014-08-18 20:27:07 +0300
committerRan Benita <ran234@gmail.com>2014-08-18 21:46:39 +0300
commita1f0595a683a167901a2f1d9f02b9b637bd762a6 (patch)
tree7e21cc7ff33fd45b879d41b29404c2a623d79bc1 /src/state.c
parent99184f1614548722e3531e55bb19ac74327c98cb (diff)
downloadxorg-lib-libxkbcommon-a1f0595a683a167901a2f1d9f02b9b637bd762a6.tar.gz
state: make sure the mods are fully resolved after xkb_state_update_mask()
Virtual modifiers can have "mappings" to real modifiers, e.g. NumLock may also set Mod2. In a normal turn of events, the various components (depressed, latched, locked, and consequently effective) include the mapped mods, because the masks are pre-resolved everywhere. However, xkb_state_update_mask() accepts arbitrary mod masks, which may not be resolved (if it comes from somewhere other than xkb_state_serialize_mods()). So let's always resolve them ourselves. Signed-off-by: Ran Benita <ran234@gmail.com>
Diffstat (limited to 'src/state.c')
-rw-r--r--src/state.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/src/state.c b/src/state.c
index 279a646..6613969 100644
--- a/src/state.c
+++ b/src/state.c
@@ -797,6 +797,27 @@ xkb_state_update_mask(struct xkb_state *state,
state->components.latched_mods = latched_mods & mask;
state->components.locked_mods = locked_mods & mask;
+ /* Make sure the mods are fully resolved - since we get arbitrary
+ * input, they might not be.
+ *
+ * It might seem more reasonable to do this only for components.mods
+ * in xkb_state_update_derived(), rather than for each component
+ * seperately. That would allow to distinguish between "really"
+ * depressed mods (would be in MODS_DEPRESSED) and indirectly
+ * depressed to to a mapping (would only be in MODS_EFFECTIVE).
+ * However, the traditional behavior of xkb_state_update_key() is that
+ * if a vmod is depressed, its mappings are depressed with it; so we're
+ * expected to do the same here. Also, LEDs (usually) look if a real
+ * mod is locked, not just effective; otherwise it won't be lit.
+ *
+ * We OR here because mod_mask_get_effective() drops vmods. */
+ state->components.base_mods |=
+ mod_mask_get_effective(state->keymap, state->components.base_mods);
+ state->components.latched_mods |=
+ mod_mask_get_effective(state->keymap, state->components.latched_mods);
+ state->components.locked_mods |=
+ mod_mask_get_effective(state->keymap, state->components.locked_mods);
+
state->components.base_group = base_group;
state->components.latched_group = latched_group;
state->components.locked_group = locked_group;