Add API to query whether a modifier is consumed
Currently the user has no way of knowing which of the active modifiers have been used in the translation of a keycode to its keysyms. The use case is described in the GTK docs: say there's a menu accelerator activated by "<Alt>+". Some layouts have "+" shifted, and some have it on the first level. So in keymaps where "+" is shifted, the Shift modifier is consumed and must be ignored when the user is testing for "<Alt>+". Otherwise, we may get "<Alt><Shift>+" and the accelerator should not actually fire. For this we also use the preserve[] information in the key types, which can forces us to report modifiers as unconsumed even if they were used in the translation. Until now we didn't do anything with this information. The API tries to match its surronding. It's not very efficient but this can be fixed. Signed-off-by: Ran Benita <ran234@gmail.com>master
parent
262bf97f9b
commit
1a930bf256
44
src/map.c
44
src/map.c
|
@ -345,3 +345,47 @@ xkb_key_repeats(struct xkb_keymap *keymap, xkb_keycode_t kc)
|
|||
return 0;
|
||||
return XkbKey(keymap, kc)->repeats;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 retrun value, from libX11.
|
||||
* - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
|
||||
* from gtk+.
|
||||
*/
|
||||
XKB_EXPORT int
|
||||
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;
|
||||
xkb_mod_mask_t active_mods;
|
||||
|
||||
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;
|
||||
|
||||
for (i = 0; i < type->num_entries; i++) {
|
||||
if (type->map[i].mods.mask == active_mods) {
|
||||
entry = &type->map[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry)
|
||||
return 0;
|
||||
|
||||
return !!((type->mods.mask & (~entry->preserve.mask)) & (1 << idx));
|
||||
}
|
||||
|
|
|
@ -268,7 +268,10 @@ print_keycode(struct keyboard *kbd, xkb_keycode_t keycode)
|
|||
for (mod = 0; mod < xkb_map_num_mods(keymap); mod++) {
|
||||
if (!xkb_state_mod_index_is_active(state, mod, XKB_STATE_EFFECTIVE))
|
||||
continue;
|
||||
printf("%s ", xkb_map_mod_get_name(keymap, mod));
|
||||
if (xkb_key_mod_index_is_consumed(state, keycode, mod))
|
||||
printf("-%s ", xkb_map_mod_get_name(keymap, mod));
|
||||
else
|
||||
printf("%s ", xkb_map_mod_get_name(keymap, mod));
|
||||
}
|
||||
printf("] ");
|
||||
|
||||
|
|
|
@ -634,6 +634,16 @@ int
|
|||
xkb_state_mod_index_is_active(struct xkb_state *state, xkb_mod_index_t idx,
|
||||
enum xkb_state_component type);
|
||||
|
||||
/**
|
||||
* Returns 1 if the modifier specified by 'idx' is used in the
|
||||
* translation of the keycode 'key' to the key symbols obtained by
|
||||
* pressing it (as in xkb_key_get_syms), given the current state.
|
||||
* Returns 0 otherwise.
|
||||
*/
|
||||
int
|
||||
xkb_key_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t key,
|
||||
xkb_mod_index_t idx);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
Loading…
Reference in New Issue