From: Daniel Stone Date: Wed, 8 Aug 2012 12:26:23 +0000 (+0200) Subject: Add xkb_map_mod_mask_remove_consumed X-Git-Tag: xkbcommon-0.2.0~284 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2f1f1bca5b28807293920e613de6c9ff705853bf;p=platform%2Fupstream%2Flibxkbcommon.git Add xkb_map_mod_mask_remove_consumed A fairly simple helper which, given an xkb_mod_mask_t, removes all modifiers which are consumed during processing of a particular key. Signed-off-by: Daniel Stone --- diff --git a/src/map.c b/src/map.c index aa6b08b..4a7ce31 100644 --- a/src/map.c +++ b/src/map.c @@ -346,6 +346,24 @@ xkb_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc) return XkbKey(keymap, kc)->repeats; } +static struct xkb_kt_map_entry * +get_entry_for_key_state(struct xkb_state *state, struct xkb_key_type *type, + xkb_keycode_t kc) +{ + xkb_mod_mask_t active_mods; + unsigned int i; + + active_mods = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE); + active_mods &= type->mods.mask; + + for (i = 0; i < type->num_entries; i++) { + if (type->map[i].mods.mask == active_mods) + return &type->map[i]; + } + + return NULL; +} + /** * Tests to see if a modifier is used up by our translation of a * keycode to keysyms, taking note of the current modifier state and @@ -363,29 +381,47 @@ xkb_key_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc, xkb_mod_index_t idx) { struct xkb_keymap *keymap = xkb_state_get_map(state); - xkb_group_index_t group; struct xkb_key_type *type; - unsigned int i; - struct xkb_kt_map_entry *entry = NULL; - xkb_mod_mask_t active_mods; + struct xkb_kt_map_entry *entry; + xkb_group_index_t group; if (!XkbKeycodeInRange(keymap, kc)) return 0; group = xkb_key_get_group(state, kc); type = XkbKeyType(keymap, XkbKey(keymap, kc), group); - active_mods = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE); - active_mods &= type->mods.mask; + entry = get_entry_for_key_state(state, type, kc); + if (!entry) + return 0; - for (i = 0; i < type->num_entries; i++) { - if (type->map[i].mods.mask == active_mods) { - entry = &type->map[i]; - break; - } - } + return !!((type->mods.mask & (~entry->preserve.mask)) & (1 << idx)); +} +/** + * Calculates which modifiers should be consumed during key processing, + * and returns the mask with all these modifiers removed. e.g. if + * given a state of Alt and Shift active for a two-level alphabetic + * key containing plus and equal on the first and second level + * respectively, will return a mask of only Alt, as Shift has been + * consumed by the type handling. + */ +XKB_EXPORT xkb_mod_mask_t +xkb_key_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc, + xkb_mod_mask_t mask) +{ + struct xkb_keymap *keymap = xkb_state_get_map(state); + struct xkb_key_type *type; + struct xkb_kt_map_entry *entry; + xkb_group_index_t group; + + if (!XkbKeycodeInRange(keymap, kc)) + return 0; + + group = xkb_key_get_group(state, kc); + type = XkbKeyType(keymap, XkbKey(keymap, kc), group); + entry = get_entry_for_key_state(state, type, kc); if (!entry) return 0; - return !!((type->mods.mask & (~entry->preserve.mask)) & (1 << idx)); + return mask & ~(type->mods.mask & ~entry->preserve.mask); } diff --git a/test/state.c b/test/state.c index 4eccb34..d4f61ef 100644 --- a/test/state.c +++ b/test/state.c @@ -236,6 +236,36 @@ test_repeat(struct xkb_keymap *keymap) assert(xkb_key_repeats(keymap, KEY_KBDILLUMDOWN + 8)); } +static void +test_consume(struct xkb_keymap *keymap) +{ + struct xkb_state *state = xkb_state_new(keymap); + xkb_mod_index_t alt, shift; + xkb_mod_mask_t mask; + + assert(state); + + alt = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_ALT); + assert(alt != XKB_MOD_INVALID); + shift = xkb_map_mod_get_index(keymap, XKB_MOD_NAME_SHIFT); + assert(shift != XKB_MOD_INVALID); + + xkb_state_update_key(state, KEY_LEFTALT + EVDEV_OFFSET, XKB_KEY_DOWN); + xkb_state_update_key(state, KEY_LEFTSHIFT + EVDEV_OFFSET, XKB_KEY_DOWN); + xkb_state_update_key(state, KEY_EQUAL + EVDEV_OFFSET, XKB_KEY_DOWN); + + fprintf(stderr, "dumping state for Alt-Shift-+\n"); + print_state(state); + + mask = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE); + assert(mask == ((1 << alt) | (1 << shift))); + mask = xkb_key_mod_mask_remove_consumed(state, KEY_EQUAL + EVDEV_OFFSET, + mask); + assert(mask == (1 << alt)); + + xkb_state_unref(state); +} + int main(void) { @@ -250,6 +280,7 @@ main(void) test_update_key(keymap); test_serialisation(keymap); test_repeat(keymap); + test_consume(keymap); xkb_map_unref(keymap); xkb_context_unref(context); diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h index 6afe5e1..0c2f06f 100644 --- a/xkbcommon/xkbcommon.h +++ b/xkbcommon/xkbcommon.h @@ -657,6 +657,15 @@ xkb_key_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key, xkb_mod_index_t idx); /** + * Takes the given modifier mask, and removes all modifiers which are + * marked as 'consumed' (see xkb_key_mod_index_is_consumed definition) + * for that particular key. + */ +xkb_mod_mask_t +xkb_key_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t key, + xkb_mod_mask_t mask); + +/** * Returns 1 if the modifiers specified by the varargs (treated as * xkb_mod_index_t, terminated with XKB_MOD_INVALID) are active in the manner * specified by 'match' and 'type', 0 otherwise, or -1 if the modifier does not