From f0569929cb95cff881c69c93204e775be4c91309 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 27 Feb 2016 19:06:14 +0200 Subject: [PATCH] state: add xkb_state_get_consumed_mods2 with an added mode parameter The current functions dealing with consumed modifiers use the traditional XKB definition of consumed modifiers (see description in the added documentation). However, for several users of the library (e.g. GTK) this definition is unsuitable or too eager. This is exacerbate by some less-than-ideal xkeyboard-config type definitions (CTRL+ALT seems to cause most grief...). So, because we - want to enable alternative interpretations, but - don't want to expose too much internal details, and - want to keep things simple for all library users, we add a high-level "mode" parameter which selects the desired interpretation. New ones can be added as long as they make some sense. All of the old consumed-modifiers functions keep using the traditional ("XKB") mode. I mark xkb_state_mod_mask_remove_consumed() and xkb_state_mod_index_is_consumed() as deprecated without adding *2 variants for them because I don't think they are very useful (or used) in practice. Alternative modes are added in subsequent commits (this commit only adds mode for existing behavior). https://github.com/xkbcommon/libxkbcommon/issues/17 Signed-off-by: Ran Benita --- src/state.c | 76 ++++++++++++++++++++++++------------------- xkbcommon.map | 1 + xkbcommon/xkbcommon.h | 68 ++++++++++++++++++++++++++++++-------- 3 files changed, 98 insertions(+), 47 deletions(-) diff --git a/src/state.c b/src/state.c index a45315d4..598bb3ef 100644 --- a/src/state.c +++ b/src/state.c @@ -1313,13 +1313,20 @@ xkb_state_led_name_is_active(struct xkb_state *state, const char *name) return xkb_state_led_index_is_active(state, idx); } +/** + * See: + * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11. + * - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+. + */ static xkb_mod_mask_t -key_get_consumed(struct xkb_state *state, const struct xkb_key *key) +key_get_consumed(struct xkb_state *state, const struct xkb_key *key, + enum xkb_consumed_mode mode) { const struct xkb_key_type *type; - const struct xkb_key_type_entry *entry; - xkb_mod_mask_t preserve; + const struct xkb_key_type_entry *matching_entry; + xkb_mod_mask_t preserve = 0; xkb_layout_index_t group; + xkb_mod_mask_t consumed = 0; group = xkb_state_key_get_layout(state, key->keycode); if (group == XKB_LAYOUT_INVALID) @@ -1327,27 +1334,19 @@ key_get_consumed(struct xkb_state *state, const struct xkb_key *key) type = key->groups[group].type; - entry = get_entry_for_key_state(state, key, group); - if (entry) - preserve = entry->preserve.mask; - else - preserve = 0; + matching_entry = get_entry_for_key_state(state, key, group); + if (matching_entry) + preserve = matching_entry->preserve.mask; + + switch (mode) { + case XKB_CONSUMED_MODE_XKB: + consumed = type->mods.mask; + break; + } - return type->mods.mask & ~preserve; + return consumed & ~preserve; } -/** - * 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 - * the appropriate key type's preserve information, if any. This allows - * the user to mask out the modifier in later processing of the - * modifiers, e.g. when implementing hot keys or accelerators. - * - * See also, for example: - * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11. - * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value, - * from gtk+. - */ XKB_EXPORT int xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc, xkb_mod_index_t idx) @@ -1357,17 +1356,9 @@ xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc, if (!key || idx >= xkb_keymap_num_mods(state->keymap)) return -1; - return !!((1u << idx) & key_get_consumed(state, key)); + return !!((1u << idx) & key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB)); } -/** - * 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_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc, xkb_mod_mask_t mask) @@ -1377,16 +1368,33 @@ xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc, if (!key) return 0; - return mask & ~key_get_consumed(state, key); + return mask & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB); } XKB_EXPORT xkb_mod_mask_t -xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc) +xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc, + enum xkb_consumed_mode mode) { - const struct xkb_key *key = XkbKey(state->keymap, kc); + const struct xkb_key *key; + switch (mode) { + case XKB_CONSUMED_MODE_XKB: + break; + default: + log_err_func(state->keymap->ctx, + "unrecognized consumed modifiers mode: %d\n", mode); + return 0; + } + + key = XkbKey(state->keymap, kc); if (!key) return 0; - return key_get_consumed(state, key); + return key_get_consumed(state, key, mode); +} + +XKB_EXPORT xkb_mod_mask_t +xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc) +{ + return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB); } diff --git a/xkbcommon.map b/xkbcommon.map index 29fd7ac9..b1f4f5c1 100644 --- a/xkbcommon.map +++ b/xkbcommon.map @@ -64,6 +64,7 @@ global: xkb_state_mod_index_is_consumed; xkb_state_mod_mask_remove_consumed; xkb_state_key_get_consumed_mods; + xkb_state_key_get_consumed_mods2; xkb_state_layout_name_is_active; xkb_state_layout_index_is_active; xkb_state_led_name_is_active; diff --git a/xkbcommon/xkbcommon.h b/xkbcommon/xkbcommon.h index e46ce445..8c3f73d0 100644 --- a/xkbcommon/xkbcommon.h +++ b/xkbcommon/xkbcommon.h @@ -1649,7 +1649,7 @@ xkb_state_mod_indices_are_active(struct xkb_state *state, * Effectively, this means that consumed modifiers (Shift in this example) * are masked out as well, before doing the comparison. * - * In summary, this is how the matching would be performed: + * In summary, this is approximately how the matching would be performed: * @code * (keysym == shortcut_keysym) && * ((state_mods & ~consumed_mods & significant_mods) == shortcut_mods) @@ -1665,10 +1665,62 @@ xkb_state_mod_indices_are_active(struct xkb_state *state, * @endparblock */ +/** + * Consumed modifiers mode. + * + * There are several possible methods for deciding which modifiers are + * consumed and which are not, each applicable for different systems or + * situations. The mode selects the method to use. + * + * Keep in mind that in all methods, the keymap may decide to "preserve" + * a modifier, meaning it is not reported as consumed even if it would + * have otherwise. + */ +enum xkb_consumed_mode { + /** + * This is the mode defined in the XKB specification and used by libX11. + * + * A modifier is consumed iff it *may affect* key translation. + * + * For example, if `Control+Alt+` produces some assigned keysym, + * then when pressing just ``, `Control` and `Alt` are consumed, + * even though they are not active, since if they *were* active they would + * have affected key translation. + */ + XKB_CONSUMED_MODE_XKB +}; + +/** + * Get the mask of modifiers consumed by translating a given key. + * + * @param state The keyboard state. + * @param key The keycode of the key. + * @param ... The consumed modifiers mode to use; see enum description. + * + * @returns a mask of the consumed modifiers. + * + * @memberof xkb_state + * @since TBD + */ +xkb_mod_mask_t +xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t key, + enum xkb_consumed_mode mode); + +/** + * Same as xkb_state_key_get_consumed_mods2() with mode XKB_CONSUMED_MODE_XKB. + * + * @memberof xkb_state + * @since 0.4.1 + */ +xkb_mod_mask_t +xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key); + /** * Test whether a modifier is consumed by keyboard state translation for * a key. * + * @deprecated Use xkb_state_key_get_consumed_mods2() instead. + * * @returns 1 if the modifier is consumed, 0 if it is not. If the modifier * index is not valid in the keymap, returns -1. * @@ -1683,6 +1735,8 @@ xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key, /** * Remove consumed modifiers from a modifier mask for a key. * + * @deprecated Use xkb_state_key_get_consumed_mods2() instead. + * * Takes the given modifier mask, and removes all modifiers which are * consumed for that particular key (as in xkb_state_mod_index_is_consumed()). * @@ -1693,18 +1747,6 @@ xkb_mod_mask_t xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t key, xkb_mod_mask_t mask); -/** - * Get the mask of modifiers consumed by translating a given key. - * - * @returns a mask of the consumed modifiers. - * - * @sa xkb_state_mod_index_is_consumed() - * @memberof xkb_state - * @since 0.4.1 - */ -xkb_mod_mask_t -xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t key); - /** * Test whether a layout is active in a given keyboard state by name. *