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
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);
}
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)
{
test_update_key(keymap);
test_serialisation(keymap);
test_repeat(keymap);
+ test_consume(keymap);
xkb_map_unref(keymap);
xkb_context_unref(context);
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