1 /************************************************************
2 * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
4 * Permission to use, copy, modify, and distribute this
5 * software and its documentation for any purpose and without
6 * fee is hereby granted, provided that the above copyright
7 * notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting
9 * documentation, and that the name of Silicon Graphics not be
10 * used in advertising or publicity pertaining to distribution
11 * of the software without specific prior written permission.
12 * Silicon Graphics makes no representation about the suitability
13 * of this software for any purpose. It is provided "as is"
14 * without any express or implied warranty.
16 * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 * THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
28 * Copyright © 2012 Intel Corporation
29 * Copyright © 2012 Ran Benita <ran234@gmail.com>
31 * Permission is hereby granted, free of charge, to any person obtaining a
32 * copy of this software and associated documentation files (the "Software"),
33 * to deal in the Software without restriction, including without limitation
34 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35 * and/or sell copies of the Software, and to permit persons to whom the
36 * Software is furnished to do so, subject to the following conditions:
38 * The above copyright notice and this permission notice (including the next
39 * paragraph) shall be included in all copies or substantial portions of the
42 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
45 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
48 * DEALINGS IN THE SOFTWARE.
50 * Author: Daniel Stone <daniel@fooishbar.org>
54 * This is a bastardised version of xkbActions.c from the X server which
55 * does not support, for the moment:
56 * - AccessX sticky/debounce/etc (will come later)
57 * - pointer keys (may come later)
58 * - key redirects (unlikely)
59 * - messages (very unlikely)
65 union xkb_action action;
66 const struct xkb_key *key;
68 int (*func)(struct xkb_state *state,
69 struct xkb_filter *filter,
70 const struct xkb_key *key,
71 enum xkb_key_direction direction);
75 struct state_components {
76 /* These may be negative, because of -1 group actions. */
77 int32_t base_group; /**< depressed */
78 int32_t latched_group;
80 xkb_layout_index_t group; /**< effective */
82 xkb_mod_mask_t base_mods; /**< depressed */
83 xkb_mod_mask_t latched_mods;
84 xkb_mod_mask_t locked_mods;
85 xkb_mod_mask_t mods; /**< effective */
91 struct state_components cur;
94 * At each event, we accumulate all the needed modifications to the base
95 * modifiers, and apply them at the end. These keep track of this state.
97 xkb_mod_mask_t set_mods;
98 xkb_mod_mask_t clear_mods;
100 * We mustn't clear a base modifier if there's another depressed key
101 * which affects it, e.g. given this sequence
102 * < Left Shift down, Right Shift down, Left Shift Up >
103 * the modifier should still be set. This keeps the count.
105 int16_t mod_key_count[sizeof(xkb_mod_mask_t) * 8];
108 darray(struct xkb_filter) filters;
109 struct xkb_keymap *keymap;
112 static const struct xkb_kt_map_entry *
113 get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
114 xkb_layout_index_t group)
116 const struct xkb_key_type *type;
117 xkb_mod_mask_t active_mods;
120 type = key->groups[group].type;
121 active_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
122 active_mods &= type->mods.mask;
124 for (i = 0; i < type->num_entries; i++)
125 if (type->map[i].mods.mask == active_mods)
126 return &type->map[i];
132 * Returns the level to use for the given key and state, or
135 XKB_EXPORT xkb_level_index_t
136 xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
137 xkb_layout_index_t layout)
139 const struct xkb_key *key = XkbKey(state->keymap, kc);
140 const struct xkb_kt_map_entry *entry;
142 if (!key || layout >= key->num_groups)
143 return XKB_LEVEL_INVALID;
145 /* If we don't find an explicit match the default is 0. */
146 entry = get_entry_for_key_state(state, key, layout);
153 static xkb_layout_index_t
154 wrap_group_into_range(int32_t group,
155 xkb_layout_index_t num_groups,
156 enum xkb_range_exceed_type out_of_range_group_action,
157 xkb_layout_index_t out_of_range_group_number)
160 return XKB_LAYOUT_INVALID;
162 if (group < num_groups)
165 switch (out_of_range_group_action) {
167 if (out_of_range_group_number >= num_groups)
169 return out_of_range_group_number;
175 return num_groups - 1;
180 * C99 says a negative dividend in a modulo operation always
181 * gives a negative result.
184 return ((int) num_groups + (group % (int) num_groups));
186 return group % num_groups;
191 * Returns the layout to use for the given key and state, taking
192 * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
194 XKB_EXPORT xkb_layout_index_t
195 xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
197 xkb_layout_index_t group =
198 xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE);
199 const struct xkb_key *key = XkbKey(state->keymap, kc);
202 return XKB_LAYOUT_INVALID;
204 return wrap_group_into_range(group, key->num_groups,
205 key->out_of_range_group_action,
206 key->out_of_range_group_number);
209 static const union xkb_action fake = { .type = ACTION_TYPE_NONE };
211 static const union xkb_action *
212 xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
214 xkb_layout_index_t layout;
215 xkb_level_index_t level;
217 layout = xkb_state_key_get_layout(state, key->keycode);
218 if (layout == XKB_LAYOUT_INVALID)
221 level = xkb_state_key_get_level(state, key->keycode, layout);
222 if (level == XKB_LEVEL_INVALID)
225 return &key->groups[layout].levels[level].action;
228 static struct xkb_filter *
229 xkb_filter_new(struct xkb_state *state)
231 struct xkb_filter *filter = NULL, *iter;
233 darray_foreach(iter, state->filters) {
241 darray_resize0(state->filters, darray_size(state->filters) + 1);
242 filter = &darray_item(state->filters, darray_size(state->filters) -1);
249 /***====================================================================***/
252 xkb_filter_group_set_func(struct xkb_state *state,
253 struct xkb_filter *filter,
254 const struct xkb_key *key,
255 enum xkb_key_direction direction)
257 if (key != filter->key) {
258 filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
262 if (direction == XKB_KEY_DOWN) {
266 else if (--filter->refcnt > 0) {
270 state->cur.base_group = filter->priv;
272 if (filter->action.group.flags & ACTION_LOCK_CLEAR)
273 state->cur.locked_group = 0;
280 xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
282 filter->priv = state->cur.base_group;
283 if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
284 state->cur.base_group = filter->action.group.group;
286 state->cur.base_group += filter->action.group.group;
290 xkb_filter_group_lock_func(struct xkb_state *state,
291 struct xkb_filter *filter,
292 const struct xkb_key *key,
293 enum xkb_key_direction direction)
295 if (key != filter->key)
298 if (direction == XKB_KEY_DOWN) {
302 if (--filter->refcnt > 0)
310 xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
312 if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
313 state->cur.locked_group = filter->action.group.group;
315 state->cur.locked_group += filter->action.group.group;
319 xkb_filter_mod_set_func(struct xkb_state *state,
320 struct xkb_filter *filter,
321 const struct xkb_key *key,
322 enum xkb_key_direction direction)
324 if (key != filter->key) {
325 filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
329 if (direction == XKB_KEY_DOWN) {
333 else if (--filter->refcnt > 0) {
337 state->clear_mods = filter->action.mods.mods.mask;
338 if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
339 state->cur.locked_mods &= ~filter->action.mods.mods.mask;
346 xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
348 state->set_mods = filter->action.mods.mods.mask;
352 xkb_filter_mod_lock_func(struct xkb_state *state,
353 struct xkb_filter *filter,
354 const struct xkb_key *key,
355 enum xkb_key_direction direction)
357 if (key != filter->key)
360 if (direction == XKB_KEY_DOWN) {
364 if (--filter->refcnt > 0)
367 state->clear_mods |= filter->action.mods.mods.mask;
368 if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
369 state->cur.locked_mods &= ~filter->priv;
376 xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
378 filter->priv = state->cur.locked_mods & filter->action.mods.mods.mask;
379 state->set_mods |= filter->action.mods.mods.mask;
380 if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
381 state->cur.locked_mods |= filter->action.mods.mods.mask;
384 enum xkb_key_latch_state {
391 xkb_action_breaks_latch(const union xkb_action *action)
393 switch (action->type) {
394 case ACTION_TYPE_NONE:
395 case ACTION_TYPE_PTR_BUTTON:
396 case ACTION_TYPE_PTR_LOCK:
397 case ACTION_TYPE_CTRL_SET:
398 case ACTION_TYPE_CTRL_LOCK:
399 case ACTION_TYPE_KEY_REDIRECT:
400 case ACTION_TYPE_SWITCH_VT:
401 case ACTION_TYPE_TERMINATE:
409 xkb_filter_mod_latch_func(struct xkb_state *state,
410 struct xkb_filter *filter,
411 const struct xkb_key *key,
412 enum xkb_key_direction direction)
414 enum xkb_key_latch_state latch = filter->priv;
416 if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
417 /* If this is a new keypress and we're awaiting our single latched
418 * keypress, then either break the latch if any random key is pressed,
419 * or promote it to a lock or plain base set if it's the same
421 const union xkb_action *action = xkb_key_get_action(state, key);
422 if (action->type == ACTION_TYPE_MOD_LATCH &&
423 action->mods.flags == filter->action.mods.flags &&
424 action->mods.mods.mask == filter->action.mods.mods.mask) {
425 filter->action = *action;
426 if (filter->action.mods.flags & ACTION_LATCH_TO_LOCK) {
427 filter->action.type = ACTION_TYPE_MOD_LOCK;
428 filter->func = xkb_filter_mod_lock_func;
429 state->cur.locked_mods |= filter->action.mods.mods.mask;
432 filter->action.type = ACTION_TYPE_MOD_SET;
433 filter->func = xkb_filter_mod_set_func;
434 state->set_mods = filter->action.mods.mods.mask;
437 state->cur.latched_mods &= ~filter->action.mods.mods.mask;
441 else if (xkb_action_breaks_latch(action)) {
442 /* XXX: This may be totally broken, we might need to break the
443 * latch in the next run after this press? */
444 state->cur.latched_mods &= ~filter->action.mods.mods.mask;
449 else if (direction == XKB_KEY_UP && key == filter->key) {
450 /* Our key got released. If we've set it to clear locks, and we
451 * currently have the same modifiers locked, then release them and
452 * don't actually latch. Else we've actually hit the latching
453 * stage, so set PENDING and move our modifier from base to
455 if (latch == NO_LATCH ||
456 ((filter->action.mods.flags & ACTION_LOCK_CLEAR) &&
457 (state->cur.locked_mods & filter->action.mods.mods.mask) ==
458 filter->action.mods.mods.mask)) {
459 /* XXX: We might be a bit overenthusiastic about clearing
460 * mods other filters have set here? */
461 if (latch == LATCH_PENDING)
462 state->cur.latched_mods &= ~filter->action.mods.mods.mask;
464 state->clear_mods = filter->action.mods.mods.mask;
465 state->cur.locked_mods &= ~filter->action.mods.mods.mask;
469 latch = LATCH_PENDING;
470 state->clear_mods = filter->action.mods.mods.mask;
471 state->cur.latched_mods |= filter->action.mods.mods.mask;
475 else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
476 /* Someone's pressed another key while we've still got the latching
477 * key held down, so keep the base modifier state active (from
478 * xkb_filter_mod_latch_new), but don't trip the latch, just clear
479 * it as soon as the modifier gets released. */
483 filter->priv = latch;
489 xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
491 filter->priv = LATCH_KEY_DOWN;
492 state->set_mods = filter->action.mods.mods.mask;
495 static const struct {
496 void (*new)(struct xkb_state *state, struct xkb_filter *filter);
497 int (*func)(struct xkb_state *state, struct xkb_filter *filter,
498 const struct xkb_key *key, enum xkb_key_direction direction);
499 } filter_action_funcs[_ACTION_TYPE_NUM_ENTRIES] = {
500 [ACTION_TYPE_MOD_SET] = { xkb_filter_mod_set_new,
501 xkb_filter_mod_set_func },
502 [ACTION_TYPE_MOD_LATCH] = { xkb_filter_mod_latch_new,
503 xkb_filter_mod_latch_func },
504 [ACTION_TYPE_MOD_LOCK] = { xkb_filter_mod_lock_new,
505 xkb_filter_mod_lock_func },
506 [ACTION_TYPE_GROUP_SET] = { xkb_filter_group_set_new,
507 xkb_filter_group_set_func },
508 [ACTION_TYPE_GROUP_LOCK] = { xkb_filter_group_lock_new,
509 xkb_filter_group_lock_func },
513 * Applies any relevant filters to the key, first from the list of filters
514 * that are currently active, then if no filter has claimed the key, possibly
515 * apply a new filter from the key action.
518 xkb_filter_apply_all(struct xkb_state *state,
519 const struct xkb_key *key,
520 enum xkb_key_direction direction)
522 struct xkb_filter *filter;
523 const union xkb_action *action;
526 /* First run through all the currently active filters and see if any of
527 * them have claimed this event. */
528 darray_foreach(filter, state->filters) {
531 send &= filter->func(state, filter, key, direction);
534 if (!send || direction == XKB_KEY_UP)
537 action = xkb_key_get_action(state, key);
538 if (!filter_action_funcs[action->type].new)
541 filter = xkb_filter_new(state);
546 filter->func = filter_action_funcs[action->type].func;
547 filter->action = *action;
548 filter_action_funcs[action->type].new(state, filter);
551 XKB_EXPORT struct xkb_state *
552 xkb_state_new(struct xkb_keymap *keymap)
554 struct xkb_state *ret;
556 ret = calloc(sizeof(*ret), 1);
561 ret->keymap = xkb_keymap_ref(keymap);
566 XKB_EXPORT struct xkb_state *
567 xkb_state_ref(struct xkb_state *state)
574 xkb_state_unref(struct xkb_state *state)
576 if (--state->refcnt > 0)
579 xkb_keymap_unref(state->keymap);
580 darray_free(state->filters);
584 XKB_EXPORT struct xkb_keymap *
585 xkb_state_get_keymap(struct xkb_state *state)
587 return state->keymap;
591 * Update the LED state to match the rest of the xkb_state.
594 xkb_state_led_update_all(struct xkb_state *state)
597 const struct xkb_indicator_map *map;
601 darray_enumerate(led, map, state->keymap->indicators) {
602 xkb_mod_mask_t mod_mask = 0;
603 xkb_layout_mask_t group_mask = 0;
605 if (map->which_mods & XKB_STATE_MODS_EFFECTIVE)
606 mod_mask |= state->cur.mods;
607 if (map->which_mods & XKB_STATE_MODS_DEPRESSED)
608 mod_mask |= state->cur.base_mods;
609 if (map->which_mods & XKB_STATE_MODS_LATCHED)
610 mod_mask |= state->cur.latched_mods;
611 if (map->which_mods & XKB_STATE_MODS_LOCKED)
612 mod_mask |= state->cur.locked_mods;
613 if (map->mods.mask & mod_mask)
614 state->cur.leds |= (1 << led);
616 if (map->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
617 group_mask |= (1 << state->cur.group);
618 if (map->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
619 group_mask |= (1 << state->cur.base_group);
620 if (map->which_groups & XKB_STATE_LAYOUT_LATCHED)
621 group_mask |= (1 << state->cur.latched_group);
622 if (map->which_groups & XKB_STATE_LAYOUT_LOCKED)
623 group_mask |= (1 << state->cur.locked_group);
624 if (map->groups & group_mask)
625 state->cur.leds |= (1 << led);
627 if (map->ctrls & state->keymap->enabled_ctrls)
628 state->cur.leds |= (1 << led);
633 * Calculates the derived state (effective mods/group and LEDs) from an
634 * up-to-date xkb_state.
637 xkb_state_update_derived(struct xkb_state *state)
639 xkb_layout_index_t num_groups = xkb_keymap_num_layouts(state->keymap);
641 state->cur.mods = (state->cur.base_mods |
642 state->cur.latched_mods |
643 state->cur.locked_mods);
645 /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
647 state->cur.locked_group = wrap_group_into_range(state->cur.locked_group,
651 state->cur.group = wrap_group_into_range(state->cur.base_group +
652 state->cur.latched_group +
653 state->cur.locked_group,
657 xkb_state_led_update_all(state);
661 * Given a particular key event, updates the state structure to reflect the
665 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
666 enum xkb_key_direction direction)
670 const struct xkb_key *key = XkbKey(state->keymap, kc);
676 state->clear_mods = 0;
678 xkb_filter_apply_all(state, key, direction);
680 for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
681 if (state->set_mods & bit) {
682 state->mod_key_count[i]++;
683 state->cur.base_mods |= bit;
684 state->set_mods &= ~bit;
688 for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
689 if (state->clear_mods & bit) {
690 state->mod_key_count[i]--;
691 if (state->mod_key_count[i] <= 0) {
692 state->cur.base_mods &= ~bit;
693 state->mod_key_count[i] = 0;
695 state->clear_mods &= ~bit;
699 xkb_state_update_derived(state);
703 * Updates the state from a set of explicit masks as gained from
704 * xkb_state_serialize_mods and xkb_state_serialize_groups. As noted in the
705 * documentation for these functions in xkbcommon.h, this round-trip is
706 * lossy, and should only be used to update a slave state mirroring the
707 * master, e.g. in a client/server window system.
710 xkb_state_update_mask(struct xkb_state *state,
711 xkb_mod_mask_t base_mods,
712 xkb_mod_mask_t latched_mods,
713 xkb_mod_mask_t locked_mods,
714 xkb_layout_index_t base_group,
715 xkb_layout_index_t latched_group,
716 xkb_layout_index_t locked_group)
718 xkb_mod_index_t num_mods;
721 state->cur.base_mods = 0;
722 state->cur.latched_mods = 0;
723 state->cur.locked_mods = 0;
724 num_mods = xkb_keymap_num_mods(state->keymap);
726 for (idx = 0; idx < num_mods; idx++) {
727 xkb_mod_mask_t mod = (1 << idx);
729 state->cur.base_mods |= mod;
730 if (latched_mods & mod)
731 state->cur.latched_mods |= mod;
732 if (locked_mods & mod)
733 state->cur.locked_mods |= mod;
736 state->cur.base_group = base_group;
737 state->cur.latched_group = latched_group;
738 state->cur.locked_group = locked_group;
740 xkb_state_update_derived(state);
744 * Provides the symbols to use for the given key and state. Returns the
745 * number of symbols pointed to in syms_out.
748 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
749 const xkb_keysym_t **syms_out)
751 xkb_layout_index_t layout;
752 xkb_level_index_t level;
754 layout = xkb_state_key_get_layout(state, kc);
755 if (layout == XKB_LAYOUT_INVALID)
758 level = xkb_state_key_get_level(state, kc, layout);
759 if (level == XKB_LEVEL_INVALID)
762 return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
771 * Provides either exactly one symbol, or XKB_KEY_NoSymbol.
773 XKB_EXPORT xkb_keysym_t
774 xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
776 const xkb_keysym_t *syms;
779 num_syms = xkb_state_key_get_syms(state, kc, &syms);
781 return XKB_KEY_NoSymbol;
787 * Serialises the requested modifier state into an xkb_mod_mask_t, with all
788 * the same disclaimers as in xkb_state_update_mask.
790 XKB_EXPORT xkb_mod_mask_t
791 xkb_state_serialize_mods(struct xkb_state *state,
792 enum xkb_state_component type)
794 xkb_mod_mask_t ret = 0;
796 if (type & XKB_STATE_MODS_EFFECTIVE)
797 return state->cur.mods;
799 if (type & XKB_STATE_MODS_DEPRESSED)
800 ret |= state->cur.base_mods;
801 if (type & XKB_STATE_MODS_LATCHED)
802 ret |= state->cur.latched_mods;
803 if (type & XKB_STATE_MODS_LOCKED)
804 ret |= state->cur.locked_mods;
810 * Serialises the requested group state, with all the same disclaimers as
811 * in xkb_state_update_mask.
813 XKB_EXPORT xkb_layout_index_t
814 xkb_state_serialize_layout(struct xkb_state *state,
815 enum xkb_state_component type)
817 xkb_layout_index_t ret = 0;
819 if (type & XKB_STATE_LAYOUT_EFFECTIVE)
820 return state->cur.group;
822 if (type & XKB_STATE_LAYOUT_DEPRESSED)
823 ret += state->cur.base_group;
824 if (type & XKB_STATE_LAYOUT_LATCHED)
825 ret += state->cur.latched_group;
826 if (type & XKB_STATE_LAYOUT_LOCKED)
827 ret += state->cur.locked_group;
833 * Returns 1 if the given modifier is active with the specified type(s), 0 if
834 * not, or -1 if the modifier is invalid.
837 xkb_state_mod_index_is_active(struct xkb_state *state,
839 enum xkb_state_component type)
841 if (idx >= xkb_keymap_num_mods(state->keymap))
844 return !!(xkb_state_serialize_mods(state, type) & (1 << idx));
848 * Helper function for xkb_state_mod_indices_are_active and
849 * xkb_state_mod_names_are_active.
852 match_mod_masks(struct xkb_state *state,
853 enum xkb_state_component type,
854 enum xkb_state_match match,
855 xkb_mod_mask_t wanted)
857 xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
859 if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
862 if (match & XKB_STATE_MATCH_ANY)
863 return !!(active & wanted);
865 return (active & wanted) == wanted;
871 * Returns 1 if the modifiers are active with the specified type(s), 0 if
872 * not, or -1 if any of the modifiers are invalid.
875 xkb_state_mod_indices_are_active(struct xkb_state *state,
876 enum xkb_state_component type,
877 enum xkb_state_match match,
881 xkb_mod_index_t idx = 0;
882 xkb_mod_mask_t wanted = 0;
884 xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
888 idx = va_arg(ap, xkb_mod_index_t);
889 if (idx == XKB_MOD_INVALID)
891 if (idx >= num_mods) {
895 wanted |= (1 << idx);
902 return match_mod_masks(state, type, match, wanted);
906 * Returns 1 if the given modifier is active with the specified type(s), 0 if
907 * not, or -1 if the modifier is invalid.
910 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
911 enum xkb_state_component type)
913 xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
915 if (idx == XKB_MOD_INVALID)
918 return xkb_state_mod_index_is_active(state, idx, type);
922 * Returns 1 if the modifiers are active with the specified type(s), 0 if
923 * not, or -1 if any of the modifiers are invalid.
925 XKB_EXPORT ATTR_NULL_SENTINEL int
926 xkb_state_mod_names_are_active(struct xkb_state *state,
927 enum xkb_state_component type,
928 enum xkb_state_match match,
932 xkb_mod_index_t idx = 0;
934 xkb_mod_mask_t wanted = 0;
939 str = va_arg(ap, const char *);
942 idx = xkb_keymap_mod_get_index(state->keymap, str);
943 if (idx == XKB_MOD_INVALID) {
947 wanted |= (1 << idx);
954 return match_mod_masks(state, type, match, wanted);
958 * Returns 1 if the given group is active with the specified type(s), 0 if
959 * not, or -1 if the group is invalid.
962 xkb_state_layout_index_is_active(struct xkb_state *state,
963 xkb_layout_index_t idx,
964 enum xkb_state_component type)
968 if (idx >= xkb_keymap_num_layouts(state->keymap))
971 if (type & XKB_STATE_LAYOUT_EFFECTIVE)
972 ret |= (state->cur.group == idx);
973 if (type & XKB_STATE_LAYOUT_DEPRESSED)
974 ret |= (state->cur.base_group == idx);
975 if (type & XKB_STATE_LAYOUT_LATCHED)
976 ret |= (state->cur.latched_group == idx);
977 if (type & XKB_STATE_LAYOUT_LOCKED)
978 ret |= (state->cur.locked_group == idx);
984 * Returns 1 if the given modifier is active with the specified type(s), 0 if
985 * not, or -1 if the modifier is invalid.
988 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
989 enum xkb_state_component type)
991 xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
993 if (idx == XKB_LAYOUT_INVALID)
996 return xkb_state_layout_index_is_active(state, idx, type);
1000 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1003 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1005 if (idx >= darray_size(state->keymap->indicators) ||
1006 darray_item(state->keymap->indicators, idx).name == XKB_ATOM_NONE)
1009 return !!(state->cur.leds & (1 << idx));
1013 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1016 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1018 xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1020 if (idx == XKB_LED_INVALID)
1023 return xkb_state_led_index_is_active(state, idx);
1026 static xkb_mod_mask_t
1027 key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
1029 const struct xkb_kt_map_entry *entry;
1030 xkb_layout_index_t group;
1032 group = xkb_state_key_get_layout(state, key->keycode);
1033 if (group == XKB_LAYOUT_INVALID)
1036 entry = get_entry_for_key_state(state, key, group);
1040 return entry->mods.mask & ~entry->preserve.mask;
1044 * Tests to see if a modifier is used up by our translation of a
1045 * keycode to keysyms, taking note of the current modifier state and
1046 * the appropriate key type's preserve information, if any. This allows
1047 * the user to mask out the modifier in later processing of the
1048 * modifiers, e.g. when implementing hot keys or accelerators.
1050 * See also, for example:
1051 * - XkbTranslateKeyCode(3), mod_rtrn retrun value, from libX11.
1052 * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
1056 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1057 xkb_mod_index_t idx)
1059 const struct xkb_key *key = XkbKey(state->keymap, kc);
1061 if (!key || idx >= xkb_keymap_num_mods(state->keymap))
1064 return !!((1 << idx) & key_get_consumed(state, key));
1068 * Calculates which modifiers should be consumed during key processing,
1069 * and returns the mask with all these modifiers removed. e.g. if
1070 * given a state of Alt and Shift active for a two-level alphabetic
1071 * key containing plus and equal on the first and second level
1072 * respectively, will return a mask of only Alt, as Shift has been
1073 * consumed by the type handling.
1075 XKB_EXPORT xkb_mod_mask_t
1076 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1077 xkb_mod_mask_t mask)
1079 const struct xkb_key *key = XkbKey(state->keymap, kc);
1084 return mask & ~key_get_consumed(state, key);