state: remove unneeded NULL check
[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 void
268 xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
269 {
270     filter->priv = state->components.base_group;
271     if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
272         state->components.base_group = filter->action.group.group;
273     else
274         state->components.base_group += filter->action.group.group;
275 }
276
277 static bool
278 xkb_filter_group_set_func(struct xkb_state *state,
279                           struct xkb_filter *filter,
280                           const struct xkb_key *key,
281                           enum xkb_key_direction direction)
282 {
283     if (key != filter->key) {
284         filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
285         return true;
286     }
287
288     if (direction == XKB_KEY_DOWN) {
289         filter->refcnt++;
290         return false;
291     }
292     else if (--filter->refcnt > 0) {
293         return false;
294     }
295
296     state->components.base_group = filter->priv;
297
298     if (filter->action.group.flags & ACTION_LOCK_CLEAR)
299         state->components.locked_group = 0;
300
301     filter->func = NULL;
302     return true;
303 }
304
305 static void
306 xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
307 {
308     if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
309         state->components.locked_group = filter->action.group.group;
310     else
311         state->components.locked_group += filter->action.group.group;
312 }
313
314 static bool
315 xkb_filter_group_lock_func(struct xkb_state *state,
316                            struct xkb_filter *filter,
317                            const struct xkb_key *key,
318                            enum xkb_key_direction direction)
319 {
320     if (key != filter->key)
321         return true;
322
323     if (direction == XKB_KEY_DOWN) {
324         filter->refcnt++;
325         return false;
326     }
327     if (--filter->refcnt > 0)
328         return false;
329
330     filter->func = NULL;
331     return true;
332 }
333
334 static void
335 xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
336 {
337     state->set_mods = filter->action.mods.mods.mask;
338 }
339
340 static bool
341 xkb_filter_mod_set_func(struct xkb_state *state,
342                         struct xkb_filter *filter,
343                         const struct xkb_key *key,
344                         enum xkb_key_direction direction)
345 {
346     if (key != filter->key) {
347         filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
348         return true;
349     }
350
351     if (direction == XKB_KEY_DOWN) {
352         filter->refcnt++;
353         return false;
354     }
355     else if (--filter->refcnt > 0) {
356         return false;
357     }
358
359     state->clear_mods = filter->action.mods.mods.mask;
360     if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
361         state->components.locked_mods &= ~filter->action.mods.mods.mask;
362
363     filter->func = NULL;
364     return true;
365 }
366
367 static void
368 xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
369 {
370     filter->priv = (state->components.locked_mods &
371                     filter->action.mods.mods.mask);
372     state->set_mods |= filter->action.mods.mods.mask;
373     if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
374         state->components.locked_mods |= filter->action.mods.mods.mask;
375 }
376
377 static bool
378 xkb_filter_mod_lock_func(struct xkb_state *state,
379                          struct xkb_filter *filter,
380                          const struct xkb_key *key,
381                          enum xkb_key_direction direction)
382 {
383     if (key != filter->key)
384         return true;
385
386     if (direction == XKB_KEY_DOWN) {
387         filter->refcnt++;
388         return false;
389     }
390     if (--filter->refcnt > 0)
391         return false;
392
393     state->clear_mods |= filter->action.mods.mods.mask;
394     if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
395         state->components.locked_mods &= ~filter->priv;
396
397     filter->func = NULL;
398     return true;
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 void
425 xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
426 {
427     filter->priv = LATCH_KEY_DOWN;
428     state->set_mods = filter->action.mods.mods.mask;
429 }
430
431 static bool
432 xkb_filter_mod_latch_func(struct xkb_state *state,
433                           struct xkb_filter *filter,
434                           const struct xkb_key *key,
435                           enum xkb_key_direction direction)
436 {
437     enum xkb_key_latch_state latch = filter->priv;
438
439     if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
440         /* If this is a new keypress and we're awaiting our single latched
441          * keypress, then either break the latch if any random key is pressed,
442          * or promote it to a lock or plain base set if it's the same
443          * modifier. */
444         const union xkb_action *action = xkb_key_get_action(state, key);
445         if (action->type == ACTION_TYPE_MOD_LATCH &&
446             action->mods.flags == filter->action.mods.flags &&
447             action->mods.mods.mask == filter->action.mods.mods.mask) {
448             filter->action = *action;
449             if (filter->action.mods.flags & ACTION_LATCH_TO_LOCK) {
450                 filter->action.type = ACTION_TYPE_MOD_LOCK;
451                 filter->func = xkb_filter_mod_lock_func;
452                 state->components.locked_mods |= filter->action.mods.mods.mask;
453             }
454             else {
455                 filter->action.type = ACTION_TYPE_MOD_SET;
456                 filter->func = xkb_filter_mod_set_func;
457                 state->set_mods = filter->action.mods.mods.mask;
458             }
459             filter->key = key;
460             state->components.latched_mods &= ~filter->action.mods.mods.mask;
461             /* XXX beep beep! */
462             return false;
463         }
464         else if (xkb_action_breaks_latch(action)) {
465             /* XXX: This may be totally broken, we might need to break the
466              *      latch in the next run after this press? */
467             state->components.latched_mods &= ~filter->action.mods.mods.mask;
468             filter->func = NULL;
469             return true;
470         }
471     }
472     else if (direction == XKB_KEY_UP && key == filter->key) {
473         /* Our key got released.  If we've set it to clear locks, and we
474          * currently have the same modifiers locked, then release them and
475          * don't actually latch.  Else we've actually hit the latching
476          * stage, so set PENDING and move our modifier from base to
477          * latched. */
478         if (latch == NO_LATCH ||
479             ((filter->action.mods.flags & ACTION_LOCK_CLEAR) &&
480              (state->components.locked_mods & filter->action.mods.mods.mask) ==
481              filter->action.mods.mods.mask)) {
482             /* XXX: We might be a bit overenthusiastic about clearing
483              *      mods other filters have set here? */
484             if (latch == LATCH_PENDING)
485                 state->components.latched_mods &=
486                     ~filter->action.mods.mods.mask;
487             else
488                 state->clear_mods = filter->action.mods.mods.mask;
489             state->components.locked_mods &= ~filter->action.mods.mods.mask;
490             filter->func = NULL;
491         }
492         else {
493             latch = LATCH_PENDING;
494             state->clear_mods = filter->action.mods.mods.mask;
495             state->components.latched_mods |= filter->action.mods.mods.mask;
496             /* XXX beep beep! */
497         }
498     }
499     else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
500         /* Someone's pressed another key while we've still got the latching
501          * key held down, so keep the base modifier state active (from
502          * xkb_filter_mod_latch_new), but don't trip the latch, just clear
503          * it as soon as the modifier gets released. */
504         latch = NO_LATCH;
505     }
506
507     filter->priv = latch;
508
509     return true;
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     filter->key = key;
571     filter->func = filter_action_funcs[action->type].func;
572     filter->action = *action;
573     filter_action_funcs[action->type].new(state, filter);
574 }
575
576 XKB_EXPORT struct xkb_state *
577 xkb_state_new(struct xkb_keymap *keymap)
578 {
579     struct xkb_state *ret;
580
581     ret = calloc(sizeof(*ret), 1);
582     if (!ret)
583         return NULL;
584
585     ret->refcnt = 1;
586     ret->keymap = xkb_keymap_ref(keymap);
587
588     return ret;
589 }
590
591 XKB_EXPORT struct xkb_state *
592 xkb_state_ref(struct xkb_state *state)
593 {
594     state->refcnt++;
595     return state;
596 }
597
598 XKB_EXPORT void
599 xkb_state_unref(struct xkb_state *state)
600 {
601     if (!state || --state->refcnt > 0)
602         return;
603
604     xkb_keymap_unref(state->keymap);
605     darray_free(state->filters);
606     free(state);
607 }
608
609 XKB_EXPORT struct xkb_keymap *
610 xkb_state_get_keymap(struct xkb_state *state)
611 {
612     return state->keymap;
613 }
614
615 /**
616  * Update the LED state to match the rest of the xkb_state.
617  */
618 static void
619 xkb_state_led_update_all(struct xkb_state *state)
620 {
621     xkb_led_index_t idx;
622     const struct xkb_led *led;
623
624     state->components.leds = 0;
625
626     xkb_leds_enumerate(idx, led, state->keymap) {
627         xkb_mod_mask_t mod_mask = 0;
628         xkb_layout_mask_t group_mask = 0;
629
630         if (led->which_mods != 0 && led->mods.mask != 0) {
631             if (led->which_mods & XKB_STATE_MODS_EFFECTIVE)
632                 mod_mask |= state->components.mods;
633             if (led->which_mods & XKB_STATE_MODS_DEPRESSED)
634                 mod_mask |= state->components.base_mods;
635             if (led->which_mods & XKB_STATE_MODS_LATCHED)
636                 mod_mask |= state->components.latched_mods;
637             if (led->which_mods & XKB_STATE_MODS_LOCKED)
638                 mod_mask |= state->components.locked_mods;
639
640             if (led->mods.mask & mod_mask) {
641                 state->components.leds |= (1u << idx);
642                 continue;
643             }
644         }
645
646         if (led->which_groups != 0 && led->groups != 0) {
647             if (led->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
648                 group_mask |= (1u << state->components.group);
649             if (led->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
650                 group_mask |= (1u << state->components.base_group);
651             if (led->which_groups & XKB_STATE_LAYOUT_LATCHED)
652                 group_mask |= (1u << state->components.latched_group);
653             if (led->which_groups & XKB_STATE_LAYOUT_LOCKED)
654                 group_mask |= (1u << state->components.locked_group);
655
656             if (led->groups & group_mask) {
657                 state->components.leds |= (1u << idx);
658                 continue;
659             }
660         }
661
662         if (led->ctrls & state->keymap->enabled_ctrls) {
663             state->components.leds |= (1u << idx);
664             continue;
665         }
666     }
667 }
668
669 /**
670  * Calculates the derived state (effective mods/group and LEDs) from an
671  * up-to-date xkb_state.
672  */
673 static void
674 xkb_state_update_derived(struct xkb_state *state)
675 {
676     xkb_layout_index_t wrapped;
677
678     state->components.mods = (state->components.base_mods |
679                               state->components.latched_mods |
680                               state->components.locked_mods);
681
682     /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
683
684     wrapped = XkbWrapGroupIntoRange(state->components.locked_group,
685                                     state->keymap->num_groups,
686                                     RANGE_WRAP, 0);
687     state->components.locked_group =
688         (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
689
690     wrapped = XkbWrapGroupIntoRange(state->components.base_group +
691                                     state->components.latched_group +
692                                     state->components.locked_group,
693                                     state->keymap->num_groups,
694                                     RANGE_WRAP, 0);
695     state->components.group =
696         (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
697
698     xkb_state_led_update_all(state);
699 }
700
701 static enum xkb_state_component
702 get_state_component_changes(const struct state_components *a,
703                             const struct state_components *b)
704 {
705     xkb_mod_mask_t mask = 0;
706
707     if (a->group != b->group)
708         mask |= XKB_STATE_LAYOUT_EFFECTIVE;
709     if (a->base_group != b->base_group)
710         mask |= XKB_STATE_LAYOUT_DEPRESSED;
711     if (a->latched_group != b->latched_group)
712         mask |= XKB_STATE_LAYOUT_LATCHED;
713     if (a->locked_group != b->locked_group)
714         mask |= XKB_STATE_LAYOUT_LOCKED;
715     if (a->mods != b->mods)
716         mask |= XKB_STATE_MODS_EFFECTIVE;
717     if (a->base_mods != b->base_mods)
718         mask |= XKB_STATE_MODS_DEPRESSED;
719     if (a->latched_mods != b->latched_mods)
720         mask |= XKB_STATE_MODS_LATCHED;
721     if (a->locked_mods != b->locked_mods)
722         mask |= XKB_STATE_MODS_LOCKED;
723     if (a->leds != b->leds)
724         mask |= XKB_STATE_LEDS;
725
726     return mask;
727 }
728
729 /**
730  * Given a particular key event, updates the state structure to reflect the
731  * new modifiers.
732  */
733 XKB_EXPORT enum xkb_state_component
734 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
735                      enum xkb_key_direction direction)
736 {
737     xkb_mod_index_t i;
738     xkb_mod_mask_t bit;
739     struct state_components prev_components;
740     const struct xkb_key *key = XkbKey(state->keymap, kc);
741
742     if (!key)
743         return 0;
744
745     prev_components = state->components;
746
747     state->set_mods = 0;
748     state->clear_mods = 0;
749
750     xkb_filter_apply_all(state, key, direction);
751
752     for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
753         if (state->set_mods & bit) {
754             state->mod_key_count[i]++;
755             state->components.base_mods |= bit;
756             state->set_mods &= ~bit;
757         }
758     }
759
760     for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
761         if (state->clear_mods & bit) {
762             state->mod_key_count[i]--;
763             if (state->mod_key_count[i] <= 0) {
764                 state->components.base_mods &= ~bit;
765                 state->mod_key_count[i] = 0;
766             }
767             state->clear_mods &= ~bit;
768         }
769     }
770
771     xkb_state_update_derived(state);
772
773     return get_state_component_changes(&prev_components, &state->components);
774 }
775
776 /**
777  * Updates the state from a set of explicit masks as gained from
778  * xkb_state_serialize_mods and xkb_state_serialize_groups.  As noted in the
779  * documentation for these functions in xkbcommon.h, this round-trip is
780  * lossy, and should only be used to update a slave state mirroring the
781  * master, e.g. in a client/server window system.
782  */
783 XKB_EXPORT enum xkb_state_component
784 xkb_state_update_mask(struct xkb_state *state,
785                       xkb_mod_mask_t base_mods,
786                       xkb_mod_mask_t latched_mods,
787                       xkb_mod_mask_t locked_mods,
788                       xkb_layout_index_t base_group,
789                       xkb_layout_index_t latched_group,
790                       xkb_layout_index_t locked_group)
791 {
792     struct state_components prev_components;
793     xkb_mod_mask_t mask;
794
795     prev_components = state->components;
796
797     /* Only include modifiers which exist in the keymap. */
798     mask = (xkb_mod_mask_t) ((1ull << xkb_keymap_num_mods(state->keymap)) - 1u);
799
800     state->components.base_mods = base_mods & mask;
801     state->components.latched_mods = latched_mods & mask;
802     state->components.locked_mods = locked_mods & mask;
803
804     /* Make sure the mods are fully resolved - since we get arbitrary
805      * input, they might not be.
806      *
807      * It might seem more reasonable to do this only for components.mods
808      * in xkb_state_update_derived(), rather than for each component
809      * seperately.  That would allow to distinguish between "really"
810      * depressed mods (would be in MODS_DEPRESSED) and indirectly
811      * depressed to to a mapping (would only be in MODS_EFFECTIVE).
812      * However, the traditional behavior of xkb_state_update_key() is that
813      * if a vmod is depressed, its mappings are depressed with it; so we're
814      * expected to do the same here.  Also, LEDs (usually) look if a real
815      * mod is locked, not just effective; otherwise it won't be lit.
816      *
817      * We OR here because mod_mask_get_effective() drops vmods. */
818     state->components.base_mods |=
819         mod_mask_get_effective(state->keymap, state->components.base_mods);
820     state->components.latched_mods |=
821         mod_mask_get_effective(state->keymap, state->components.latched_mods);
822     state->components.locked_mods |=
823         mod_mask_get_effective(state->keymap, state->components.locked_mods);
824
825     state->components.base_group = base_group;
826     state->components.latched_group = latched_group;
827     state->components.locked_group = locked_group;
828
829     xkb_state_update_derived(state);
830
831     return get_state_component_changes(&prev_components, &state->components);
832 }
833
834 /**
835  * Provides the symbols to use for the given key and state.  Returns the
836  * number of symbols pointed to in syms_out.
837  */
838 XKB_EXPORT int
839 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
840                        const xkb_keysym_t **syms_out)
841 {
842     xkb_layout_index_t layout;
843     xkb_level_index_t level;
844
845     layout = xkb_state_key_get_layout(state, kc);
846     if (layout == XKB_LAYOUT_INVALID)
847         goto err;
848
849     level = xkb_state_key_get_level(state, kc, layout);
850     if (level == XKB_LEVEL_INVALID)
851         goto err;
852
853     return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
854                                             syms_out);
855
856 err:
857     *syms_out = NULL;
858     return 0;
859 }
860
861 /*
862  * http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
863  */
864 static bool
865 should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
866 {
867     xkb_mod_index_t caps =
868         xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CAPS);
869
870     return
871         xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0 &&
872         xkb_state_mod_index_is_consumed(state, kc, caps) == 0;
873 }
874
875 /*
876  * http://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
877  */
878 static bool
879 should_do_ctrl_transformation(struct xkb_state *state, xkb_keycode_t kc)
880 {
881     xkb_mod_index_t ctrl =
882         xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CTRL);
883
884     return
885         xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0 &&
886         xkb_state_mod_index_is_consumed(state, kc, ctrl) == 0;
887 }
888
889 /* Verbatim from libX11:src/xkb/XKBBind.c */
890 static char
891 XkbToControl(char ch)
892 {
893     char c = ch;
894
895     if ((c >= '@' && c < '\177') || c == ' ')
896         c &= 0x1F;
897     else if (c == '2')
898         c = '\000';
899     else if (c >= '3' && c <= '7')
900         c -= ('3' - '\033');
901     else if (c == '8')
902         c = '\177';
903     else if (c == '/')
904         c = '_' & 0x1F;
905     return c;
906 }
907
908 /**
909  * Provides either exactly one symbol, or XKB_KEY_NoSymbol.
910  */
911 XKB_EXPORT xkb_keysym_t
912 xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
913 {
914     const xkb_keysym_t *syms;
915     xkb_keysym_t sym;
916     int num_syms;
917
918     num_syms = xkb_state_key_get_syms(state, kc, &syms);
919     if (num_syms != 1)
920         return XKB_KEY_NoSymbol;
921
922     sym = syms[0];
923
924     if (should_do_caps_transformation(state, kc))
925         sym = xkb_keysym_to_upper(sym);
926
927     return sym;
928 }
929
930 /*
931  * The caps and ctrl transformations require some special handling,
932  * so we cannot simply use xkb_state_get_one_sym() for them.
933  * In particular, if Control is set, we must try very hard to find
934  * some layout in which the keysym is ASCII and thus can be (maybe)
935  * converted to a control character. libX11 allows to disable this
936  * behavior with the XkbLC_ControlFallback (see XkbSetXlibControls(3)),
937  * but it is enabled by default, yippee.
938  */
939 static xkb_keysym_t
940 get_one_sym_for_string(struct xkb_state *state, xkb_keycode_t kc)
941 {
942     xkb_level_index_t level;
943     xkb_layout_index_t layout, num_layouts;
944     const xkb_keysym_t *syms;
945     int nsyms;
946     xkb_keysym_t sym;
947
948     layout = xkb_state_key_get_layout(state, kc);
949     num_layouts = xkb_keymap_num_layouts_for_key(state->keymap, kc);
950     level = xkb_state_key_get_level(state, kc, layout);
951     if (layout == XKB_LAYOUT_INVALID || num_layouts == 0 ||
952         level == XKB_LEVEL_INVALID)
953         return XKB_KEY_NoSymbol;
954
955     nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
956                                              layout, level, &syms);
957     if (nsyms != 1)
958         return XKB_KEY_NoSymbol;
959     sym = syms[0];
960
961     if (should_do_ctrl_transformation(state, kc) && sym > 127u) {
962         for (xkb_layout_index_t i = 0; i < num_layouts; i++) {
963             level = xkb_state_key_get_level(state, kc, i);
964             if (level == XKB_LEVEL_INVALID)
965                 continue;
966
967             nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
968                                                      i, level, &syms);
969             if (nsyms == 1 && syms[0] <= 127u) {
970                 sym = syms[0];
971                 break;
972             }
973         }
974     }
975
976     if (should_do_caps_transformation(state, kc)) {
977         sym = xkb_keysym_to_upper(sym);
978     }
979
980     return sym;
981 }
982
983 XKB_EXPORT int
984 xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t kc,
985                        char *buffer, size_t size)
986 {
987     xkb_keysym_t sym;
988     const xkb_keysym_t *syms;
989     int nsyms;
990     int offset;
991     char tmp[7];
992
993     sym = get_one_sym_for_string(state, kc);
994     if (sym != XKB_KEY_NoSymbol) {
995         nsyms = 1; syms = &sym;
996     }
997     else {
998         nsyms = xkb_state_key_get_syms(state, kc, &syms);
999     }
1000
1001     /* Make sure not to truncate in the middle of a UTF-8 sequence. */
1002     offset = 0;
1003     for (int i = 0; i < nsyms; i++) {
1004         int ret = xkb_keysym_to_utf8(syms[i], tmp, sizeof(tmp));
1005         if (ret <= 0)
1006             goto err_bad;
1007
1008         ret--;
1009         if ((size_t) (offset + ret) <= size)
1010             memcpy(buffer + offset, tmp, ret);
1011         offset += ret;
1012     }
1013
1014     if ((size_t) offset >= size)
1015         goto err_trunc;
1016     buffer[offset] = '\0';
1017
1018     if (!is_valid_utf8(buffer, offset))
1019         goto err_bad;
1020
1021     if (offset == 1 && (unsigned int) buffer[0] <= 127u &&
1022         should_do_ctrl_transformation(state, kc))
1023         buffer[0] = XkbToControl(buffer[0]);
1024
1025     return offset;
1026
1027 err_trunc:
1028     if (size > 0)
1029         buffer[size - 1] = '\0';
1030     return offset;
1031
1032 err_bad:
1033     if (size > 0)
1034         buffer[0] = '\0';
1035     return 0;
1036 }
1037
1038 XKB_EXPORT uint32_t
1039 xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t kc)
1040 {
1041     xkb_keysym_t sym;
1042     uint32_t cp;
1043
1044     sym = get_one_sym_for_string(state, kc);
1045     cp = xkb_keysym_to_utf32(sym);
1046
1047     if (cp <= 127u && should_do_ctrl_transformation(state, kc))
1048         cp = (uint32_t) XkbToControl((char) cp);
1049
1050     return cp;
1051 }
1052
1053 /**
1054  * Serialises the requested modifier state into an xkb_mod_mask_t, with all
1055  * the same disclaimers as in xkb_state_update_mask.
1056  */
1057 XKB_EXPORT xkb_mod_mask_t
1058 xkb_state_serialize_mods(struct xkb_state *state,
1059                          enum xkb_state_component type)
1060 {
1061     xkb_mod_mask_t ret = 0;
1062
1063     if (type & XKB_STATE_MODS_EFFECTIVE)
1064         return state->components.mods;
1065
1066     if (type & XKB_STATE_MODS_DEPRESSED)
1067         ret |= state->components.base_mods;
1068     if (type & XKB_STATE_MODS_LATCHED)
1069         ret |= state->components.latched_mods;
1070     if (type & XKB_STATE_MODS_LOCKED)
1071         ret |= state->components.locked_mods;
1072
1073     return ret;
1074 }
1075
1076 /**
1077  * Serialises the requested group state, with all the same disclaimers as
1078  * in xkb_state_update_mask.
1079  */
1080 XKB_EXPORT xkb_layout_index_t
1081 xkb_state_serialize_layout(struct xkb_state *state,
1082                            enum xkb_state_component type)
1083 {
1084     xkb_layout_index_t ret = 0;
1085
1086     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1087         return state->components.group;
1088
1089     if (type & XKB_STATE_LAYOUT_DEPRESSED)
1090         ret += state->components.base_group;
1091     if (type & XKB_STATE_LAYOUT_LATCHED)
1092         ret += state->components.latched_group;
1093     if (type & XKB_STATE_LAYOUT_LOCKED)
1094         ret += state->components.locked_group;
1095
1096     return ret;
1097 }
1098
1099 /**
1100  * Gets a modifier mask and returns the resolved effective mask; this
1101  * is needed because some modifiers can also map to other modifiers, e.g.
1102  * the "NumLock" modifier usually also sets the "Mod2" modifier.
1103  */
1104 xkb_mod_mask_t
1105 mod_mask_get_effective(struct xkb_keymap *keymap, xkb_mod_mask_t mods)
1106 {
1107     const struct xkb_mod *mod;
1108     xkb_mod_index_t i;
1109     xkb_mod_mask_t mask;
1110
1111     /* The effective mask is only real mods for now. */
1112     mask = mods & MOD_REAL_MASK_ALL;
1113
1114     xkb_mods_enumerate(i, mod, &keymap->mods)
1115         if (mods & (1u << i))
1116             mask |= mod->mapping;
1117
1118     return mask;
1119 }
1120
1121 /**
1122  * Returns 1 if the given modifier is active with the specified type(s), 0 if
1123  * not, or -1 if the modifier is invalid.
1124  */
1125 XKB_EXPORT int
1126 xkb_state_mod_index_is_active(struct xkb_state *state,
1127                               xkb_mod_index_t idx,
1128                               enum xkb_state_component type)
1129 {
1130     if (idx >= xkb_keymap_num_mods(state->keymap))
1131         return -1;
1132
1133     return !!(xkb_state_serialize_mods(state, type) & (1u << idx));
1134 }
1135
1136 /**
1137  * Helper function for xkb_state_mod_indices_are_active and
1138  * xkb_state_mod_names_are_active.
1139  */
1140 static bool
1141 match_mod_masks(struct xkb_state *state,
1142                 enum xkb_state_component type,
1143                 enum xkb_state_match match,
1144                 xkb_mod_mask_t wanted)
1145 {
1146     xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
1147
1148     if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
1149         return false;
1150
1151     if (match & XKB_STATE_MATCH_ANY)
1152         return active & wanted;
1153
1154     return (active & wanted) == wanted;
1155 }
1156
1157 /**
1158  * Returns 1 if the modifiers are active with the specified type(s), 0 if
1159  * not, or -1 if any of the modifiers are invalid.
1160  */
1161 XKB_EXPORT int
1162 xkb_state_mod_indices_are_active(struct xkb_state *state,
1163                                  enum xkb_state_component type,
1164                                  enum xkb_state_match match,
1165                                  ...)
1166 {
1167     va_list ap;
1168     xkb_mod_mask_t wanted = 0;
1169     int ret = 0;
1170     xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
1171
1172     va_start(ap, match);
1173     while (1) {
1174         xkb_mod_index_t idx = va_arg(ap, xkb_mod_index_t);
1175         if (idx == XKB_MOD_INVALID)
1176             break;
1177         if (idx >= num_mods) {
1178             ret = -1;
1179             break;
1180         }
1181         wanted |= (1u << idx);
1182     }
1183     va_end(ap);
1184
1185     if (ret == -1)
1186         return ret;
1187
1188     return match_mod_masks(state, type, match, wanted);
1189 }
1190
1191 /**
1192  * Returns 1 if the given modifier is active with the specified type(s), 0 if
1193  * not, or -1 if the modifier is invalid.
1194  */
1195 XKB_EXPORT int
1196 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
1197                              enum xkb_state_component type)
1198 {
1199     xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
1200
1201     if (idx == XKB_MOD_INVALID)
1202         return -1;
1203
1204     return xkb_state_mod_index_is_active(state, idx, type);
1205 }
1206
1207 /**
1208  * Returns 1 if the modifiers are active with the specified type(s), 0 if
1209  * not, or -1 if any of the modifiers are invalid.
1210  */
1211 XKB_EXPORT ATTR_NULL_SENTINEL int
1212 xkb_state_mod_names_are_active(struct xkb_state *state,
1213                                enum xkb_state_component type,
1214                                enum xkb_state_match match,
1215                                ...)
1216 {
1217     va_list ap;
1218     xkb_mod_mask_t wanted = 0;
1219     int ret = 0;
1220
1221     va_start(ap, match);
1222     while (1) {
1223         xkb_mod_index_t idx;
1224         const char *str = va_arg(ap, const char *);
1225         if (str == NULL)
1226             break;
1227         idx = xkb_keymap_mod_get_index(state->keymap, str);
1228         if (idx == XKB_MOD_INVALID) {
1229             ret = -1;
1230             break;
1231         }
1232         wanted |= (1u << idx);
1233     }
1234     va_end(ap);
1235
1236     if (ret == -1)
1237         return ret;
1238
1239     return match_mod_masks(state, type, match, wanted);
1240 }
1241
1242 /**
1243  * Returns 1 if the given group is active with the specified type(s), 0 if
1244  * not, or -1 if the group is invalid.
1245  */
1246 XKB_EXPORT int
1247 xkb_state_layout_index_is_active(struct xkb_state *state,
1248                                 xkb_layout_index_t idx,
1249                                 enum xkb_state_component type)
1250 {
1251     int ret = 0;
1252
1253     if (idx >= state->keymap->num_groups)
1254         return -1;
1255
1256     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1257         ret |= (state->components.group == idx);
1258     if (type & XKB_STATE_LAYOUT_DEPRESSED)
1259         ret |= (state->components.base_group == (int32_t) idx);
1260     if (type & XKB_STATE_LAYOUT_LATCHED)
1261         ret |= (state->components.latched_group == (int32_t) idx);
1262     if (type & XKB_STATE_LAYOUT_LOCKED)
1263         ret |= (state->components.locked_group == (int32_t) idx);
1264
1265     return ret;
1266 }
1267
1268 /**
1269  * Returns 1 if the given modifier is active with the specified type(s), 0 if
1270  * not, or -1 if the modifier is invalid.
1271  */
1272 XKB_EXPORT int
1273 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
1274                                 enum xkb_state_component type)
1275 {
1276     xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
1277
1278     if (idx == XKB_LAYOUT_INVALID)
1279         return -1;
1280
1281     return xkb_state_layout_index_is_active(state, idx, type);
1282 }
1283
1284 /**
1285  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1286  */
1287 XKB_EXPORT int
1288 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1289 {
1290     if (idx >= state->keymap->num_leds ||
1291         state->keymap->leds[idx].name == XKB_ATOM_NONE)
1292         return -1;
1293
1294     return !!(state->components.leds & (1u << idx));
1295 }
1296
1297 /**
1298  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1299  */
1300 XKB_EXPORT int
1301 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1302 {
1303     xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1304
1305     if (idx == XKB_LED_INVALID)
1306         return -1;
1307
1308     return xkb_state_led_index_is_active(state, idx);
1309 }
1310
1311 /**
1312  * See:
1313  * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11.
1314  * - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+.
1315  */
1316 static xkb_mod_mask_t
1317 key_get_consumed(struct xkb_state *state, const struct xkb_key *key,
1318                  enum xkb_consumed_mode mode)
1319 {
1320     const struct xkb_key_type *type;
1321     const struct xkb_key_type_entry *matching_entry;
1322     xkb_mod_mask_t preserve = 0;
1323     xkb_layout_index_t group;
1324     xkb_mod_mask_t consumed = 0;
1325
1326     group = xkb_state_key_get_layout(state, key->keycode);
1327     if (group == XKB_LAYOUT_INVALID)
1328         return 0;
1329
1330     type = key->groups[group].type;
1331
1332     matching_entry = get_entry_for_key_state(state, key, group);
1333     if (matching_entry)
1334         preserve = matching_entry->preserve.mask;
1335
1336     switch (mode) {
1337     case XKB_CONSUMED_MODE_XKB:
1338         consumed = type->mods.mask;
1339         break;
1340
1341     case XKB_CONSUMED_MODE_GTK: {
1342         const struct xkb_key_type_entry *no_mods_entry;
1343         xkb_level_index_t no_mods_leveli;
1344         const struct xkb_level *no_mods_level, *level;
1345
1346         no_mods_entry = get_entry_for_mods(type, 0);
1347         no_mods_leveli = no_mods_entry ? no_mods_entry->level : 0;
1348         no_mods_level = &key->groups[group].levels[no_mods_leveli];
1349
1350         for (unsigned i = 0; i < type->num_entries; i++) {
1351             const struct xkb_key_type_entry *entry = &type->entries[i];
1352             if (!entry_is_active(entry))
1353                 continue;
1354
1355             level = &key->groups[group].levels[entry->level];
1356             if (XkbLevelsSameSyms(level, no_mods_level))
1357                 continue;
1358
1359             if (entry == matching_entry || my_popcount(entry->mods.mask) == 1)
1360                 consumed |= entry->mods.mask & ~entry->preserve.mask;
1361         }
1362         break;
1363     }
1364     }
1365
1366     return consumed & ~preserve;
1367 }
1368
1369 XKB_EXPORT int
1370 xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t kc,
1371                                  xkb_mod_index_t idx,
1372                                  enum xkb_consumed_mode mode)
1373 {
1374     const struct xkb_key *key = XkbKey(state->keymap, kc);
1375
1376     if (!key || idx >= xkb_keymap_num_mods(state->keymap))
1377         return -1;
1378
1379     return !!((1u << idx) & key_get_consumed(state, key, mode));
1380 }
1381
1382 XKB_EXPORT int
1383 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1384                                 xkb_mod_index_t idx)
1385 {
1386     return xkb_state_mod_index_is_consumed2(state, kc, idx,
1387                                             XKB_CONSUMED_MODE_XKB);
1388 }
1389
1390 XKB_EXPORT xkb_mod_mask_t
1391 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1392                                    xkb_mod_mask_t mask)
1393 {
1394     const struct xkb_key *key = XkbKey(state->keymap, kc);
1395
1396     if (!key)
1397         return 0;
1398
1399     return mask & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB);
1400 }
1401
1402 XKB_EXPORT xkb_mod_mask_t
1403 xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc,
1404                                  enum xkb_consumed_mode mode)
1405 {
1406     const struct xkb_key *key;
1407
1408     switch (mode) {
1409     case XKB_CONSUMED_MODE_XKB:
1410     case XKB_CONSUMED_MODE_GTK:
1411         break;
1412     default:
1413         log_err_func(state->keymap->ctx,
1414                      "unrecognized consumed modifiers mode: %d\n", mode);
1415         return 0;
1416     }
1417
1418     key = XkbKey(state->keymap, kc);
1419     if (!key)
1420         return 0;
1421
1422     return key_get_consumed(state, key, mode);
1423 }
1424
1425 XKB_EXPORT xkb_mod_mask_t
1426 xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc)
1427 {
1428     return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB);
1429 }