keymap: wrap the layout parameter if it is out of range for the key
[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 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 || --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     state->cur.mods = (state->cur.base_mods |
650                        state->cur.latched_mods |
651                        state->cur.locked_mods);
652
653     /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
654
655     state->cur.locked_group = wrap_group_into_range(state->cur.locked_group,
656                                                     state->keymap->num_groups,
657                                                     RANGE_WRAP, 0);
658
659     state->cur.group = wrap_group_into_range(state->cur.base_group +
660                                              state->cur.latched_group +
661                                              state->cur.locked_group,
662                                              state->keymap->num_groups,
663                                              RANGE_WRAP, 0);
664
665     xkb_state_led_update_all(state);
666 }
667
668 static enum xkb_state_component
669 get_state_component_changes(const struct state_components *a,
670                             const struct state_components *b)
671 {
672     xkb_mod_mask_t mask = 0;
673
674     if (a->group != b->group)
675         mask |= XKB_STATE_LAYOUT_EFFECTIVE;
676     if (a->base_group != b->base_group)
677         mask |= XKB_STATE_LAYOUT_DEPRESSED;
678     if (a->latched_group != b->latched_group)
679         mask |= XKB_STATE_LAYOUT_LATCHED;
680     if (a->locked_group != b->locked_group)
681         mask |= XKB_STATE_LAYOUT_LOCKED;
682     if (a->mods != b->mods)
683         mask |= XKB_STATE_MODS_EFFECTIVE;
684     if (a->base_mods != b->base_mods)
685         mask |= XKB_STATE_MODS_DEPRESSED;
686     if (a->latched_mods != b->latched_mods)
687         mask |= XKB_STATE_MODS_LATCHED;
688     if (a->locked_mods != b->locked_mods)
689         mask |= XKB_STATE_MODS_LOCKED;
690     if (a->leds != b->leds)
691         mask |= XKB_STATE_LEDS;
692
693     return mask;
694 }
695
696 /**
697  * Given a particular key event, updates the state structure to reflect the
698  * new modifiers.
699  */
700 XKB_EXPORT enum xkb_state_component
701 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
702                      enum xkb_key_direction direction)
703 {
704     xkb_mod_index_t i;
705     xkb_mod_mask_t bit;
706     const struct xkb_key *key = XkbKey(state->keymap, kc);
707
708     if (!key)
709         return 0;
710
711     state->prev = state->cur;
712
713     state->set_mods = 0;
714     state->clear_mods = 0;
715
716     xkb_filter_apply_all(state, key, direction);
717
718     for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
719         if (state->set_mods & bit) {
720             state->mod_key_count[i]++;
721             state->cur.base_mods |= bit;
722             state->set_mods &= ~bit;
723         }
724     }
725
726     for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
727         if (state->clear_mods & bit) {
728             state->mod_key_count[i]--;
729             if (state->mod_key_count[i] <= 0) {
730                 state->cur.base_mods &= ~bit;
731                 state->mod_key_count[i] = 0;
732             }
733             state->clear_mods &= ~bit;
734         }
735     }
736
737     xkb_state_update_derived(state);
738
739     return get_state_component_changes(&state->prev, &state->cur);
740 }
741
742 /**
743  * Updates the state from a set of explicit masks as gained from
744  * xkb_state_serialize_mods and xkb_state_serialize_groups.  As noted in the
745  * documentation for these functions in xkbcommon.h, this round-trip is
746  * lossy, and should only be used to update a slave state mirroring the
747  * master, e.g. in a client/server window system.
748  */
749 XKB_EXPORT enum xkb_state_component
750 xkb_state_update_mask(struct xkb_state *state,
751                       xkb_mod_mask_t base_mods,
752                       xkb_mod_mask_t latched_mods,
753                       xkb_mod_mask_t locked_mods,
754                       xkb_layout_index_t base_group,
755                       xkb_layout_index_t latched_group,
756                       xkb_layout_index_t locked_group)
757 {
758     xkb_mod_index_t num_mods;
759     xkb_mod_index_t idx;
760
761     state->prev = state->cur;
762
763     state->cur.base_mods = 0;
764     state->cur.latched_mods = 0;
765     state->cur.locked_mods = 0;
766     num_mods = xkb_keymap_num_mods(state->keymap);
767
768     for (idx = 0; idx < num_mods; idx++) {
769         xkb_mod_mask_t mod = (1 << idx);
770         if (base_mods & mod)
771             state->cur.base_mods |= mod;
772         if (latched_mods & mod)
773             state->cur.latched_mods |= mod;
774         if (locked_mods & mod)
775             state->cur.locked_mods |= mod;
776     }
777
778     state->cur.base_group = base_group;
779     state->cur.latched_group = latched_group;
780     state->cur.locked_group = locked_group;
781
782     xkb_state_update_derived(state);
783
784     return get_state_component_changes(&state->prev, &state->cur);
785 }
786
787 /**
788  * Provides the symbols to use for the given key and state.  Returns the
789  * number of symbols pointed to in syms_out.
790  */
791 XKB_EXPORT int
792 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
793                        const xkb_keysym_t **syms_out)
794 {
795     xkb_layout_index_t layout;
796     xkb_level_index_t level;
797
798     layout = xkb_state_key_get_layout(state, kc);
799     if (layout == XKB_LAYOUT_INVALID)
800         goto err;
801
802     level = xkb_state_key_get_level(state, kc, layout);
803     if (level == XKB_LEVEL_INVALID)
804         goto err;
805
806     return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
807                                             syms_out);
808
809 err:
810     *syms_out = NULL;
811     return 0;
812 }
813
814 /**
815  * Provides either exactly one symbol, or XKB_KEY_NoSymbol.
816  */
817 XKB_EXPORT xkb_keysym_t
818 xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
819 {
820     const xkb_keysym_t *syms;
821     int num_syms;
822
823     num_syms = xkb_state_key_get_syms(state, kc, &syms);
824     if (num_syms != 1)
825         return XKB_KEY_NoSymbol;
826
827     return syms[0];
828 }
829
830 /**
831  * Serialises the requested modifier state into an xkb_mod_mask_t, with all
832  * the same disclaimers as in xkb_state_update_mask.
833  */
834 XKB_EXPORT xkb_mod_mask_t
835 xkb_state_serialize_mods(struct xkb_state *state,
836                          enum xkb_state_component type)
837 {
838     xkb_mod_mask_t ret = 0;
839
840     if (type & XKB_STATE_MODS_EFFECTIVE)
841         return state->cur.mods;
842
843     if (type & XKB_STATE_MODS_DEPRESSED)
844         ret |= state->cur.base_mods;
845     if (type & XKB_STATE_MODS_LATCHED)
846         ret |= state->cur.latched_mods;
847     if (type & XKB_STATE_MODS_LOCKED)
848         ret |= state->cur.locked_mods;
849
850     return ret;
851 }
852
853 /**
854  * Serialises the requested group state, with all the same disclaimers as
855  * in xkb_state_update_mask.
856  */
857 XKB_EXPORT xkb_layout_index_t
858 xkb_state_serialize_layout(struct xkb_state *state,
859                            enum xkb_state_component type)
860 {
861     xkb_layout_index_t ret = 0;
862
863     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
864         return state->cur.group;
865
866     if (type & XKB_STATE_LAYOUT_DEPRESSED)
867         ret += state->cur.base_group;
868     if (type & XKB_STATE_LAYOUT_LATCHED)
869         ret += state->cur.latched_group;
870     if (type & XKB_STATE_LAYOUT_LOCKED)
871         ret += state->cur.locked_group;
872
873     return ret;
874 }
875
876 /**
877  * Returns 1 if the given modifier is active with the specified type(s), 0 if
878  * not, or -1 if the modifier is invalid.
879  */
880 XKB_EXPORT int
881 xkb_state_mod_index_is_active(struct xkb_state *state,
882                               xkb_mod_index_t idx,
883                               enum xkb_state_component type)
884 {
885     if (idx >= xkb_keymap_num_mods(state->keymap))
886         return -1;
887
888     return !!(xkb_state_serialize_mods(state, type) & (1 << idx));
889 }
890
891 /**
892  * Helper function for xkb_state_mod_indices_are_active and
893  * xkb_state_mod_names_are_active.
894  */
895 static int
896 match_mod_masks(struct xkb_state *state,
897                 enum xkb_state_component type,
898                 enum xkb_state_match match,
899                 xkb_mod_mask_t wanted)
900 {
901     xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
902
903     if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
904         return 0;
905
906     if (match & XKB_STATE_MATCH_ANY)
907         return !!(active & wanted);
908     else
909         return (active & wanted) == wanted;
910
911     return 0;
912 }
913
914 /**
915  * Returns 1 if the modifiers are active with the specified type(s), 0 if
916  * not, or -1 if any of the modifiers are invalid.
917  */
918 XKB_EXPORT int
919 xkb_state_mod_indices_are_active(struct xkb_state *state,
920                                  enum xkb_state_component type,
921                                  enum xkb_state_match match,
922                                  ...)
923 {
924     va_list ap;
925     xkb_mod_index_t idx = 0;
926     xkb_mod_mask_t wanted = 0;
927     int ret = 0;
928     xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
929
930     va_start(ap, match);
931     while (1) {
932         idx = va_arg(ap, xkb_mod_index_t);
933         if (idx == XKB_MOD_INVALID)
934             break;
935         if (idx >= num_mods) {
936             ret = -1;
937             break;
938         }
939         wanted |= (1 << idx);
940     }
941     va_end(ap);
942
943     if (ret == -1)
944         return ret;
945
946     return match_mod_masks(state, type, match, wanted);
947 }
948
949 /**
950  * Returns 1 if the given modifier is active with the specified type(s), 0 if
951  * not, or -1 if the modifier is invalid.
952  */
953 XKB_EXPORT int
954 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
955                              enum xkb_state_component type)
956 {
957     xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
958
959     if (idx == XKB_MOD_INVALID)
960         return -1;
961
962     return xkb_state_mod_index_is_active(state, idx, type);
963 }
964
965 /**
966  * Returns 1 if the modifiers are active with the specified type(s), 0 if
967  * not, or -1 if any of the modifiers are invalid.
968  */
969 XKB_EXPORT ATTR_NULL_SENTINEL int
970 xkb_state_mod_names_are_active(struct xkb_state *state,
971                                enum xkb_state_component type,
972                                enum xkb_state_match match,
973                                ...)
974 {
975     va_list ap;
976     xkb_mod_index_t idx = 0;
977     const char *str;
978     xkb_mod_mask_t wanted = 0;
979     int ret = 0;
980
981     va_start(ap, match);
982     while (1) {
983         str = va_arg(ap, const char *);
984         if (str == NULL)
985             break;
986         idx = xkb_keymap_mod_get_index(state->keymap, str);
987         if (idx == XKB_MOD_INVALID) {
988             ret = -1;
989             break;
990         }
991         wanted |= (1 << idx);
992     }
993     va_end(ap);
994
995     if (ret == -1)
996         return ret;
997
998     return match_mod_masks(state, type, match, wanted);
999 }
1000
1001 /**
1002  * Returns 1 if the given group is active with the specified type(s), 0 if
1003  * not, or -1 if the group is invalid.
1004  */
1005 XKB_EXPORT int
1006 xkb_state_layout_index_is_active(struct xkb_state *state,
1007                                 xkb_layout_index_t idx,
1008                                 enum xkb_state_component type)
1009 {
1010     int ret = 0;
1011
1012     if (idx >= state->keymap->num_groups)
1013         return -1;
1014
1015     if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1016         ret |= (state->cur.group == idx);
1017     if (type & XKB_STATE_LAYOUT_DEPRESSED)
1018         ret |= (state->cur.base_group == idx);
1019     if (type & XKB_STATE_LAYOUT_LATCHED)
1020         ret |= (state->cur.latched_group == idx);
1021     if (type & XKB_STATE_LAYOUT_LOCKED)
1022         ret |= (state->cur.locked_group == idx);
1023
1024     return ret;
1025 }
1026
1027 /**
1028  * Returns 1 if the given modifier is active with the specified type(s), 0 if
1029  * not, or -1 if the modifier is invalid.
1030  */
1031 XKB_EXPORT int
1032 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
1033                                 enum xkb_state_component type)
1034 {
1035     xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
1036
1037     if (idx == XKB_LAYOUT_INVALID)
1038         return -1;
1039
1040     return xkb_state_layout_index_is_active(state, idx, type);
1041 }
1042
1043 /**
1044  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1045  */
1046 XKB_EXPORT int
1047 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1048 {
1049     if (idx >= darray_size(state->keymap->indicators) ||
1050         darray_item(state->keymap->indicators, idx).name == XKB_ATOM_NONE)
1051         return -1;
1052
1053     return !!(state->cur.leds & (1 << idx));
1054 }
1055
1056 /**
1057  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1058  */
1059 XKB_EXPORT int
1060 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1061 {
1062     xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1063
1064     if (idx == XKB_LED_INVALID)
1065         return -1;
1066
1067     return xkb_state_led_index_is_active(state, idx);
1068 }
1069
1070 static xkb_mod_mask_t
1071 key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
1072 {
1073     const struct xkb_kt_map_entry *entry;
1074     xkb_layout_index_t group;
1075
1076     group = xkb_state_key_get_layout(state, key->keycode);
1077     if (group == XKB_LAYOUT_INVALID)
1078         return 0;
1079
1080     entry = get_entry_for_key_state(state, key, group);
1081     if (!entry)
1082         return 0;
1083
1084     return entry->mods.mask & ~entry->preserve.mask;
1085 }
1086
1087 /**
1088  * Tests to see if a modifier is used up by our translation of a
1089  * keycode to keysyms, taking note of the current modifier state and
1090  * the appropriate key type's preserve information, if any. This allows
1091  * the user to mask out the modifier in later processing of the
1092  * modifiers, e.g. when implementing hot keys or accelerators.
1093  *
1094  * See also, for example:
1095  * - XkbTranslateKeyCode(3), mod_rtrn retrun value, from libX11.
1096  * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
1097  *   from gtk+.
1098  */
1099 XKB_EXPORT int
1100 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1101                                 xkb_mod_index_t idx)
1102 {
1103     const struct xkb_key *key = XkbKey(state->keymap, kc);
1104
1105     if (!key || idx >= xkb_keymap_num_mods(state->keymap))
1106         return -1;
1107
1108     return !!((1 << idx) & key_get_consumed(state, key));
1109 }
1110
1111 /**
1112  * Calculates which modifiers should be consumed during key processing,
1113  * and returns the mask with all these modifiers removed.  e.g. if
1114  * given a state of Alt and Shift active for a two-level alphabetic
1115  * key containing plus and equal on the first and second level
1116  * respectively, will return a mask of only Alt, as Shift has been
1117  * consumed by the type handling.
1118  */
1119 XKB_EXPORT xkb_mod_mask_t
1120 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1121                                    xkb_mod_mask_t mask)
1122 {
1123     const struct xkb_key *key = XkbKey(state->keymap, kc);
1124
1125     if (!key)
1126         return 0;
1127
1128     return mask & ~key_get_consumed(state, key);
1129 }