Merge pull request #31 from bluetech/consumed-modes
[platform/upstream/libxkbcommon.git] / src / state.c
1 /************************************************************
2  * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3  *
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.
15  *
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.
24  *
25  ********************************************************/
26
27 /*
28  * Copyright © 2012 Intel Corporation
29  * Copyright © 2012 Ran Benita <ran234@gmail.com>
30  *
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:
37  *
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
40  * Software.
41  *
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.
49  *
50  * Author: Daniel Stone <daniel@fooishbar.org>
51  */
52
53 /*
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)
60  */
61
62 #include "keymap.h"
63 #include "keysym.h"
64 #include "utf8.h"
65
66 struct xkb_filter {
67     union xkb_action action;
68     const struct xkb_key *key;
69     uint32_t priv;
70     bool (*func)(struct xkb_state *state,
71                  struct xkb_filter *filter,
72                  const struct xkb_key *key,
73                  enum xkb_key_direction direction);
74     int refcnt;
75 };
76
77 struct state_components {
78     /* These may be negative, because of -1 group actions. */
79     int32_t base_group; /**< depressed */
80     int32_t latched_group;
81     int32_t locked_group;
82     xkb_layout_index_t group; /**< effective */
83
84     xkb_mod_mask_t base_mods; /**< depressed */
85     xkb_mod_mask_t latched_mods;
86     xkb_mod_mask_t locked_mods;
87     xkb_mod_mask_t mods; /**< effective */
88
89     xkb_led_mask_t leds;
90 };
91
92 struct xkb_state {
93     /*
94      * Before updating the state, we keep a copy of just this struct. This
95      * allows us to report which components of the state have changed.
96      */
97     struct state_components components;
98
99     /*
100      * At each event, we accumulate all the needed modifications to the base
101      * modifiers, and apply them at the end. These keep track of this state.
102      */
103     xkb_mod_mask_t set_mods;
104     xkb_mod_mask_t clear_mods;
105
106     /*
107      * We mustn't clear a base modifier if there's another depressed key
108      * which affects it, e.g. given this sequence
109      * < Left Shift down, Right Shift down, Left Shift Up >
110      * the modifier should still be set. This keeps the count.
111      */
112     int16_t mod_key_count[XKB_MAX_MODS];
113
114     int refcnt;
115     darray(struct xkb_filter) filters;
116     struct xkb_keymap *keymap;
117 };
118
119 /*
120  * If the virtual modifiers are not bound to anything, the entry
121  * is not active and should be skipped. xserver does this with
122  * cached entry->active field.
123  */
124 static bool
125 entry_is_active(const struct xkb_key_type_entry *entry)
126 {
127     return entry->mods.mods == 0 || entry->mods.mask != 0;
128 }
129
130 static const struct xkb_key_type_entry *
131 get_entry_for_mods(const struct xkb_key_type *type, xkb_mod_mask_t mods)
132 {
133     for (unsigned i = 0; i < type->num_entries; i++)
134         if (entry_is_active(&type->entries[i]) &&
135             type->entries[i].mods.mask == mods)
136             return &type->entries[i];
137     return NULL;
138 }
139
140 static const struct xkb_key_type_entry *
141 get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
142                         xkb_layout_index_t group)
143 {
144     const struct xkb_key_type *type = key->groups[group].type;
145     xkb_mod_mask_t active_mods = state->components.mods & type->mods.mask;
146     return get_entry_for_mods(type, active_mods);
147 }
148
149 /**
150  * Returns the level to use for the given key and state, or
151  * XKB_LEVEL_INVALID.
152  */
153 XKB_EXPORT xkb_level_index_t
154 xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
155                         xkb_layout_index_t layout)
156 {
157     const struct xkb_key *key = XkbKey(state->keymap, kc);
158     const struct xkb_key_type_entry *entry;
159
160     if (!key || layout >= key->num_groups)
161         return XKB_LEVEL_INVALID;
162
163     /* If we don't find an explicit match the default is 0. */
164     entry = get_entry_for_key_state(state, key, layout);
165     if (!entry)
166         return 0;
167
168     return entry->level;
169 }
170
171 xkb_layout_index_t
172 XkbWrapGroupIntoRange(int32_t group,
173                       xkb_layout_index_t num_groups,
174                       enum xkb_range_exceed_type out_of_range_group_action,
175                       xkb_layout_index_t out_of_range_group_number)
176 {
177     if (num_groups == 0)
178         return XKB_LAYOUT_INVALID;
179
180     if (group >= 0 && (xkb_layout_index_t) group < num_groups)
181         return group;
182
183     switch (out_of_range_group_action) {
184     case RANGE_REDIRECT:
185         if (out_of_range_group_number >= num_groups)
186             return 0;
187         return out_of_range_group_number;
188
189     case RANGE_SATURATE:
190         if (group < 0)
191             return 0;
192         else
193             return num_groups - 1;
194
195     case RANGE_WRAP:
196     default:
197         /*
198          * C99 says a negative dividend in a modulo operation always
199          * gives a negative result.
200          */
201         if (group < 0)
202             return ((int) num_groups + (group % (int) num_groups));
203         else
204             return group % num_groups;
205     }
206 }
207
208 /**
209  * Returns the layout to use for the given key and state, taking
210  * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
211  */
212 XKB_EXPORT xkb_layout_index_t
213 xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
214 {
215     const struct xkb_key *key = XkbKey(state->keymap, kc);
216
217     if (!key)
218         return XKB_LAYOUT_INVALID;
219
220     return XkbWrapGroupIntoRange(state->components.group, key->num_groups,
221                                  key->out_of_range_group_action,
222                                  key->out_of_range_group_number);
223 }
224
225 static const union xkb_action *
226 xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
227 {
228     static const union xkb_action dummy = { .type = ACTION_TYPE_NONE };
229
230     xkb_layout_index_t layout;
231     xkb_level_index_t level;
232
233     layout = xkb_state_key_get_layout(state, key->keycode);
234     if (layout == XKB_LAYOUT_INVALID)
235         return &dummy;
236
237     level = xkb_state_key_get_level(state, key->keycode, layout);
238     if (level == XKB_LEVEL_INVALID)
239         return &dummy;
240
241     return &key->groups[layout].levels[level].action;
242 }
243
244 static struct xkb_filter *
245 xkb_filter_new(struct xkb_state *state)
246 {
247     struct xkb_filter *filter = NULL, *iter;
248
249     darray_foreach(iter, state->filters) {
250         if (iter->func)
251             continue;
252         filter = iter;
253         break;
254     }
255
256     if (!filter) {
257         darray_resize0(state->filters, darray_size(state->filters) + 1);
258         filter = &darray_item(state->filters, darray_size(state->filters) -1);
259     }
260
261     filter->refcnt = 1;
262     return filter;
263 }
264
265 /***====================================================================***/
266
267 static bool
268 xkb_filter_group_set_func(struct xkb_state *state,
269                           struct xkb_filter *filter,
270                           const struct xkb_key *key,
271                           enum xkb_key_direction direction)
272 {
273     if (key != filter->key) {
274         filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
275         return true;
276     }
277
278     if (direction == XKB_KEY_DOWN) {
279         filter->refcnt++;
280         return false;
281     }
282     else if (--filter->refcnt > 0) {
283         return false;
284     }
285
286     state->components.base_group = filter->priv;
287
288     if (filter->action.group.flags & ACTION_LOCK_CLEAR)
289         state->components.locked_group = 0;
290
291     filter->func = NULL;
292     return true;
293 }
294
295 static void
296 xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
297 {
298     filter->priv = state->components.base_group;
299     if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
300         state->components.base_group = filter->action.group.group;
301     else
302         state->components.base_group += filter->action.group.group;
303 }
304
305 static bool
306 xkb_filter_group_lock_func(struct xkb_state *state,
307                            struct xkb_filter *filter,
308                            const struct xkb_key *key,
309                            enum xkb_key_direction direction)
310 {
311     if (key != filter->key)
312         return true;
313
314     if (direction == XKB_KEY_DOWN) {
315         filter->refcnt++;
316         return false;
317     }
318     if (--filter->refcnt > 0)
319         return false;
320
321     filter->func = NULL;
322     return true;
323 }
324
325 static void
326 xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
327 {
328     if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
329         state->components.locked_group = filter->action.group.group;
330     else
331         state->components.locked_group += filter->action.group.group;
332 }
333
334 static bool
335 xkb_filter_mod_set_func(struct xkb_state *state,
336                         struct xkb_filter *filter,
337                         const struct xkb_key *key,
338                         enum xkb_key_direction direction)
339 {
340     if (key != filter->key) {
341         filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
342         return true;
343     }
344
345     if (direction == XKB_KEY_DOWN) {
346         filter->refcnt++;
347         return false;
348     }
349     else if (--filter->refcnt > 0) {
350         return false;
351     }
352
353     state->clear_mods = filter->action.mods.mods.mask;
354     if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
355         state->components.locked_mods &= ~filter->action.mods.mods.mask;
356
357     filter->func = NULL;
358     return true;
359 }
360
361 static void
362 xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
363 {
364     state->set_mods = filter->action.mods.mods.mask;
365 }
366
367 static bool
368 xkb_filter_mod_lock_func(struct xkb_state *state,
369                          struct xkb_filter *filter,
370                          const struct xkb_key *key,
371                          enum xkb_key_direction direction)
372 {
373     if (key != filter->key)
374         return true;
375
376     if (direction == XKB_KEY_DOWN) {
377         filter->refcnt++;
378         return false;
379     }
380     if (--filter->refcnt > 0)
381         return false;
382
383     state->clear_mods |= filter->action.mods.mods.mask;
384     if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
385         state->components.locked_mods &= ~filter->priv;
386
387     filter->func = NULL;
388     return true;
389 }
390
391 static void
392 xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
393 {
394     filter->priv = (state->components.locked_mods &
395                     filter->action.mods.mods.mask);
396     state->set_mods |= filter->action.mods.mods.mask;
397     if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
398         state->components.locked_mods |= filter->action.mods.mods.mask;
399 }
400
401 enum xkb_key_latch_state {
402     NO_LATCH,
403     LATCH_KEY_DOWN,
404     LATCH_PENDING,
405 };
406
407 static bool
408 xkb_action_breaks_latch(const union xkb_action *action)
409 {
410     switch (action->type) {
411     case ACTION_TYPE_NONE:
412     case ACTION_TYPE_PTR_BUTTON:
413     case ACTION_TYPE_PTR_LOCK:
414     case ACTION_TYPE_CTRL_SET:
415     case ACTION_TYPE_CTRL_LOCK:
416     case ACTION_TYPE_SWITCH_VT:
417     case ACTION_TYPE_TERMINATE:
418         return true;
419     default:
420         return false;
421     }
422 }
423
424 static bool
425 xkb_filter_mod_latch_func(struct xkb_state *state,
426                           struct xkb_filter *filter,
427                           const struct xkb_key *key,
428                           enum xkb_key_direction direction)
429 {
430     enum xkb_key_latch_state latch = filter->priv;
431
432     if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
433         /* If this is a new keypress and we're awaiting our single latched
434          * keypress, then either break the latch if any random key is pressed,
435          * or promote it to a lock or plain base set if it's the same
436          * modifier. */
437         const union xkb_action *action = xkb_key_get_action(state, key);
438         if (action->type == ACTION_TYPE_MOD_LATCH &&
439             action->mods.flags == filter->action.mods.flags &&
440             action->mods.mods.mask == filter->action.mods.mods.mask) {
441             filter->action = *action;
442             if (filter->action.mods.flags & ACTION_LATCH_TO_LOCK) {
443                 filter->action.type = ACTION_TYPE_MOD_LOCK;
444                 filter->func = xkb_filter_mod_lock_func;
445                 state->components.locked_mods |= filter->action.mods.mods.mask;
446             }
447             else {
448                 filter->action.type = ACTION_TYPE_MOD_SET;
449                 filter->func = xkb_filter_mod_set_func;
450                 state->set_mods = filter->action.mods.mods.mask;
451             }
452             filter->key = key;
453             state->components.latched_mods &= ~filter->action.mods.mods.mask;
454             /* XXX beep beep! */
455             return false;
456         }
457         else if (xkb_action_breaks_latch(action)) {
458             /* XXX: This may be totally broken, we might need to break the
459              *      latch in the next run after this press? */
460             state->components.latched_mods &= ~filter->action.mods.mods.mask;
461             filter->func = NULL;
462             return true;
463         }
464     }
465     else if (direction == XKB_KEY_UP && key == filter->key) {
466         /* Our key got released.  If we've set it to clear locks, and we
467          * currently have the same modifiers locked, then release them and
468          * don't actually latch.  Else we've actually hit the latching
469          * stage, so set PENDING and move our modifier from base to
470          * latched. */
471         if (latch == NO_LATCH ||
472             ((filter->action.mods.flags & ACTION_LOCK_CLEAR) &&
473              (state->components.locked_mods & filter->action.mods.mods.mask) ==
474              filter->action.mods.mods.mask)) {
475             /* XXX: We might be a bit overenthusiastic about clearing
476              *      mods other filters have set here? */
477             if (latch == LATCH_PENDING)
478                 state->components.latched_mods &=
479                     ~filter->action.mods.mods.mask;
480             else
481                 state->clear_mods = filter->action.mods.mods.mask;
482             state->components.locked_mods &= ~filter->action.mods.mods.mask;
483             filter->func = NULL;
484         }
485         else {
486             latch = LATCH_PENDING;
487             state->clear_mods = filter->action.mods.mods.mask;
488             state->components.latched_mods |= filter->action.mods.mods.mask;
489             /* XXX beep beep! */
490         }
491     }
492     else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
493         /* Someone's pressed another key while we've still got the latching
494          * key held down, so keep the base modifier state active (from
495          * xkb_filter_mod_latch_new), but don't trip the latch, just clear
496          * it as soon as the modifier gets released. */
497         latch = NO_LATCH;
498     }
499
500     filter->priv = latch;
501
502     return true;
503 }
504
505 static void
506 xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
507 {
508     filter->priv = LATCH_KEY_DOWN;
509     state->set_mods = filter->action.mods.mods.mask;
510 }
511
512 static const struct {
513     void (*new)(struct xkb_state *state, struct xkb_filter *filter);
514     bool (*func)(struct xkb_state *state, struct xkb_filter *filter,
515                  const struct xkb_key *key, enum xkb_key_direction direction);
516 } filter_action_funcs[_ACTION_TYPE_NUM_ENTRIES] = {
517     [ACTION_TYPE_MOD_SET]    = { xkb_filter_mod_set_new,
518                                  xkb_filter_mod_set_func },
519     [ACTION_TYPE_MOD_LATCH]  = { xkb_filter_mod_latch_new,
520                                  xkb_filter_mod_latch_func },
521     [ACTION_TYPE_MOD_LOCK]   = { xkb_filter_mod_lock_new,
522                                  xkb_filter_mod_lock_func },
523     [ACTION_TYPE_GROUP_SET]  = { xkb_filter_group_set_new,
524                                  xkb_filter_group_set_func },
525     [ACTION_TYPE_GROUP_LOCK] = { xkb_filter_group_lock_new,
526                                  xkb_filter_group_lock_func },
527 };
528
529 /**
530  * Applies any relevant filters to the key, first from the list of filters
531  * that are currently active, then if no filter has claimed the key, possibly
532  * apply a new filter from the key action.
533  */
534 static void
535 xkb_filter_apply_all(struct xkb_state *state,
536                      const struct xkb_key *key,
537                      enum xkb_key_direction direction)
538 {
539     struct xkb_filter *filter;
540     const union xkb_action *action;
541     bool send = true;
542
543     /* First run through all the currently active filters and see if any of
544      * them have claimed this event. */
545     darray_foreach(filter, state->filters) {
546         if (!filter->func)
547             continue;
548         send = filter->func(state, filter, key, direction) && send;
549     }
550
551     if (!send || direction == XKB_KEY_UP)
552         return;
553
554     action = xkb_key_get_action(state, key);
555
556     /*
557      * It's possible for the keymap to set action->type explicitly, like so:
558      *     interpret XF86_Next_VMode {
559      *         action = Private(type=0x86, data="+VMode");
560      *     };
561      * We don't handle those.
562      */
563     if (action->type >= _ACTION_TYPE_NUM_ENTRIES)
564         return;
565
566     if (!filter_action_funcs[action->type].new)
567         return;
568
569     filter = xkb_filter_new(state);
570     if (!filter)
571         return; /* WSGO */
572
573     filter->key = key;
574     filter->func = filter_action_funcs[action->type].func;
575     filter->action = *action;
576     filter_action_funcs[action->type].new(state, filter);
577 }
578
579 XKB_EXPORT struct xkb_state *
580 xkb_state_new(struct xkb_keymap *keymap)
581 {
582     struct xkb_state *ret;
583
584     ret = calloc(sizeof(*ret), 1);
585     if (!ret)
586         return NULL;
587
588     ret->refcnt = 1;
589     ret->keymap = xkb_keymap_ref(keymap);
590
591     return ret;
592 }
593
594 XKB_EXPORT struct xkb_state *
595 xkb_state_ref(struct xkb_state *state)
596 {
597     state->refcnt++;
598     return state;
599 }
600
601 XKB_EXPORT void
602 xkb_state_unref(struct xkb_state *state)
603 {
604     if (!state || --state->refcnt > 0)
605         return;
606
607     xkb_keymap_unref(state->keymap);
608     darray_free(state->filters);
609     free(state);
610 }
611
612 XKB_EXPORT struct xkb_keymap *
613 xkb_state_get_keymap(struct xkb_state *state)
614 {
615     return state->keymap;
616 }
617
618 /**
619  * Update the LED state to match the rest of the xkb_state.
620  */
621 static void
622 xkb_state_led_update_all(struct xkb_state *state)
623 {
624     xkb_led_index_t idx;
625     const struct xkb_led *led;
626
627     state->components.leds = 0;
628
629     xkb_leds_enumerate(idx, led, state->keymap) {
630         xkb_mod_mask_t mod_mask = 0;
631         xkb_layout_mask_t group_mask = 0;
632
633         if (led->which_mods != 0 && led->mods.mask != 0) {
634             if (led->which_mods & XKB_STATE_MODS_EFFECTIVE)
635                 mod_mask |= state->components.mods;
636             if (led->which_mods & XKB_STATE_MODS_DEPRESSED)
637                 mod_mask |= state->components.base_mods;
638             if (led->which_mods & XKB_STATE_MODS_LATCHED)
639                 mod_mask |= state->components.latched_mods;
640             if (led->which_mods & XKB_STATE_MODS_LOCKED)
641                 mod_mask |= state->components.locked_mods;
642
643             if (led->mods.mask & mod_mask) {
644                 state->components.leds |= (1u << idx);
645                 continue;
646             }
647         }
648
649         if (led->which_groups != 0 && led->groups != 0) {
650             if (led->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
651                 group_mask |= (1u << state->components.group);
652             if (led->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
653                 group_mask |= (1u << state->components.base_group);
654             if (led->which_groups & XKB_STATE_LAYOUT_LATCHED)
655                 group_mask |= (1u << state->components.latched_group);
656             if (led->which_groups & XKB_STATE_LAYOUT_LOCKED)
657                 group_mask |= (1u << state->components.locked_group);
658
659             if (led->groups & group_mask) {
660                 state->components.leds |= (1u << idx);
661                 continue;
662             }
663         }
664
665         if (led->ctrls & state->keymap->enabled_ctrls) {
666             state->components.leds |= (1u << idx);
667             continue;
668         }
669     }
670 }
671
672 /**
673  * Calculates the derived state (effective mods/group and LEDs) from an
674  * up-to-date xkb_state.
675  */
676 static void
677 xkb_state_update_derived(struct xkb_state *state)
678 {
679     xkb_layout_index_t wrapped;
680
681     state->components.mods = (state->components.base_mods |
682                               state->components.latched_mods |
683                               state->components.locked_mods);
684
685     /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
686
687     wrapped = XkbWrapGroupIntoRange(state->components.locked_group,
688                                     state->keymap->num_groups,
689                                     RANGE_WRAP, 0);
690     state->components.locked_group =
691         (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
692
693     wrapped = XkbWrapGroupIntoRange(state->components.base_group +
694                                     state->components.latched_group +
695                                     state->components.locked_group,
696                                     state->keymap->num_groups,
697                                     RANGE_WRAP, 0);
698     state->components.group =
699         (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
700
701     xkb_state_led_update_all(state);
702 }
703
704 static enum xkb_state_component
705 get_state_component_changes(const struct state_components *a,
706                             const struct state_components *b)
707 {
708     xkb_mod_mask_t mask = 0;
709
710     if (a->group != b->group)
711         mask |= XKB_STATE_LAYOUT_EFFECTIVE;
712     if (a->base_group != b->base_group)
713         mask |= XKB_STATE_LAYOUT_DEPRESSED;
714     if (a->latched_group != b->latched_group)
715         mask |= XKB_STATE_LAYOUT_LATCHED;
716     if (a->locked_group != b->locked_group)
717         mask |= XKB_STATE_LAYOUT_LOCKED;
718     if (a->mods != b->mods)
719         mask |= XKB_STATE_MODS_EFFECTIVE;
720     if (a->base_mods != b->base_mods)
721         mask |= XKB_STATE_MODS_DEPRESSED;
722     if (a->latched_mods != b->latched_mods)
723         mask |= XKB_STATE_MODS_LATCHED;
724     if (a->locked_mods != b->locked_mods)
725         mask |= XKB_STATE_MODS_LOCKED;
726     if (a->leds != b->leds)
727         mask |= XKB_STATE_LEDS;
728
729     return mask;
730 }
731
732 /**
733  * Given a particular key event, updates the state structure to reflect the
734  * new modifiers.
735  */
736 XKB_EXPORT enum xkb_state_component
737 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
738                      enum xkb_key_direction direction)
739 {
740     xkb_mod_index_t i;
741     xkb_mod_mask_t bit;
742     struct state_components prev_components;
743     const struct xkb_key *key = XkbKey(state->keymap, kc);
744
745     if (!key)
746         return 0;
747
748     prev_components = state->components;
749
750     state->set_mods = 0;
751     state->clear_mods = 0;
752
753     xkb_filter_apply_all(state, key, direction);
754
755     for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
756         if (state->set_mods & bit) {
757             state->mod_key_count[i]++;
758             state->components.base_mods |= bit;
759             state->set_mods &= ~bit;
760         }
761     }
762
763     for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
764         if (state->clear_mods & bit) {
765             state->mod_key_count[i]--;
766             if (state->mod_key_count[i] <= 0) {
767                 state->components.base_mods &= ~bit;
768                 state->mod_key_count[i] = 0;
769             }
770             state->clear_mods &= ~bit;
771         }
772     }
773
774     xkb_state_update_derived(state);
775
776     return get_state_component_changes(&prev_components, &state->components);
777 }
778
779 /**
780  * Updates the state from a set of explicit masks as gained from
781  * xkb_state_serialize_mods and xkb_state_serialize_groups.  As noted in the
782  * documentation for these functions in xkbcommon.h, this round-trip is
783  * lossy, and should only be used to update a slave state mirroring the
784  * master, e.g. in a client/server window system.
785  */
786 XKB_EXPORT enum xkb_state_component
787 xkb_state_update_mask(struct xkb_state *state,
788                       xkb_mod_mask_t base_mods,
789                       xkb_mod_mask_t latched_mods,
790                       xkb_mod_mask_t locked_mods,
791                       xkb_layout_index_t base_group,
792                       xkb_layout_index_t latched_group,
793                       xkb_layout_index_t locked_group)
794 {
795     struct state_components prev_components;
796     xkb_mod_mask_t mask;
797
798     prev_components = state->components;
799
800     /* Only include modifiers which exist in the keymap. */
801     mask = (xkb_mod_mask_t) ((1ull << xkb_keymap_num_mods(state->keymap)) - 1u);
802
803     state->components.base_mods = base_mods & mask;
804     state->components.latched_mods = latched_mods & mask;
805     state->components.locked_mods = locked_mods & mask;
806
807     /* Make sure the mods are fully resolved - since we get arbitrary
808      * input, they might not be.
809      *
810      * It might seem more reasonable to do this only for components.mods
811      * in xkb_state_update_derived(), rather than for each component
812      * seperately.  That would allow to distinguish between "really"
813      * depressed mods (would be in MODS_DEPRESSED) and indirectly
814      * depressed to to a mapping (would only be in MODS_EFFECTIVE).
815      * However, the traditional behavior of xkb_state_update_key() is that
816      * if a vmod is depressed, its mappings are depressed with it; so we're
817      * expected to do the same here.  Also, LEDs (usually) look if a real
818      * mod is locked, not just effective; otherwise it won't be lit.
819      *
820      * We OR here because mod_mask_get_effective() drops vmods. */
821     state->components.base_mods |=
822         mod_mask_get_effective(state->keymap, state->components.base_mods);
823     state->components.latched_mods |=
824         mod_mask_get_effective(state->keymap, state->components.latched_mods);
825     state->components.locked_mods |=
826         mod_mask_get_effective(state->keymap, state->components.locked_mods);
827
828     state->components.base_group = base_group;
829     state->components.latched_group = latched_group;
830     state->components.locked_group = locked_group;
831
832     xkb_state_update_derived(state);
833
834     return get_state_component_changes(&prev_components, &state->components);
835 }
836
837 /**
838  * Provides the symbols to use for the given key and state.  Returns the
839  * number of symbols pointed to in syms_out.
840  */
841 XKB_EXPORT int
842 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
843                        const xkb_keysym_t **syms_out)
844 {
845     xkb_layout_index_t layout;
846     xkb_level_index_t level;
847
848     layout = xkb_state_key_get_layout(state, kc);
849     if (layout == XKB_LAYOUT_INVALID)
850         goto err;
851
852     level = xkb_state_key_get_level(state, kc, layout);
853     if (level == XKB_LEVEL_INVALID)
854         goto err;
855
856     return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
857                                             syms_out);
858
859 err:
860     *syms_out = NULL;
861     return 0;
862 }
863
864 /*
865  * http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
866  */
867 static bool
868 should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
869 {
870     xkb_mod_index_t caps =
871         xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CAPS);
872
873     return
874         xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0 &&
875         xkb_state_mod_index_is_consumed(state, kc, caps) == 0;
876 }
877
878 /*
879  * http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
880  */
881 static bool
882 should_do_ctrl_transformation(struct xkb_state *state, xkb_keycode_t kc)
883 {
884     xkb_mod_index_t ctrl =
885         xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CTRL);
886
887     return
888         xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0 &&
889         xkb_state_mod_index_is_consumed(state, kc, ctrl) == 0;
890 }
891
892 /* Verbatim from libX11:src/xkb/XKBBind.c */
893 static char
894 XkbToControl(char ch)
895 {
896     char c = ch;
897
898     if ((c >= '@' && c < '\177') || c == ' ')
899         c &= 0x1F;
900     else if (c == '2')
901         c = '\000';
902     else if (c >= '3' && c <= '7')
903         c -= ('3' - '\033');
904     else if (c == '8')
905         c = '\177';
906     else if (c == '/')
907         c = '_' & 0x1F;
908     return c;
909 }
910
911 /**
912  * Provides either exactly one symbol, or XKB_KEY_NoSymbol.
913  */
914 XKB_EXPORT xkb_keysym_t
915 xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
916 {
917     const xkb_keysym_t *syms;
918     xkb_keysym_t sym;
919     int num_syms;
920
921     num_syms = xkb_state_key_get_syms(state, kc, &syms);
922     if (num_syms != 1)
923         return XKB_KEY_NoSymbol;
924
925     sym = syms[0];
926
927     if (should_do_caps_transformation(state, kc))
928         sym = xkb_keysym_to_upper(sym);
929
930     return sym;
931 }
932
933 /*
934  * The caps and ctrl transformations require some special handling,
935  * so we cannot simply use xkb_state_get_one_sym() for them.
936  * In particular, if Control is set, we must try very hard to find
937  * some layout in which the keysym is ASCII and thus can be (maybe)
938  * converted to a control character. libX11 allows to disable this
939  * behavior with the XkbLC_ControlFallback (see XkbSetXlibControls(3)),
940  * but it is enabled by default, yippee.
941  */
942 static xkb_keysym_t
943 get_one_sym_for_string(struct xkb_state *state, xkb_keycode_t kc)
944 {
945     xkb_level_index_t level;
946     xkb_layout_index_t layout, num_layouts;
947     const xkb_keysym_t *syms;
948     int nsyms;
949     xkb_keysym_t sym;
950
951     layout = xkb_state_key_get_layout(state, kc);
952     num_layouts = xkb_keymap_num_layouts_for_key(state->keymap, kc);
953     level = xkb_state_key_get_level(state, kc, layout);
954     if (layout == XKB_LAYOUT_INVALID || num_layouts == 0 ||
955         level == XKB_LEVEL_INVALID)
956         return XKB_KEY_NoSymbol;
957
958     nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
959                                              layout, level, &syms);
960     if (nsyms != 1)
961         return XKB_KEY_NoSymbol;
962     sym = syms[0];
963
964     if (should_do_ctrl_transformation(state, kc) && sym > 127u) {
965         for (xkb_layout_index_t i = 0; i < num_layouts; i++) {
966             level = xkb_state_key_get_level(state, kc, i);
967             if (level == XKB_LEVEL_INVALID)
968                 continue;
969
970             nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
971                                                      i, level, &syms);
972             if (nsyms == 1 && syms[0] <= 127u) {
973                 sym = syms[0];
974                 break;
975             }
976         }
977     }
978
979     if (should_do_caps_transformation(state, kc)) {
980         sym = xkb_keysym_to_upper(sym);
981     }
982
983     return sym;
984 }
985
986 XKB_EXPORT int
987 xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t kc,
988                        char *buffer, size_t size)
989 {
990     xkb_keysym_t sym;
991     const xkb_keysym_t *syms;
992     int nsyms;
993     int offset;
994     char tmp[7];
995
996     sym = get_one_sym_for_string(state, kc);
997     if (sym != XKB_KEY_NoSymbol) {
998         nsyms = 1; syms = &sym;
999     }
1000     else {
1001         nsyms = xkb_state_key_get_syms(state, kc, &syms);
1002     }
1003
1004     /* Make sure not to truncate in the middle of a UTF-8 sequence. */
1005     offset = 0;
1006     for (int i = 0; i < nsyms; i++) {
1007         int ret = xkb_keysym_to_utf8(syms[i], tmp, sizeof(tmp));
1008         if (ret <= 0)
1009             goto err_bad;
1010
1011         ret--;
1012         if ((size_t) (offset + ret) <= size)
1013             memcpy(buffer + offset, tmp, ret);
1014         offset += ret;
1015     }
1016
1017     if ((size_t) offset >= size)
1018         goto err_trunc;
1019     buffer[offset] = '\0';
1020
1021     if (!is_valid_utf8(buffer, offset))
1022         goto err_bad;
1023
1024     if (offset == 1 && (unsigned int) buffer[0] <= 127u &&
1025         should_do_ctrl_transformation(state, kc))
1026         buffer[0] = XkbToControl(buffer[0]);
1027
1028     return offset;
1029
1030 err_trunc:
1031     if (size > 0)
1032         buffer[size - 1] = '\0';
1033     return offset;
1034
1035 err_bad:
1036     if (size > 0)
1037         buffer[0] = '\0';
1038     return 0;
1039 }
1040
1041 XKB_EXPORT uint32_t
1042 xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t kc)
1043 {
1044     xkb_keysym_t sym;
1045     uint32_t cp;
1046
1047     sym = get_one_sym_for_string(state, kc);
1048     cp = xkb_keysym_to_utf32(sym);
1049
1050     if (cp <= 127u && should_do_ctrl_transformation(state, kc))
1051         cp = (uint32_t) XkbToControl((char) cp);
1052
1053     return cp;
1054 }
1055
1056 /**
1057  * Serialises the requested modifier state into an xkb_mod_mask_t, with all
1058  * the same disclaimers as in xkb_state_update_mask.
1059  */
1060 XKB_EXPORT xkb_mod_mask_t
1061 xkb_state_serialize_mods(struct xkb_state *state,
1062                          enum xkb_state_component type)
1063 {
1064     xkb_mod_mask_t ret = 0;
1065
1066     if (type & XKB_STATE_MODS_EFFECTIVE)
1067         return state->components.mods;
1068
1069     if (type & XKB_STATE_MODS_DEPRESSED)
1070         ret |= state->components.base_mods;
1071     if (type & XKB_STATE_MODS_LATCHED)
1072         ret |= state->components.latched_mods;
1073     if (type & XKB_STATE_MODS_LOCKED)
1074         ret |= state->components.locked_mods;
1075
1076     return ret;
1077 }
1078
1079 /**
1080  * Serialises the requested group state, with all the same disclaimers as
1081  * in xkb_state_update_mask.
1082  */
1083 XKB_EXPORT xkb_layout_index_t
1084 xkb_state_serialize_layout(struct xkb_state *state,
1085                            enum xkb_state_component type)
1086 {
1087     xkb_layout_index_t ret = 0;
1088
1089     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1090         return state->components.group;
1091
1092     if (type & XKB_STATE_LAYOUT_DEPRESSED)
1093         ret += state->components.base_group;
1094     if (type & XKB_STATE_LAYOUT_LATCHED)
1095         ret += state->components.latched_group;
1096     if (type & XKB_STATE_LAYOUT_LOCKED)
1097         ret += state->components.locked_group;
1098
1099     return ret;
1100 }
1101
1102 /**
1103  * Gets a modifier mask and returns the resolved effective mask; this
1104  * is needed because some modifiers can also map to other modifiers, e.g.
1105  * the "NumLock" modifier usually also sets the "Mod2" modifier.
1106  */
1107 xkb_mod_mask_t
1108 mod_mask_get_effective(struct xkb_keymap *keymap, xkb_mod_mask_t mods)
1109 {
1110     const struct xkb_mod *mod;
1111     xkb_mod_index_t i;
1112     xkb_mod_mask_t mask;
1113
1114     /* The effective mask is only real mods for now. */
1115     mask = mods & MOD_REAL_MASK_ALL;
1116
1117     xkb_mods_enumerate(i, mod, &keymap->mods)
1118         if (mods & (1u << i))
1119             mask |= mod->mapping;
1120
1121     return mask;
1122 }
1123
1124 /**
1125  * Returns 1 if the given modifier is active with the specified type(s), 0 if
1126  * not, or -1 if the modifier is invalid.
1127  */
1128 XKB_EXPORT int
1129 xkb_state_mod_index_is_active(struct xkb_state *state,
1130                               xkb_mod_index_t idx,
1131                               enum xkb_state_component type)
1132 {
1133     if (idx >= xkb_keymap_num_mods(state->keymap))
1134         return -1;
1135
1136     return !!(xkb_state_serialize_mods(state, type) & (1u << idx));
1137 }
1138
1139 /**
1140  * Helper function for xkb_state_mod_indices_are_active and
1141  * xkb_state_mod_names_are_active.
1142  */
1143 static bool
1144 match_mod_masks(struct xkb_state *state,
1145                 enum xkb_state_component type,
1146                 enum xkb_state_match match,
1147                 xkb_mod_mask_t wanted)
1148 {
1149     xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
1150
1151     if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
1152         return false;
1153
1154     if (match & XKB_STATE_MATCH_ANY)
1155         return active & wanted;
1156
1157     return (active & wanted) == wanted;
1158 }
1159
1160 /**
1161  * Returns 1 if the modifiers are active with the specified type(s), 0 if
1162  * not, or -1 if any of the modifiers are invalid.
1163  */
1164 XKB_EXPORT int
1165 xkb_state_mod_indices_are_active(struct xkb_state *state,
1166                                  enum xkb_state_component type,
1167                                  enum xkb_state_match match,
1168                                  ...)
1169 {
1170     va_list ap;
1171     xkb_mod_mask_t wanted = 0;
1172     int ret = 0;
1173     xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
1174
1175     va_start(ap, match);
1176     while (1) {
1177         xkb_mod_index_t idx = va_arg(ap, xkb_mod_index_t);
1178         if (idx == XKB_MOD_INVALID)
1179             break;
1180         if (idx >= num_mods) {
1181             ret = -1;
1182             break;
1183         }
1184         wanted |= (1u << idx);
1185     }
1186     va_end(ap);
1187
1188     if (ret == -1)
1189         return ret;
1190
1191     return match_mod_masks(state, type, match, wanted);
1192 }
1193
1194 /**
1195  * Returns 1 if the given modifier is active with the specified type(s), 0 if
1196  * not, or -1 if the modifier is invalid.
1197  */
1198 XKB_EXPORT int
1199 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
1200                              enum xkb_state_component type)
1201 {
1202     xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
1203
1204     if (idx == XKB_MOD_INVALID)
1205         return -1;
1206
1207     return xkb_state_mod_index_is_active(state, idx, type);
1208 }
1209
1210 /**
1211  * Returns 1 if the modifiers are active with the specified type(s), 0 if
1212  * not, or -1 if any of the modifiers are invalid.
1213  */
1214 XKB_EXPORT ATTR_NULL_SENTINEL int
1215 xkb_state_mod_names_are_active(struct xkb_state *state,
1216                                enum xkb_state_component type,
1217                                enum xkb_state_match match,
1218                                ...)
1219 {
1220     va_list ap;
1221     xkb_mod_mask_t wanted = 0;
1222     int ret = 0;
1223
1224     va_start(ap, match);
1225     while (1) {
1226         xkb_mod_index_t idx;
1227         const char *str = va_arg(ap, const char *);
1228         if (str == NULL)
1229             break;
1230         idx = xkb_keymap_mod_get_index(state->keymap, str);
1231         if (idx == XKB_MOD_INVALID) {
1232             ret = -1;
1233             break;
1234         }
1235         wanted |= (1u << idx);
1236     }
1237     va_end(ap);
1238
1239     if (ret == -1)
1240         return ret;
1241
1242     return match_mod_masks(state, type, match, wanted);
1243 }
1244
1245 /**
1246  * Returns 1 if the given group is active with the specified type(s), 0 if
1247  * not, or -1 if the group is invalid.
1248  */
1249 XKB_EXPORT int
1250 xkb_state_layout_index_is_active(struct xkb_state *state,
1251                                 xkb_layout_index_t idx,
1252                                 enum xkb_state_component type)
1253 {
1254     int ret = 0;
1255
1256     if (idx >= state->keymap->num_groups)
1257         return -1;
1258
1259     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1260         ret |= (state->components.group == idx);
1261     if (type & XKB_STATE_LAYOUT_DEPRESSED)
1262         ret |= (state->components.base_group == (int32_t) idx);
1263     if (type & XKB_STATE_LAYOUT_LATCHED)
1264         ret |= (state->components.latched_group == (int32_t) idx);
1265     if (type & XKB_STATE_LAYOUT_LOCKED)
1266         ret |= (state->components.locked_group == (int32_t) idx);
1267
1268     return ret;
1269 }
1270
1271 /**
1272  * Returns 1 if the given modifier is active with the specified type(s), 0 if
1273  * not, or -1 if the modifier is invalid.
1274  */
1275 XKB_EXPORT int
1276 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
1277                                 enum xkb_state_component type)
1278 {
1279     xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
1280
1281     if (idx == XKB_LAYOUT_INVALID)
1282         return -1;
1283
1284     return xkb_state_layout_index_is_active(state, idx, type);
1285 }
1286
1287 /**
1288  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1289  */
1290 XKB_EXPORT int
1291 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1292 {
1293     if (idx >= state->keymap->num_leds ||
1294         state->keymap->leds[idx].name == XKB_ATOM_NONE)
1295         return -1;
1296
1297     return !!(state->components.leds & (1u << idx));
1298 }
1299
1300 /**
1301  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1302  */
1303 XKB_EXPORT int
1304 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1305 {
1306     xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1307
1308     if (idx == XKB_LED_INVALID)
1309         return -1;
1310
1311     return xkb_state_led_index_is_active(state, idx);
1312 }
1313
1314 /**
1315  * See:
1316  * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11.
1317  * - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+.
1318  */
1319 static xkb_mod_mask_t
1320 key_get_consumed(struct xkb_state *state, const struct xkb_key *key,
1321                  enum xkb_consumed_mode mode)
1322 {
1323     const struct xkb_key_type *type;
1324     const struct xkb_key_type_entry *matching_entry;
1325     xkb_mod_mask_t preserve = 0;
1326     xkb_layout_index_t group;
1327     xkb_mod_mask_t consumed = 0;
1328
1329     group = xkb_state_key_get_layout(state, key->keycode);
1330     if (group == XKB_LAYOUT_INVALID)
1331         return 0;
1332
1333     type = key->groups[group].type;
1334
1335     matching_entry = get_entry_for_key_state(state, key, group);
1336     if (matching_entry)
1337         preserve = matching_entry->preserve.mask;
1338
1339     switch (mode) {
1340     case XKB_CONSUMED_MODE_XKB:
1341         consumed = type->mods.mask;
1342         break;
1343
1344     case XKB_CONSUMED_MODE_GTK: {
1345         const struct xkb_key_type_entry *no_mods_entry;
1346         xkb_level_index_t no_mods_leveli;
1347         const struct xkb_level *no_mods_level, *level;
1348
1349         no_mods_entry = get_entry_for_mods(type, 0);
1350         no_mods_leveli = no_mods_entry ? no_mods_entry->level : 0;
1351         no_mods_level = &key->groups[group].levels[no_mods_leveli];
1352
1353         for (unsigned i = 0; i < type->num_entries; i++) {
1354             const struct xkb_key_type_entry *entry = &type->entries[i];
1355             if (!entry_is_active(entry))
1356                 continue;
1357
1358             level = &key->groups[group].levels[entry->level];
1359             if (XkbLevelsSameSyms(level, no_mods_level))
1360                 continue;
1361
1362             if (entry == matching_entry || popcount(entry->mods.mask) == 1)
1363                 consumed |= entry->mods.mask & ~entry->preserve.mask;
1364         }
1365         break;
1366     }
1367     }
1368
1369     return consumed & ~preserve;
1370 }
1371
1372 XKB_EXPORT int
1373 xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t kc,
1374                                  xkb_mod_index_t idx,
1375                                  enum xkb_consumed_mode mode)
1376 {
1377     const struct xkb_key *key = XkbKey(state->keymap, kc);
1378
1379     if (!key || idx >= xkb_keymap_num_mods(state->keymap))
1380         return -1;
1381
1382     return !!((1u << idx) & key_get_consumed(state, key, mode));
1383 }
1384
1385 XKB_EXPORT int
1386 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1387                                 xkb_mod_index_t idx)
1388 {
1389     return xkb_state_mod_index_is_consumed2(state, kc, idx,
1390                                             XKB_CONSUMED_MODE_XKB);
1391 }
1392
1393 XKB_EXPORT xkb_mod_mask_t
1394 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1395                                    xkb_mod_mask_t mask)
1396 {
1397     const struct xkb_key *key = XkbKey(state->keymap, kc);
1398
1399     if (!key)
1400         return 0;
1401
1402     return mask & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB);
1403 }
1404
1405 XKB_EXPORT xkb_mod_mask_t
1406 xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc,
1407                                  enum xkb_consumed_mode mode)
1408 {
1409     const struct xkb_key *key;
1410
1411     switch (mode) {
1412     case XKB_CONSUMED_MODE_XKB:
1413     case XKB_CONSUMED_MODE_GTK:
1414         break;
1415     default:
1416         log_err_func(state->keymap->ctx,
1417                      "unrecognized consumed modifiers mode: %d\n", mode);
1418         return 0;
1419     }
1420
1421     key = XkbKey(state->keymap, kc);
1422     if (!key)
1423         return 0;
1424
1425     return key_get_consumed(state, key, mode);
1426 }
1427
1428 XKB_EXPORT xkb_mod_mask_t
1429 xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc)
1430 {
1431     return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB);
1432 }