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