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