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