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 */
92 * Before updating the state, we keep a copy. This allows us to report
93 * which components of the state have changed.
95 struct state_components cur, prev;
98 * At each event, we accumulate all the needed modifications to the base
99 * modifiers, and apply them at the end. These keep track of this state.
101 xkb_mod_mask_t set_mods;
102 xkb_mod_mask_t clear_mods;
105 * We mustn't clear a base modifier if there's another depressed key
106 * which affects it, e.g. given this sequence
107 * < Left Shift down, Right Shift down, Left Shift Up >
108 * the modifier should still be set. This keeps the count.
110 int16_t mod_key_count[sizeof(xkb_mod_mask_t) * 8];
113 darray(struct xkb_filter) filters;
114 struct xkb_keymap *keymap;
117 static const struct xkb_kt_map_entry *
118 get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
119 xkb_layout_index_t group)
121 const struct xkb_key_type *type;
122 xkb_mod_mask_t active_mods;
125 type = key->groups[group].type;
126 active_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
127 active_mods &= type->mods.mask;
129 for (i = 0; i < type->num_entries; i++)
130 if (type->map[i].mods.mask == active_mods)
131 return &type->map[i];
137 * Returns the level to use for the given key and state, or
140 XKB_EXPORT xkb_level_index_t
141 xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
142 xkb_layout_index_t layout)
144 const struct xkb_key *key = XkbKey(state->keymap, kc);
145 const struct xkb_kt_map_entry *entry;
147 if (!key || layout >= key->num_groups)
148 return XKB_LEVEL_INVALID;
150 /* If we don't find an explicit match the default is 0. */
151 entry = get_entry_for_key_state(state, key, layout);
158 static xkb_layout_index_t
159 wrap_group_into_range(int32_t group,
160 xkb_layout_index_t num_groups,
161 enum xkb_range_exceed_type out_of_range_group_action,
162 xkb_layout_index_t out_of_range_group_number)
165 return XKB_LAYOUT_INVALID;
167 if (group < num_groups)
170 switch (out_of_range_group_action) {
172 if (out_of_range_group_number >= num_groups)
174 return out_of_range_group_number;
180 return num_groups - 1;
185 * C99 says a negative dividend in a modulo operation always
186 * gives a negative result.
189 return ((int) num_groups + (group % (int) num_groups));
191 return group % num_groups;
196 * Returns the layout to use for the given key and state, taking
197 * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
199 XKB_EXPORT xkb_layout_index_t
200 xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
202 xkb_layout_index_t group =
203 xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE);
204 const struct xkb_key *key = XkbKey(state->keymap, kc);
207 return XKB_LAYOUT_INVALID;
209 return wrap_group_into_range(group, key->num_groups,
210 key->out_of_range_group_action,
211 key->out_of_range_group_number);
214 static const union xkb_action fake = { .type = ACTION_TYPE_NONE };
216 static const union xkb_action *
217 xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
219 xkb_layout_index_t layout;
220 xkb_level_index_t level;
222 layout = xkb_state_key_get_layout(state, key->keycode);
223 if (layout == XKB_LAYOUT_INVALID)
226 level = xkb_state_key_get_level(state, key->keycode, layout);
227 if (level == XKB_LEVEL_INVALID)
230 return &key->groups[layout].levels[level].action;
233 static struct xkb_filter *
234 xkb_filter_new(struct xkb_state *state)
236 struct xkb_filter *filter = NULL, *iter;
238 darray_foreach(iter, state->filters) {
246 darray_resize0(state->filters, darray_size(state->filters) + 1);
247 filter = &darray_item(state->filters, darray_size(state->filters) -1);
254 /***====================================================================***/
257 xkb_filter_group_set_func(struct xkb_state *state,
258 struct xkb_filter *filter,
259 const struct xkb_key *key,
260 enum xkb_key_direction direction)
262 if (key != filter->key) {
263 filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
267 if (direction == XKB_KEY_DOWN) {
271 else if (--filter->refcnt > 0) {
275 state->cur.base_group = filter->priv;
277 if (filter->action.group.flags & ACTION_LOCK_CLEAR)
278 state->cur.locked_group = 0;
285 xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
287 filter->priv = state->cur.base_group;
288 if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
289 state->cur.base_group = filter->action.group.group;
291 state->cur.base_group += filter->action.group.group;
295 xkb_filter_group_lock_func(struct xkb_state *state,
296 struct xkb_filter *filter,
297 const struct xkb_key *key,
298 enum xkb_key_direction direction)
300 if (key != filter->key)
303 if (direction == XKB_KEY_DOWN) {
307 if (--filter->refcnt > 0)
315 xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
317 if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
318 state->cur.locked_group = filter->action.group.group;
320 state->cur.locked_group += filter->action.group.group;
324 xkb_filter_mod_set_func(struct xkb_state *state,
325 struct xkb_filter *filter,
326 const struct xkb_key *key,
327 enum xkb_key_direction direction)
329 if (key != filter->key) {
330 filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
334 if (direction == XKB_KEY_DOWN) {
338 else if (--filter->refcnt > 0) {
342 state->clear_mods = filter->action.mods.mods.mask;
343 if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
344 state->cur.locked_mods &= ~filter->action.mods.mods.mask;
351 xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
353 state->set_mods = filter->action.mods.mods.mask;
357 xkb_filter_mod_lock_func(struct xkb_state *state,
358 struct xkb_filter *filter,
359 const struct xkb_key *key,
360 enum xkb_key_direction direction)
362 if (key != filter->key)
365 if (direction == XKB_KEY_DOWN) {
369 if (--filter->refcnt > 0)
372 state->clear_mods |= filter->action.mods.mods.mask;
373 if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
374 state->cur.locked_mods &= ~filter->priv;
381 xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
383 filter->priv = state->cur.locked_mods & filter->action.mods.mods.mask;
384 state->set_mods |= filter->action.mods.mods.mask;
385 if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
386 state->cur.locked_mods |= filter->action.mods.mods.mask;
389 enum xkb_key_latch_state {
396 xkb_action_breaks_latch(const union xkb_action *action)
398 switch (action->type) {
399 case ACTION_TYPE_NONE:
400 case ACTION_TYPE_PTR_BUTTON:
401 case ACTION_TYPE_PTR_LOCK:
402 case ACTION_TYPE_CTRL_SET:
403 case ACTION_TYPE_CTRL_LOCK:
404 case ACTION_TYPE_KEY_REDIRECT:
405 case ACTION_TYPE_SWITCH_VT:
406 case ACTION_TYPE_TERMINATE:
414 xkb_filter_mod_latch_func(struct xkb_state *state,
415 struct xkb_filter *filter,
416 const struct xkb_key *key,
417 enum xkb_key_direction direction)
419 enum xkb_key_latch_state latch = filter->priv;
421 if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
422 /* If this is a new keypress and we're awaiting our single latched
423 * keypress, then either break the latch if any random key is pressed,
424 * or promote it to a lock or plain base set if it's the same
426 const union xkb_action *action = xkb_key_get_action(state, key);
427 if (action->type == ACTION_TYPE_MOD_LATCH &&
428 action->mods.flags == filter->action.mods.flags &&
429 action->mods.mods.mask == filter->action.mods.mods.mask) {
430 filter->action = *action;
431 if (filter->action.mods.flags & ACTION_LATCH_TO_LOCK) {
432 filter->action.type = ACTION_TYPE_MOD_LOCK;
433 filter->func = xkb_filter_mod_lock_func;
434 state->cur.locked_mods |= filter->action.mods.mods.mask;
437 filter->action.type = ACTION_TYPE_MOD_SET;
438 filter->func = xkb_filter_mod_set_func;
439 state->set_mods = filter->action.mods.mods.mask;
442 state->cur.latched_mods &= ~filter->action.mods.mods.mask;
446 else if (xkb_action_breaks_latch(action)) {
447 /* XXX: This may be totally broken, we might need to break the
448 * latch in the next run after this press? */
449 state->cur.latched_mods &= ~filter->action.mods.mods.mask;
454 else if (direction == XKB_KEY_UP && key == filter->key) {
455 /* Our key got released. If we've set it to clear locks, and we
456 * currently have the same modifiers locked, then release them and
457 * don't actually latch. Else we've actually hit the latching
458 * stage, so set PENDING and move our modifier from base to
460 if (latch == NO_LATCH ||
461 ((filter->action.mods.flags & ACTION_LOCK_CLEAR) &&
462 (state->cur.locked_mods & filter->action.mods.mods.mask) ==
463 filter->action.mods.mods.mask)) {
464 /* XXX: We might be a bit overenthusiastic about clearing
465 * mods other filters have set here? */
466 if (latch == LATCH_PENDING)
467 state->cur.latched_mods &= ~filter->action.mods.mods.mask;
469 state->clear_mods = filter->action.mods.mods.mask;
470 state->cur.locked_mods &= ~filter->action.mods.mods.mask;
474 latch = LATCH_PENDING;
475 state->clear_mods = filter->action.mods.mods.mask;
476 state->cur.latched_mods |= filter->action.mods.mods.mask;
480 else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
481 /* Someone's pressed another key while we've still got the latching
482 * key held down, so keep the base modifier state active (from
483 * xkb_filter_mod_latch_new), but don't trip the latch, just clear
484 * it as soon as the modifier gets released. */
488 filter->priv = latch;
494 xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
496 filter->priv = LATCH_KEY_DOWN;
497 state->set_mods = filter->action.mods.mods.mask;
500 static const struct {
501 void (*new)(struct xkb_state *state, struct xkb_filter *filter);
502 int (*func)(struct xkb_state *state, struct xkb_filter *filter,
503 const struct xkb_key *key, enum xkb_key_direction direction);
504 } filter_action_funcs[_ACTION_TYPE_NUM_ENTRIES] = {
505 [ACTION_TYPE_MOD_SET] = { xkb_filter_mod_set_new,
506 xkb_filter_mod_set_func },
507 [ACTION_TYPE_MOD_LATCH] = { xkb_filter_mod_latch_new,
508 xkb_filter_mod_latch_func },
509 [ACTION_TYPE_MOD_LOCK] = { xkb_filter_mod_lock_new,
510 xkb_filter_mod_lock_func },
511 [ACTION_TYPE_GROUP_SET] = { xkb_filter_group_set_new,
512 xkb_filter_group_set_func },
513 [ACTION_TYPE_GROUP_LOCK] = { xkb_filter_group_lock_new,
514 xkb_filter_group_lock_func },
518 * Applies any relevant filters to the key, first from the list of filters
519 * that are currently active, then if no filter has claimed the key, possibly
520 * apply a new filter from the key action.
523 xkb_filter_apply_all(struct xkb_state *state,
524 const struct xkb_key *key,
525 enum xkb_key_direction direction)
527 struct xkb_filter *filter;
528 const union xkb_action *action;
531 /* First run through all the currently active filters and see if any of
532 * them have claimed this event. */
533 darray_foreach(filter, state->filters) {
536 send &= filter->func(state, filter, key, direction);
539 if (!send || direction == XKB_KEY_UP)
542 action = xkb_key_get_action(state, key);
543 if (!filter_action_funcs[action->type].new)
546 filter = xkb_filter_new(state);
551 filter->func = filter_action_funcs[action->type].func;
552 filter->action = *action;
553 filter_action_funcs[action->type].new(state, filter);
556 XKB_EXPORT struct xkb_state *
557 xkb_state_new(struct xkb_keymap *keymap)
559 struct xkb_state *ret;
561 ret = calloc(sizeof(*ret), 1);
566 ret->keymap = xkb_keymap_ref(keymap);
571 XKB_EXPORT struct xkb_state *
572 xkb_state_ref(struct xkb_state *state)
579 xkb_state_unref(struct xkb_state *state)
581 if (--state->refcnt > 0)
584 xkb_keymap_unref(state->keymap);
585 darray_free(state->filters);
589 XKB_EXPORT struct xkb_keymap *
590 xkb_state_get_keymap(struct xkb_state *state)
592 return state->keymap;
596 * Update the LED state to match the rest of the xkb_state.
599 xkb_state_led_update_all(struct xkb_state *state)
602 const struct xkb_indicator_map *map;
606 darray_enumerate(led, map, state->keymap->indicators) {
607 xkb_mod_mask_t mod_mask = 0;
608 xkb_layout_mask_t group_mask = 0;
610 if (map->which_mods & XKB_STATE_MODS_EFFECTIVE)
611 mod_mask |= state->cur.mods;
612 if (map->which_mods & XKB_STATE_MODS_DEPRESSED)
613 mod_mask |= state->cur.base_mods;
614 if (map->which_mods & XKB_STATE_MODS_LATCHED)
615 mod_mask |= state->cur.latched_mods;
616 if (map->which_mods & XKB_STATE_MODS_LOCKED)
617 mod_mask |= state->cur.locked_mods;
618 if (map->mods.mask & mod_mask)
619 state->cur.leds |= (1 << led);
621 if (map->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
622 group_mask |= (1 << state->cur.group);
623 if (map->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
624 group_mask |= (1 << state->cur.base_group);
625 if (map->which_groups & XKB_STATE_LAYOUT_LATCHED)
626 group_mask |= (1 << state->cur.latched_group);
627 if (map->which_groups & XKB_STATE_LAYOUT_LOCKED)
628 group_mask |= (1 << state->cur.locked_group);
629 if (map->groups & group_mask)
630 state->cur.leds |= (1 << led);
632 if (map->ctrls & state->keymap->enabled_ctrls)
633 state->cur.leds |= (1 << led);
638 * Calculates the derived state (effective mods/group and LEDs) from an
639 * up-to-date xkb_state.
642 xkb_state_update_derived(struct xkb_state *state)
644 xkb_layout_index_t num_groups = xkb_keymap_num_layouts(state->keymap);
646 state->cur.mods = (state->cur.base_mods |
647 state->cur.latched_mods |
648 state->cur.locked_mods);
650 /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
652 state->cur.locked_group = wrap_group_into_range(state->cur.locked_group,
656 state->cur.group = wrap_group_into_range(state->cur.base_group +
657 state->cur.latched_group +
658 state->cur.locked_group,
662 xkb_state_led_update_all(state);
665 static enum xkb_state_component
666 get_state_component_changes(const struct state_components *a,
667 const struct state_components *b)
669 xkb_mod_mask_t mask = 0;
671 if (a->group != b->group)
672 mask |= XKB_STATE_LAYOUT_EFFECTIVE;
673 if (a->base_group != b->base_group)
674 mask |= XKB_STATE_LAYOUT_DEPRESSED;
675 if (a->latched_group != b->latched_group)
676 mask |= XKB_STATE_LAYOUT_LATCHED;
677 if (a->locked_group != b->locked_group)
678 mask |= XKB_STATE_LAYOUT_LOCKED;
679 if (a->mods != b->mods)
680 mask |= XKB_STATE_MODS_EFFECTIVE;
681 if (a->base_mods != b->base_mods)
682 mask |= XKB_STATE_MODS_DEPRESSED;
683 if (a->latched_mods != b->latched_mods)
684 mask |= XKB_STATE_MODS_LATCHED;
685 if (a->locked_mods != b->locked_mods)
686 mask |= XKB_STATE_MODS_LOCKED;
687 if (a->leds != b->leds)
688 mask |= XKB_STATE_LEDS;
694 * Given a particular key event, updates the state structure to reflect the
697 XKB_EXPORT enum xkb_state_component
698 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
699 enum xkb_key_direction direction)
703 const struct xkb_key *key = XkbKey(state->keymap, kc);
708 state->prev = state->cur;
711 state->clear_mods = 0;
713 xkb_filter_apply_all(state, key, direction);
715 for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
716 if (state->set_mods & bit) {
717 state->mod_key_count[i]++;
718 state->cur.base_mods |= bit;
719 state->set_mods &= ~bit;
723 for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
724 if (state->clear_mods & bit) {
725 state->mod_key_count[i]--;
726 if (state->mod_key_count[i] <= 0) {
727 state->cur.base_mods &= ~bit;
728 state->mod_key_count[i] = 0;
730 state->clear_mods &= ~bit;
734 xkb_state_update_derived(state);
736 return get_state_component_changes(&state->prev, &state->cur);
740 * Updates the state from a set of explicit masks as gained from
741 * xkb_state_serialize_mods and xkb_state_serialize_groups. As noted in the
742 * documentation for these functions in xkbcommon.h, this round-trip is
743 * lossy, and should only be used to update a slave state mirroring the
744 * master, e.g. in a client/server window system.
746 XKB_EXPORT enum xkb_state_component
747 xkb_state_update_mask(struct xkb_state *state,
748 xkb_mod_mask_t base_mods,
749 xkb_mod_mask_t latched_mods,
750 xkb_mod_mask_t locked_mods,
751 xkb_layout_index_t base_group,
752 xkb_layout_index_t latched_group,
753 xkb_layout_index_t locked_group)
755 xkb_mod_index_t num_mods;
758 state->cur = state->prev;
760 state->cur.base_mods = 0;
761 state->cur.latched_mods = 0;
762 state->cur.locked_mods = 0;
763 num_mods = xkb_keymap_num_mods(state->keymap);
765 for (idx = 0; idx < num_mods; idx++) {
766 xkb_mod_mask_t mod = (1 << idx);
768 state->cur.base_mods |= mod;
769 if (latched_mods & mod)
770 state->cur.latched_mods |= mod;
771 if (locked_mods & mod)
772 state->cur.locked_mods |= mod;
775 state->cur.base_group = base_group;
776 state->cur.latched_group = latched_group;
777 state->cur.locked_group = locked_group;
779 xkb_state_update_derived(state);
781 return get_state_component_changes(&state->prev, &state->cur);
785 * Provides the symbols to use for the given key and state. Returns the
786 * number of symbols pointed to in syms_out.
789 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
790 const xkb_keysym_t **syms_out)
792 xkb_layout_index_t layout;
793 xkb_level_index_t level;
795 layout = xkb_state_key_get_layout(state, kc);
796 if (layout == XKB_LAYOUT_INVALID)
799 level = xkb_state_key_get_level(state, kc, layout);
800 if (level == XKB_LEVEL_INVALID)
803 return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
812 * Provides either exactly one symbol, or XKB_KEY_NoSymbol.
814 XKB_EXPORT xkb_keysym_t
815 xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
817 const xkb_keysym_t *syms;
820 num_syms = xkb_state_key_get_syms(state, kc, &syms);
822 return XKB_KEY_NoSymbol;
828 * Serialises the requested modifier state into an xkb_mod_mask_t, with all
829 * the same disclaimers as in xkb_state_update_mask.
831 XKB_EXPORT xkb_mod_mask_t
832 xkb_state_serialize_mods(struct xkb_state *state,
833 enum xkb_state_component type)
835 xkb_mod_mask_t ret = 0;
837 if (type & XKB_STATE_MODS_EFFECTIVE)
838 return state->cur.mods;
840 if (type & XKB_STATE_MODS_DEPRESSED)
841 ret |= state->cur.base_mods;
842 if (type & XKB_STATE_MODS_LATCHED)
843 ret |= state->cur.latched_mods;
844 if (type & XKB_STATE_MODS_LOCKED)
845 ret |= state->cur.locked_mods;
851 * Serialises the requested group state, with all the same disclaimers as
852 * in xkb_state_update_mask.
854 XKB_EXPORT xkb_layout_index_t
855 xkb_state_serialize_layout(struct xkb_state *state,
856 enum xkb_state_component type)
858 xkb_layout_index_t ret = 0;
860 if (type & XKB_STATE_LAYOUT_EFFECTIVE)
861 return state->cur.group;
863 if (type & XKB_STATE_LAYOUT_DEPRESSED)
864 ret += state->cur.base_group;
865 if (type & XKB_STATE_LAYOUT_LATCHED)
866 ret += state->cur.latched_group;
867 if (type & XKB_STATE_LAYOUT_LOCKED)
868 ret += state->cur.locked_group;
874 * Returns 1 if the given modifier is active with the specified type(s), 0 if
875 * not, or -1 if the modifier is invalid.
878 xkb_state_mod_index_is_active(struct xkb_state *state,
880 enum xkb_state_component type)
882 if (idx >= xkb_keymap_num_mods(state->keymap))
885 return !!(xkb_state_serialize_mods(state, type) & (1 << idx));
889 * Helper function for xkb_state_mod_indices_are_active and
890 * xkb_state_mod_names_are_active.
893 match_mod_masks(struct xkb_state *state,
894 enum xkb_state_component type,
895 enum xkb_state_match match,
896 xkb_mod_mask_t wanted)
898 xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
900 if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
903 if (match & XKB_STATE_MATCH_ANY)
904 return !!(active & wanted);
906 return (active & wanted) == wanted;
912 * Returns 1 if the modifiers are active with the specified type(s), 0 if
913 * not, or -1 if any of the modifiers are invalid.
916 xkb_state_mod_indices_are_active(struct xkb_state *state,
917 enum xkb_state_component type,
918 enum xkb_state_match match,
922 xkb_mod_index_t idx = 0;
923 xkb_mod_mask_t wanted = 0;
925 xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
929 idx = va_arg(ap, xkb_mod_index_t);
930 if (idx == XKB_MOD_INVALID)
932 if (idx >= num_mods) {
936 wanted |= (1 << idx);
943 return match_mod_masks(state, type, match, wanted);
947 * Returns 1 if the given modifier is active with the specified type(s), 0 if
948 * not, or -1 if the modifier is invalid.
951 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
952 enum xkb_state_component type)
954 xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
956 if (idx == XKB_MOD_INVALID)
959 return xkb_state_mod_index_is_active(state, idx, type);
963 * Returns 1 if the modifiers are active with the specified type(s), 0 if
964 * not, or -1 if any of the modifiers are invalid.
966 XKB_EXPORT ATTR_NULL_SENTINEL int
967 xkb_state_mod_names_are_active(struct xkb_state *state,
968 enum xkb_state_component type,
969 enum xkb_state_match match,
973 xkb_mod_index_t idx = 0;
975 xkb_mod_mask_t wanted = 0;
980 str = va_arg(ap, const char *);
983 idx = xkb_keymap_mod_get_index(state->keymap, str);
984 if (idx == XKB_MOD_INVALID) {
988 wanted |= (1 << idx);
995 return match_mod_masks(state, type, match, wanted);
999 * Returns 1 if the given group is active with the specified type(s), 0 if
1000 * not, or -1 if the group is invalid.
1003 xkb_state_layout_index_is_active(struct xkb_state *state,
1004 xkb_layout_index_t idx,
1005 enum xkb_state_component type)
1009 if (idx >= xkb_keymap_num_layouts(state->keymap))
1012 if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1013 ret |= (state->cur.group == idx);
1014 if (type & XKB_STATE_LAYOUT_DEPRESSED)
1015 ret |= (state->cur.base_group == idx);
1016 if (type & XKB_STATE_LAYOUT_LATCHED)
1017 ret |= (state->cur.latched_group == idx);
1018 if (type & XKB_STATE_LAYOUT_LOCKED)
1019 ret |= (state->cur.locked_group == idx);
1025 * Returns 1 if the given modifier is active with the specified type(s), 0 if
1026 * not, or -1 if the modifier is invalid.
1029 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
1030 enum xkb_state_component type)
1032 xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
1034 if (idx == XKB_LAYOUT_INVALID)
1037 return xkb_state_layout_index_is_active(state, idx, type);
1041 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1044 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1046 if (idx >= darray_size(state->keymap->indicators) ||
1047 darray_item(state->keymap->indicators, idx).name == XKB_ATOM_NONE)
1050 return !!(state->cur.leds & (1 << idx));
1054 * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1057 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1059 xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1061 if (idx == XKB_LED_INVALID)
1064 return xkb_state_led_index_is_active(state, idx);
1067 static xkb_mod_mask_t
1068 key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
1070 const struct xkb_kt_map_entry *entry;
1071 xkb_layout_index_t group;
1073 group = xkb_state_key_get_layout(state, key->keycode);
1074 if (group == XKB_LAYOUT_INVALID)
1077 entry = get_entry_for_key_state(state, key, group);
1081 return entry->mods.mask & ~entry->preserve.mask;
1085 * Tests to see if a modifier is used up by our translation of a
1086 * keycode to keysyms, taking note of the current modifier state and
1087 * the appropriate key type's preserve information, if any. This allows
1088 * the user to mask out the modifier in later processing of the
1089 * modifiers, e.g. when implementing hot keys or accelerators.
1091 * See also, for example:
1092 * - XkbTranslateKeyCode(3), mod_rtrn retrun value, from libX11.
1093 * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
1097 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1098 xkb_mod_index_t idx)
1100 const struct xkb_key *key = XkbKey(state->keymap, kc);
1102 if (!key || idx >= xkb_keymap_num_mods(state->keymap))
1105 return !!((1 << idx) & key_get_consumed(state, key));
1109 * Calculates which modifiers should be consumed during key processing,
1110 * and returns the mask with all these modifiers removed. e.g. if
1111 * given a state of Alt and Shift active for a two-level alphabetic
1112 * key containing plus and equal on the first and second level
1113 * respectively, will return a mask of only Alt, as Shift has been
1114 * consumed by the type handling.
1116 XKB_EXPORT xkb_mod_mask_t
1117 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1118 xkb_mod_mask_t mask)
1120 const struct xkb_key *key = XkbKey(state->keymap, kc);
1125 return mask & ~key_get_consumed(state, key);