Split the mods, layout, leds parts of xkb_state_components
[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
64 struct xkb_filter {
65     union xkb_action action;
66     const struct xkb_key *key;
67     uint32_t priv;
68     int (*func)(struct xkb_state *state,
69                 struct xkb_filter *filter,
70                 const struct xkb_key *key,
71                 enum xkb_key_direction direction);
72     int refcnt;
73 };
74
75 struct xkb_state {
76     /* These may be negative, because of -1 group actions. */
77     int32_t base_group; /**< depressed */
78     int32_t latched_group;
79     int32_t locked_group;
80     xkb_layout_index_t group; /**< effective */
81
82     xkb_mod_mask_t base_mods; /**< depressed */
83     xkb_mod_mask_t latched_mods;
84     xkb_mod_mask_t locked_mods;
85     xkb_mod_mask_t mods; /**< effective */
86
87     /*
88      * At each event, we accumulate all the needed modifications to the base
89      * modifiers, and apply them at the end. These keep track of this state.
90      */
91     xkb_mod_mask_t set_mods;
92     xkb_mod_mask_t clear_mods;
93     /*
94      * We mustn't clear a base modifier if there's another depressed key
95      * which affects it, e.g. given this sequence
96      * < Left Shift down, Right Shift down, Left Shift Up >
97      * the modifier should still be set. This keeps the count.
98      */
99     int16_t mod_key_count[sizeof(xkb_mod_mask_t) * 8];
100
101     xkb_led_mask_t leds;
102
103     int refcnt;
104     darray(struct xkb_filter) filters;
105     struct xkb_keymap *keymap;
106 };
107
108 static const struct xkb_kt_map_entry *
109 get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
110                         xkb_layout_index_t group)
111 {
112     const struct xkb_key_type *type;
113     xkb_mod_mask_t active_mods;
114     unsigned int i;
115
116     type = key->groups[group].type;
117     active_mods = xkb_state_serialize_mods(state, XKB_STATE_MODS_EFFECTIVE);
118     active_mods &= type->mods.mask;
119
120     for (i = 0; i < type->num_entries; i++)
121         if (type->map[i].mods.mask == active_mods)
122             return &type->map[i];
123
124     return NULL;
125 }
126
127 /**
128  * Returns the level to use for the given key and state, or
129  * XKB_LEVEL_INVALID.
130  */
131 XKB_EXPORT xkb_level_index_t
132 xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
133                         xkb_layout_index_t layout)
134 {
135     const struct xkb_key *key = XkbKey(state->keymap, kc);
136     const struct xkb_kt_map_entry *entry;
137
138     if (!key || layout >= key->num_groups)
139         return XKB_LEVEL_INVALID;
140
141     /* If we don't find an explicit match the default is 0. */
142     entry = get_entry_for_key_state(state, key, layout);
143     if (!entry)
144         return 0;
145
146     return entry->level;
147 }
148
149 static xkb_layout_index_t
150 wrap_group_into_range(int32_t group,
151                       xkb_layout_index_t num_groups,
152                       enum xkb_range_exceed_type out_of_range_group_action,
153                       xkb_layout_index_t out_of_range_group_number)
154 {
155     if (num_groups == 0)
156         return XKB_LAYOUT_INVALID;
157
158     if (group < num_groups)
159         return group;
160
161     switch (out_of_range_group_action) {
162     case RANGE_REDIRECT:
163         if (out_of_range_group_number >= num_groups)
164             return 0;
165         return out_of_range_group_number;
166
167     case RANGE_SATURATE:
168         if (group < 0)
169             return 0;
170         else
171             return num_groups - 1;
172
173     case RANGE_WRAP:
174     default:
175         /*
176          * C99 says a negative dividend in a modulo operation always
177          * gives a negative result.
178          */
179         if (group < 0)
180             return ((int) num_groups + (group % (int) num_groups));
181         else
182             return group % num_groups;
183     }
184 }
185
186 /**
187  * Returns the layout to use for the given key and state, taking
188  * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
189  */
190 XKB_EXPORT xkb_layout_index_t
191 xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
192 {
193     xkb_layout_index_t group =
194         xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_EFFECTIVE);
195     const struct xkb_key *key = XkbKey(state->keymap, kc);
196
197     if (!key)
198         return XKB_LAYOUT_INVALID;
199
200     return wrap_group_into_range(group, key->num_groups,
201                                  key->out_of_range_group_action,
202                                  key->out_of_range_group_number);
203 }
204
205 static const union xkb_action fake = { .type = ACTION_TYPE_NONE };
206
207 static const union xkb_action *
208 xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
209 {
210     xkb_layout_index_t layout;
211     xkb_level_index_t level;
212
213     layout = xkb_state_key_get_layout(state, key->keycode);
214     if (layout == XKB_LAYOUT_INVALID)
215         return &fake;
216
217     level = xkb_state_key_get_level(state, key->keycode, layout);
218     if (level == XKB_LEVEL_INVALID)
219         return &fake;
220
221     return &key->groups[layout].levels[level].action;
222 }
223
224 static struct xkb_filter *
225 xkb_filter_new(struct xkb_state *state)
226 {
227     struct xkb_filter *filter = NULL, *iter;
228
229     darray_foreach(iter, state->filters) {
230         if (iter->func)
231             continue;
232         filter = iter;
233         break;
234     }
235
236     if (!filter) {
237         darray_resize0(state->filters, darray_size(state->filters) + 1);
238         filter = &darray_item(state->filters, darray_size(state->filters) -1);
239     }
240
241     filter->refcnt = 1;
242     return filter;
243 }
244
245 /***====================================================================***/
246
247 static int
248 xkb_filter_group_set_func(struct xkb_state *state,
249                           struct xkb_filter *filter,
250                           const struct xkb_key *key,
251                           enum xkb_key_direction direction)
252 {
253     if (key != filter->key) {
254         filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
255         return 1;
256     }
257
258     if (direction == XKB_KEY_DOWN) {
259         filter->refcnt++;
260         return 0;
261     }
262     else if (--filter->refcnt > 0) {
263         return 0;
264     }
265
266     state->base_group = filter->priv;
267
268     if (filter->action.group.flags & ACTION_LOCK_CLEAR)
269         state->locked_group = 0;
270
271     filter->func = NULL;
272     return 1;
273 }
274
275 static void
276 xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
277 {
278     filter->priv = state->base_group;
279     if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
280         state->base_group = filter->action.group.group;
281     else
282         state->base_group += filter->action.group.group;
283 }
284
285 static int
286 xkb_filter_group_lock_func(struct xkb_state *state,
287                            struct xkb_filter *filter,
288                            const struct xkb_key *key,
289                            enum xkb_key_direction direction)
290 {
291     if (key != filter->key)
292         return 1;
293
294     if (direction == XKB_KEY_DOWN) {
295         filter->refcnt++;
296         return 0;
297     }
298     if (--filter->refcnt > 0)
299         return 0;
300
301     filter->func = NULL;
302     return 1;
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->locked_group = filter->action.group.group;
310     else
311         state->locked_group += filter->action.group.group;
312 }
313
314 static int
315 xkb_filter_mod_set_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         filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
322         return 1;
323     }
324
325     if (direction == XKB_KEY_DOWN) {
326         filter->refcnt++;
327         return 0;
328     }
329     else if (--filter->refcnt > 0) {
330         return 0;
331     }
332
333     state->clear_mods = filter->action.mods.mods.mask;
334     if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
335         state->locked_mods &= ~filter->action.mods.mods.mask;
336
337     filter->func = NULL;
338     return 1;
339 }
340
341 static void
342 xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
343 {
344     state->set_mods = filter->action.mods.mods.mask;
345 }
346
347 static int
348 xkb_filter_mod_lock_func(struct xkb_state *state,
349                          struct xkb_filter *filter,
350                          const struct xkb_key *key,
351                          enum xkb_key_direction direction)
352 {
353     if (key != filter->key)
354         return 1;
355
356     if (direction == XKB_KEY_DOWN) {
357         filter->refcnt++;
358         return 0;
359     }
360     if (--filter->refcnt > 0)
361         return 0;
362
363     state->clear_mods |= filter->action.mods.mods.mask;
364     if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
365         state->locked_mods &= ~filter->priv;
366
367     filter->func = NULL;
368     return 1;
369 }
370
371 static void
372 xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
373 {
374     filter->priv = state->locked_mods & filter->action.mods.mods.mask;
375     state->set_mods |= filter->action.mods.mods.mask;
376     if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
377         state->locked_mods |= filter->action.mods.mods.mask;
378 }
379
380 enum xkb_key_latch_state {
381     NO_LATCH,
382     LATCH_KEY_DOWN,
383     LATCH_PENDING,
384 };
385
386 static bool
387 xkb_action_breaks_latch(const union xkb_action *action)
388 {
389     switch (action->type) {
390     case ACTION_TYPE_NONE:
391     case ACTION_TYPE_PTR_BUTTON:
392     case ACTION_TYPE_PTR_LOCK:
393     case ACTION_TYPE_CTRL_SET:
394     case ACTION_TYPE_CTRL_LOCK:
395     case ACTION_TYPE_KEY_REDIRECT:
396     case ACTION_TYPE_SWITCH_VT:
397     case ACTION_TYPE_TERMINATE:
398         return true;
399     default:
400         return false;
401     }
402 }
403
404 static int
405 xkb_filter_mod_latch_func(struct xkb_state *state,
406                           struct xkb_filter *filter,
407                           const struct xkb_key *key,
408                           enum xkb_key_direction direction)
409 {
410     enum xkb_key_latch_state latch = filter->priv;
411
412     if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
413         /* If this is a new keypress and we're awaiting our single latched
414          * keypress, then either break the latch if any random key is pressed,
415          * or promote it to a lock or plain base set if it's the same
416          * modifier. */
417         const union xkb_action *action = xkb_key_get_action(state, key);
418         if (action->type == ACTION_TYPE_MOD_LATCH &&
419             action->mods.flags == filter->action.mods.flags &&
420             action->mods.mods.mask == filter->action.mods.mods.mask) {
421             filter->action = *action;
422             if (filter->action.mods.flags & ACTION_LATCH_TO_LOCK) {
423                 filter->action.type = ACTION_TYPE_MOD_LOCK;
424                 filter->func = xkb_filter_mod_lock_func;
425                 state->locked_mods |= filter->action.mods.mods.mask;
426             }
427             else {
428                 filter->action.type = ACTION_TYPE_MOD_SET;
429                 filter->func = xkb_filter_mod_set_func;
430                 state->set_mods = filter->action.mods.mods.mask;
431             }
432             filter->key = key;
433             state->latched_mods &= ~filter->action.mods.mods.mask;
434             /* XXX beep beep! */
435             return 0;
436         }
437         else if (xkb_action_breaks_latch(action)) {
438             /* XXX: This may be totally broken, we might need to break the
439              *      latch in the next run after this press? */
440             state->latched_mods &= ~filter->action.mods.mods.mask;
441             filter->func = NULL;
442             return 1;
443         }
444     }
445     else if (direction == XKB_KEY_UP && key == filter->key) {
446         /* Our key got released.  If we've set it to clear locks, and we
447          * currently have the same modifiers locked, then release them and
448          * don't actually latch.  Else we've actually hit the latching
449          * stage, so set PENDING and move our modifier from base to
450          * latched. */
451         if (latch == NO_LATCH ||
452             ((filter->action.mods.flags & ACTION_LOCK_CLEAR) &&
453              (state->locked_mods & filter->action.mods.mods.mask) ==
454              filter->action.mods.mods.mask)) {
455             /* XXX: We might be a bit overenthusiastic about clearing
456              *      mods other filters have set here? */
457             if (latch == LATCH_PENDING)
458                 state->latched_mods &= ~filter->action.mods.mods.mask;
459             else
460                 state->clear_mods = filter->action.mods.mods.mask;
461             state->locked_mods &= ~filter->action.mods.mods.mask;
462             filter->func = NULL;
463         }
464         else {
465             latch = LATCH_PENDING;
466             state->clear_mods = filter->action.mods.mods.mask;
467             state->latched_mods |= filter->action.mods.mods.mask;
468             /* XXX beep beep! */
469         }
470     }
471     else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
472         /* Someone's pressed another key while we've still got the latching
473          * key held down, so keep the base modifier state active (from
474          * xkb_filter_mod_latch_new), but don't trip the latch, just clear
475          * it as soon as the modifier gets released. */
476         latch = NO_LATCH;
477     }
478
479     filter->priv = latch;
480
481     return 1;
482 }
483
484 static void
485 xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
486 {
487     filter->priv = LATCH_KEY_DOWN;
488     state->set_mods = filter->action.mods.mods.mask;
489 }
490
491 static const struct {
492     void (*new)(struct xkb_state *state, struct xkb_filter *filter);
493     int (*func)(struct xkb_state *state, struct xkb_filter *filter,
494                 const struct xkb_key *key, enum xkb_key_direction direction);
495 } filter_action_funcs[_ACTION_TYPE_NUM_ENTRIES] = {
496     [ACTION_TYPE_MOD_SET]    = { xkb_filter_mod_set_new,
497                                  xkb_filter_mod_set_func },
498     [ACTION_TYPE_MOD_LATCH]  = { xkb_filter_mod_latch_new,
499                                  xkb_filter_mod_latch_func },
500     [ACTION_TYPE_MOD_LOCK]   = { xkb_filter_mod_lock_new,
501                                  xkb_filter_mod_lock_func },
502     [ACTION_TYPE_GROUP_SET]  = { xkb_filter_group_set_new,
503                                  xkb_filter_group_set_func },
504     [ACTION_TYPE_GROUP_LOCK] = { xkb_filter_group_lock_new,
505                                  xkb_filter_group_lock_func },
506 };
507
508 /**
509  * Applies any relevant filters to the key, first from the list of filters
510  * that are currently active, then if no filter has claimed the key, possibly
511  * apply a new filter from the key action.
512  */
513 static void
514 xkb_filter_apply_all(struct xkb_state *state,
515                      const struct xkb_key *key,
516                      enum xkb_key_direction direction)
517 {
518     struct xkb_filter *filter;
519     const union xkb_action *action;
520     int send = 1;
521
522     /* First run through all the currently active filters and see if any of
523      * them have claimed this event. */
524     darray_foreach(filter, state->filters) {
525         if (!filter->func)
526             continue;
527         send &= filter->func(state, filter, key, direction);
528     }
529
530     if (!send || direction == XKB_KEY_UP)
531         return;
532
533     action = xkb_key_get_action(state, key);
534     if (!filter_action_funcs[action->type].new)
535         return;
536
537     filter = xkb_filter_new(state);
538     if (!filter)
539         return; /* WSGO */
540
541     filter->key = key;
542     filter->func = filter_action_funcs[action->type].func;
543     filter->action = *action;
544     filter_action_funcs[action->type].new(state, filter);
545 }
546
547 XKB_EXPORT struct xkb_state *
548 xkb_state_new(struct xkb_keymap *keymap)
549 {
550     struct xkb_state *ret;
551
552     ret = calloc(sizeof(*ret), 1);
553     if (!ret)
554         return NULL;
555
556     ret->refcnt = 1;
557     ret->keymap = xkb_keymap_ref(keymap);
558
559     return ret;
560 }
561
562 XKB_EXPORT struct xkb_state *
563 xkb_state_ref(struct xkb_state *state)
564 {
565     state->refcnt++;
566     return state;
567 }
568
569 XKB_EXPORT void
570 xkb_state_unref(struct xkb_state *state)
571 {
572     if (--state->refcnt > 0)
573         return;
574
575     xkb_keymap_unref(state->keymap);
576     darray_free(state->filters);
577     free(state);
578 }
579
580 XKB_EXPORT struct xkb_keymap *
581 xkb_state_get_keymap(struct xkb_state *state)
582 {
583     return state->keymap;
584 }
585
586 /**
587  * Update the LED state to match the rest of the xkb_state.
588  */
589 static void
590 xkb_state_led_update_all(struct xkb_state *state)
591 {
592     xkb_led_index_t led;
593     const struct xkb_indicator_map *map;
594
595     state->leds = 0;
596
597     darray_enumerate(led, map, state->keymap->indicators) {
598         xkb_mod_mask_t mod_mask = 0;
599         xkb_layout_mask_t group_mask = 0;
600
601         if (map->which_mods & XKB_STATE_MODS_EFFECTIVE)
602             mod_mask |= state->mods;
603         if (map->which_mods & XKB_STATE_MODS_DEPRESSED)
604             mod_mask |= state->base_mods;
605         if (map->which_mods & XKB_STATE_MODS_LATCHED)
606             mod_mask |= state->latched_mods;
607         if (map->which_mods & XKB_STATE_MODS_LOCKED)
608             mod_mask |= state->locked_mods;
609         if (map->mods.mask & mod_mask)
610             state->leds |= (1 << led);
611
612         if (map->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
613             group_mask |= (1 << state->group);
614         if (map->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
615             group_mask |= (1 << state->base_group);
616         if (map->which_groups & XKB_STATE_LAYOUT_LATCHED)
617             group_mask |= (1 << state->latched_group);
618         if (map->which_groups & XKB_STATE_LAYOUT_LOCKED)
619             group_mask |= (1 << state->locked_group);
620         if (map->groups & group_mask)
621             state->leds |= (1 << led);
622
623         if (map->ctrls & state->keymap->enabled_ctrls)
624             state->leds |= (1 << led);
625     }
626 }
627
628 /**
629  * Calculates the derived state (effective mods/group and LEDs) from an
630  * up-to-date xkb_state.
631  */
632 static void
633 xkb_state_update_derived(struct xkb_state *state)
634 {
635     xkb_layout_index_t num_groups = xkb_keymap_num_layouts(state->keymap);
636
637     state->mods = (state->base_mods |
638                    state->latched_mods |
639                    state->locked_mods);
640
641     /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
642
643     state->locked_group = wrap_group_into_range(state->locked_group,
644                                                 num_groups,
645                                                 RANGE_WRAP, 0);
646
647     state->group = wrap_group_into_range(state->base_group +
648                                          state->latched_group +
649                                          state->locked_group,
650                                          num_groups,
651                                          RANGE_WRAP, 0);
652
653     xkb_state_led_update_all(state);
654 }
655
656 /**
657  * Given a particular key event, updates the state structure to reflect the
658  * new modifiers.
659  */
660 XKB_EXPORT void
661 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
662                      enum xkb_key_direction direction)
663 {
664     xkb_mod_index_t i;
665     xkb_mod_mask_t bit;
666     const struct xkb_key *key = XkbKey(state->keymap, kc);
667
668     if (!key)
669         return;
670
671     state->set_mods = 0;
672     state->clear_mods = 0;
673
674     xkb_filter_apply_all(state, key, direction);
675
676     for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
677         if (state->set_mods & bit) {
678             state->mod_key_count[i]++;
679             state->base_mods |= bit;
680             state->set_mods &= ~bit;
681         }
682     }
683
684     for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
685         if (state->clear_mods & bit) {
686             state->mod_key_count[i]--;
687             if (state->mod_key_count[i] <= 0) {
688                 state->base_mods &= ~bit;
689                 state->mod_key_count[i] = 0;
690             }
691             state->clear_mods &= ~bit;
692         }
693     }
694
695     xkb_state_update_derived(state);
696 }
697
698 /**
699  * Updates the state from a set of explicit masks as gained from
700  * xkb_state_serialize_mods and xkb_state_serialize_groups.  As noted in the
701  * documentation for these functions in xkbcommon.h, this round-trip is
702  * lossy, and should only be used to update a slave state mirroring the
703  * master, e.g. in a client/server window system.
704  */
705 XKB_EXPORT void
706 xkb_state_update_mask(struct xkb_state *state,
707                       xkb_mod_mask_t base_mods,
708                       xkb_mod_mask_t latched_mods,
709                       xkb_mod_mask_t locked_mods,
710                       xkb_layout_index_t base_group,
711                       xkb_layout_index_t latched_group,
712                       xkb_layout_index_t locked_group)
713 {
714     xkb_mod_index_t num_mods;
715     xkb_mod_index_t idx;
716
717     state->base_mods = 0;
718     state->latched_mods = 0;
719     state->locked_mods = 0;
720     num_mods = xkb_keymap_num_mods(state->keymap);
721
722     for (idx = 0; idx < num_mods; idx++) {
723         xkb_mod_mask_t mod = (1 << idx);
724         if (base_mods & mod)
725             state->base_mods |= mod;
726         if (latched_mods & mod)
727             state->latched_mods |= mod;
728         if (locked_mods & mod)
729             state->locked_mods |= mod;
730     }
731
732     state->base_group = base_group;
733     state->latched_group = latched_group;
734     state->locked_group = locked_group;
735
736     xkb_state_update_derived(state);
737 }
738
739 /**
740  * Provides the symbols to use for the given key and state.  Returns the
741  * number of symbols pointed to in syms_out.
742  */
743 XKB_EXPORT int
744 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
745                        const xkb_keysym_t **syms_out)
746 {
747     xkb_layout_index_t layout;
748     xkb_level_index_t level;
749
750     layout = xkb_state_key_get_layout(state, kc);
751     if (layout == XKB_LAYOUT_INVALID)
752         goto err;
753
754     level = xkb_state_key_get_level(state, kc, layout);
755     if (level == XKB_LEVEL_INVALID)
756         goto err;
757
758     return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
759                                             syms_out);
760
761 err:
762     *syms_out = NULL;
763     return 0;
764 }
765
766 /**
767  * Provides either exactly one symbol, or XKB_KEY_NoSymbol.
768  */
769 XKB_EXPORT xkb_keysym_t
770 xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
771 {
772     const xkb_keysym_t *syms;
773     int num_syms;
774
775     num_syms = xkb_state_key_get_syms(state, kc, &syms);
776     if (num_syms != 1)
777         return XKB_KEY_NoSymbol;
778
779     return syms[0];
780 }
781
782 /**
783  * Serialises the requested modifier state into an xkb_mod_mask_t, with all
784  * the same disclaimers as in xkb_state_update_mask.
785  */
786 XKB_EXPORT xkb_mod_mask_t
787 xkb_state_serialize_mods(struct xkb_state *state,
788                          enum xkb_state_component type)
789 {
790     xkb_mod_mask_t ret = 0;
791
792     if (type & XKB_STATE_MODS_EFFECTIVE)
793         return state->mods;
794
795     if (type & XKB_STATE_MODS_DEPRESSED)
796         ret |= state->base_mods;
797     if (type & XKB_STATE_MODS_LATCHED)
798         ret |= state->latched_mods;
799     if (type & XKB_STATE_MODS_LOCKED)
800         ret |= state->locked_mods;
801
802     return ret;
803 }
804
805 /**
806  * Serialises the requested group state, with all the same disclaimers as
807  * in xkb_state_update_mask.
808  */
809 XKB_EXPORT xkb_layout_index_t
810 xkb_state_serialize_layout(struct xkb_state *state,
811                            enum xkb_state_component type)
812 {
813     xkb_layout_index_t ret = 0;
814
815     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
816         return state->group;
817
818     if (type & XKB_STATE_LAYOUT_DEPRESSED)
819         ret += state->base_group;
820     if (type & XKB_STATE_LAYOUT_LATCHED)
821         ret += state->latched_group;
822     if (type & XKB_STATE_LAYOUT_LOCKED)
823         ret += state->locked_group;
824
825     return ret;
826 }
827
828 /**
829  * Returns 1 if the given modifier is active with the specified type(s), 0 if
830  * not, or -1 if the modifier is invalid.
831  */
832 XKB_EXPORT int
833 xkb_state_mod_index_is_active(struct xkb_state *state,
834                               xkb_mod_index_t idx,
835                               enum xkb_state_component type)
836 {
837     if (idx >= xkb_keymap_num_mods(state->keymap))
838         return -1;
839
840     return !!(xkb_state_serialize_mods(state, type) & (1 << idx));
841 }
842
843 /**
844  * Helper function for xkb_state_mod_indices_are_active and
845  * xkb_state_mod_names_are_active.
846  */
847 static int
848 match_mod_masks(struct xkb_state *state,
849                 enum xkb_state_component type,
850                 enum xkb_state_match match,
851                 xkb_mod_mask_t wanted)
852 {
853     xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
854
855     if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
856         return 0;
857
858     if (match & XKB_STATE_MATCH_ANY)
859         return !!(active & wanted);
860     else
861         return (active & wanted) == wanted;
862
863     return 0;
864 }
865
866 /**
867  * Returns 1 if the modifiers are active with the specified type(s), 0 if
868  * not, or -1 if any of the modifiers are invalid.
869  */
870 XKB_EXPORT int
871 xkb_state_mod_indices_are_active(struct xkb_state *state,
872                                  enum xkb_state_component type,
873                                  enum xkb_state_match match,
874                                  ...)
875 {
876     va_list ap;
877     xkb_mod_index_t idx = 0;
878     xkb_mod_mask_t wanted = 0;
879     int ret = 0;
880     xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
881
882     va_start(ap, match);
883     while (1) {
884         idx = va_arg(ap, xkb_mod_index_t);
885         if (idx == XKB_MOD_INVALID)
886             break;
887         if (idx >= num_mods) {
888             ret = -1;
889             break;
890         }
891         wanted |= (1 << idx);
892     }
893     va_end(ap);
894
895     if (ret == -1)
896         return ret;
897
898     return match_mod_masks(state, type, match, wanted);
899 }
900
901 /**
902  * Returns 1 if the given modifier is active with the specified type(s), 0 if
903  * not, or -1 if the modifier is invalid.
904  */
905 XKB_EXPORT int
906 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
907                              enum xkb_state_component type)
908 {
909     xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
910
911     if (idx == XKB_MOD_INVALID)
912         return -1;
913
914     return xkb_state_mod_index_is_active(state, idx, type);
915 }
916
917 /**
918  * Returns 1 if the modifiers are active with the specified type(s), 0 if
919  * not, or -1 if any of the modifiers are invalid.
920  */
921 XKB_EXPORT ATTR_NULL_SENTINEL int
922 xkb_state_mod_names_are_active(struct xkb_state *state,
923                                enum xkb_state_component type,
924                                enum xkb_state_match match,
925                                ...)
926 {
927     va_list ap;
928     xkb_mod_index_t idx = 0;
929     const char *str;
930     xkb_mod_mask_t wanted = 0;
931     int ret = 0;
932
933     va_start(ap, match);
934     while (1) {
935         str = va_arg(ap, const char *);
936         if (str == NULL)
937             break;
938         idx = xkb_keymap_mod_get_index(state->keymap, str);
939         if (idx == XKB_MOD_INVALID) {
940             ret = -1;
941             break;
942         }
943         wanted |= (1 << idx);
944     }
945     va_end(ap);
946
947     if (ret == -1)
948         return ret;
949
950     return match_mod_masks(state, type, match, wanted);
951 }
952
953 /**
954  * Returns 1 if the given group is active with the specified type(s), 0 if
955  * not, or -1 if the group is invalid.
956  */
957 XKB_EXPORT int
958 xkb_state_layout_index_is_active(struct xkb_state *state,
959                                 xkb_layout_index_t idx,
960                                 enum xkb_state_component type)
961 {
962     int ret = 0;
963
964     if (idx >= xkb_keymap_num_layouts(state->keymap))
965         return -1;
966
967     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
968         ret |= (state->group == idx);
969     if (type & XKB_STATE_LAYOUT_DEPRESSED)
970         ret |= (state->base_group == idx);
971     if (type & XKB_STATE_LAYOUT_LATCHED)
972         ret |= (state->latched_group == idx);
973     if (type & XKB_STATE_LAYOUT_LOCKED)
974         ret |= (state->locked_group == idx);
975
976     return ret;
977 }
978
979 /**
980  * Returns 1 if the given modifier is active with the specified type(s), 0 if
981  * not, or -1 if the modifier is invalid.
982  */
983 XKB_EXPORT int
984 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
985                                 enum xkb_state_component type)
986 {
987     xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
988
989     if (idx == XKB_LAYOUT_INVALID)
990         return -1;
991
992     return xkb_state_layout_index_is_active(state, idx, type);
993 }
994
995 /**
996  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
997  */
998 XKB_EXPORT int
999 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1000 {
1001     if (idx >= darray_size(state->keymap->indicators) ||
1002         darray_item(state->keymap->indicators, idx).name == XKB_ATOM_NONE)
1003         return -1;
1004
1005     return !!(state->leds & (1 << idx));
1006 }
1007
1008 /**
1009  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1010  */
1011 XKB_EXPORT int
1012 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1013 {
1014     xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1015
1016     if (idx == XKB_LED_INVALID)
1017         return -1;
1018
1019     return xkb_state_led_index_is_active(state, idx);
1020 }
1021
1022 static xkb_mod_mask_t
1023 key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
1024 {
1025     const struct xkb_kt_map_entry *entry;
1026     xkb_layout_index_t group;
1027
1028     group = xkb_state_key_get_layout(state, key->keycode);
1029     if (group == XKB_LAYOUT_INVALID)
1030         return 0;
1031
1032     entry = get_entry_for_key_state(state, key, group);
1033     if (!entry)
1034         return 0;
1035
1036     return entry->mods.mask & ~entry->preserve.mask;
1037 }
1038
1039 /**
1040  * Tests to see if a modifier is used up by our translation of a
1041  * keycode to keysyms, taking note of the current modifier state and
1042  * the appropriate key type's preserve information, if any. This allows
1043  * the user to mask out the modifier in later processing of the
1044  * modifiers, e.g. when implementing hot keys or accelerators.
1045  *
1046  * See also, for example:
1047  * - XkbTranslateKeyCode(3), mod_rtrn retrun value, from libX11.
1048  * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
1049  *   from gtk+.
1050  */
1051 XKB_EXPORT int
1052 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1053                                 xkb_mod_index_t idx)
1054 {
1055     const struct xkb_key *key = XkbKey(state->keymap, kc);
1056
1057     if (!key || idx >= xkb_keymap_num_mods(state->keymap))
1058         return -1;
1059
1060     return !!((1 << idx) & key_get_consumed(state, key));
1061 }
1062
1063 /**
1064  * Calculates which modifiers should be consumed during key processing,
1065  * and returns the mask with all these modifiers removed.  e.g. if
1066  * given a state of Alt and Shift active for a two-level alphabetic
1067  * key containing plus and equal on the first and second level
1068  * respectively, will return a mask of only Alt, as Shift has been
1069  * consumed by the type handling.
1070  */
1071 XKB_EXPORT xkb_mod_mask_t
1072 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1073                                    xkb_mod_mask_t mask)
1074 {
1075     const struct xkb_key *key = XkbKey(state->keymap, kc);
1076
1077     if (!key)
1078         return 0;
1079
1080     return mask & ~key_get_consumed(state, key);
1081 }