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