Skip to content

Commit

Permalink
state: add xkb_state_get_consumed_mods2 with an added mode parameter
Browse files Browse the repository at this point in the history
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).

xkbcommon#17

Signed-off-by: Ran Benita <[email protected]>
  • Loading branch information
bluetech committed Feb 27, 2016
1 parent 8028991 commit f056992
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 47 deletions.
76 changes: 42 additions & 34 deletions src/state.c
Original file line number Diff line number Diff line change
Expand Up @@ -1313,41 +1313,40 @@ 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)
return 0;

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)
Expand All @@ -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)
Expand All @@ -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);
}
1 change: 1 addition & 0 deletions xkbcommon.map
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
68 changes: 55 additions & 13 deletions xkbcommon/xkbcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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+<Backspace>` produces some assigned keysym,
* then when pressing just `<Backspace>`, `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.
*
Expand All @@ -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()).
*
Expand All @@ -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.
*
Expand Down

0 comments on commit f056992

Please sign in to comment.