state: missing XKB_EXPORT on xkb_state_key_get_level
[platform/upstream/libxkbcommon.git] / src / state.c
1 /************************************************************
2  * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3  *
4  * Permission to use, copy, modify, and distribute this
5  * software and its documentation for any purpose and without
6  * fee is hereby granted, provided that the above copyright
7  * notice appear in all copies and that both that copyright
8  * notice and this permission notice appear in supporting
9  * documentation, and that the name of Silicon Graphics not be
10  * used in advertising or publicity pertaining to distribution
11  * of the software without specific prior written permission.
12  * Silicon Graphics makes no representation about the suitability
13  * of this software for any purpose. It is provided "as is"
14  * without any express or implied warranty.
15  *
16  * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  * THE USE OR PERFORMANCE OF THIS SOFTWARE.
24  *
25  ********************************************************/
26
27 /*
28  * Copyright © 2012 Intel Corporation
29  * Copyright © 2012 Ran Benita <ran234@gmail.com>
30  *
31  * Permission is hereby granted, free of charge, to any person obtaining a
32  * copy of this software and associated documentation files (the "Software"),
33  * to deal in the Software without restriction, including without limitation
34  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35  * and/or sell copies of the Software, and to permit persons to whom the
36  * Software is furnished to do so, subject to the following conditions:
37  *
38  * The above copyright notice and this permission notice (including the next
39  * paragraph) shall be included in all copies or substantial portions of the
40  * Software.
41  *
42  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
45  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
48  * DEALINGS IN THE SOFTWARE.
49  *
50  * Author: Daniel Stone <daniel@fooishbar.org>
51  */
52
53 /*
54  * This is a bastardised version of xkbActions.c from the X server which
55  * does not support, for the moment:
56  *   - AccessX sticky/debounce/etc (will come later)
57  *   - pointer keys (may come later)
58  *   - key redirects (unlikely)
59  *   - messages (very unlikely)
60  */
61
62 #include "keymap.h"
63
64 struct xkb_filter {
65     union xkb_action action;
66     const struct xkb_key *key;
67     uint32_t priv;
68     int (*func)(struct xkb_state *state,
69                 struct xkb_filter *filter,
70                 const struct xkb_key *key,
71                 enum xkb_key_direction direction);
72     int refcnt;
73 };
74
75 struct xkb_state {
76     /* These may be negative, because of -1 group actions. */
77     int32_t base_group; /**< depressed */
78     int32_t latched_group;
79     int32_t locked_group;
80     xkb_layout_index_t group; /**< effective */
81
82     xkb_mod_mask_t base_mods; /**< depressed */
83     xkb_mod_mask_t latched_mods;
84     xkb_mod_mask_t locked_mods;
85     xkb_mod_mask_t mods; /**< effective */
86
87     /*
88      * At each event, we accumulate all the needed modifications to the base
89      * modifiers, and apply them at the end. These keep track of this state.
90      */
91     xkb_mod_mask_t set_mods;
92     xkb_mod_mask_t clear_mods;
93     /*
94      * We mustn't clear a base modifier if there's another depressed key
95      * which affects it, e.g. given this sequence
96      * < Left Shift down, Right Shift down, Left Shift Up >
97      * the modifier should still be set. This keeps the count.
98      */
99     int16_t mod_key_count[sizeof(xkb_mod_mask_t) * 8];
100
101     uint32_t leds;
102
103     int refcnt;
104     darray(struct xkb_filter) filters;
105     struct xkb_keymap *keymap;
106 };
107
108 static struct xkb_kt_map_entry *
109 get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
110                         xkb_layout_index_t group)
111 {
112     struct xkb_key_type *type;
113     xkb_mod_mask_t active_mods;
114     unsigned int i;
115
116     type = XkbKeyType(state->keymap, key, group);
117     active_mods = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE);
118     active_mods &= type->mods.mask;
119
120     for (i = 0; i < type->num_entries; i++)
121         if (type->map[i].mods.mask == active_mods)
122             return &type->map[i];
123
124     return NULL;
125 }
126
127 /**
128  * Returns the level to use for the given key and state, or
129  * XKB_LEVEL_INVALID.
130  */
131 XKB_EXPORT xkb_level_index_t
132 xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
133                         xkb_layout_index_t layout)
134 {
135     const struct xkb_key *key = XkbKey(state->keymap, kc);
136     struct xkb_kt_map_entry *entry;
137
138     if (!key || layout >= key->num_groups)
139         return XKB_LEVEL_INVALID;
140
141     /* If we don't find an explicit match the default is 0. */
142     entry = get_entry_for_key_state(state, key, layout);
143     if (!entry)
144         return 0;
145
146     return entry->level;
147 }
148
149 static xkb_layout_index_t
150 wrap_group_into_range(int32_t group,
151                       xkb_layout_index_t num_groups,
152                       enum xkb_range_exceed_type out_of_range_group_action,
153                       xkb_layout_index_t out_of_range_group_number)
154 {
155     if (num_groups == 0)
156         return XKB_LAYOUT_INVALID;
157
158     if (group < num_groups)
159         return group;
160
161     switch (out_of_range_group_action) {
162     case RANGE_REDIRECT:
163         if (out_of_range_group_number >= num_groups)
164             return 0;
165         return out_of_range_group_number;
166
167     case RANGE_SATURATE:
168         if (group < 0)
169             return 0;
170         else
171             return num_groups - 1;
172
173     case RANGE_WRAP:
174     default:
175         /*
176          * C99 says a negative dividend in a modulo operation always
177          * gives a negative result.
178          */
179         if (group < 0)
180             return ((int) num_groups + (group % (int) num_groups));
181         else
182             return group % num_groups;
183     }
184 }
185
186 /**
187  * Returns the layout to use for the given key and state, taking
188  * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
189  */
190 XKB_EXPORT xkb_layout_index_t
191 xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
192 {
193     xkb_layout_index_t group =
194         xkb_state_serialize_layout(state, XKB_STATE_EFFECTIVE);
195     const struct xkb_key *key = XkbKey(state->keymap, kc);
196
197     if (!key)
198         return XKB_LAYOUT_INVALID;
199
200     return wrap_group_into_range(group, key->num_groups,
201                                  key->out_of_range_group_action,
202                                  key->out_of_range_group_number);
203 }
204
205 static const union xkb_action fake = { .type = ACTION_TYPE_NONE };
206
207 static const union xkb_action *
208 xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
209 {
210     xkb_layout_index_t layout;
211     xkb_level_index_t level;
212
213     if (!key->actions)
214         return &fake;
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 XkbKeyActionEntry(key, layout, level);
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->base_group = filter->priv;
270
271     if (filter->action.group.flags & ACTION_LOCK_CLEAR)
272         state->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->base_group;
282     if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
283         state->base_group = filter->action.group.group;
284     else
285         state->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->locked_group = filter->action.group.group;
313     else
314         state->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->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->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->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->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->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->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->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->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->latched_mods &= ~filter->action.mods.mods.mask;
462             else
463                 state->clear_mods = filter->action.mods.mods.mask;
464             state->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->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     if (!filter_action_funcs[action->type].new)
538         return;
539
540     filter = xkb_filter_new(state);
541     if (!filter)
542         return; /* WSGO */
543
544     filter->key = key;
545     filter->func = filter_action_funcs[action->type].func;
546     filter->action = *action;
547     filter_action_funcs[action->type].new(state, filter);
548 }
549
550 XKB_EXPORT struct xkb_state *
551 xkb_state_new(struct xkb_keymap *keymap)
552 {
553     struct xkb_state *ret;
554
555     ret = calloc(sizeof(*ret), 1);
556     if (!ret)
557         return NULL;
558
559     ret->refcnt = 1;
560     ret->keymap = xkb_keymap_ref(keymap);
561
562     return ret;
563 }
564
565 XKB_EXPORT struct xkb_state *
566 xkb_state_ref(struct xkb_state *state)
567 {
568     state->refcnt++;
569     return state;
570 }
571
572 XKB_EXPORT void
573 xkb_state_unref(struct xkb_state *state)
574 {
575     if (--state->refcnt > 0)
576         return;
577
578     xkb_keymap_unref(state->keymap);
579     darray_free(state->filters);
580     free(state);
581 }
582
583 XKB_EXPORT struct xkb_keymap *
584 xkb_state_get_keymap(struct xkb_state *state)
585 {
586     return state->keymap;
587 }
588
589 /**
590  * Update the LED state to match the rest of the xkb_state.
591  */
592 static void
593 xkb_state_led_update_all(struct xkb_state *state)
594 {
595     xkb_led_index_t led;
596
597     state->leds = 0;
598
599     for (led = 0; led < XKB_NUM_INDICATORS; led++) {
600         struct xkb_indicator_map *map = &state->keymap->indicators[led];
601         xkb_mod_mask_t mod_mask = 0;
602         uint32_t group_mask = 0;
603
604         if (map->which_mods & XKB_STATE_DEPRESSED)
605             mod_mask |= state->base_mods;
606         if (map->which_mods & XKB_STATE_LATCHED)
607             mod_mask |= state->latched_mods;
608         if (map->which_mods & XKB_STATE_LOCKED)
609             mod_mask |= state->locked_mods;
610         if ((map->mods.mask & mod_mask))
611             state->leds |= (1 << led);
612
613         if (map->which_groups & XKB_STATE_DEPRESSED)
614             group_mask |= (1 << state->base_group);
615         if (map->which_groups & XKB_STATE_LATCHED)
616             group_mask |= (1 << state->latched_group);
617         if (map->which_groups & XKB_STATE_LOCKED)
618             group_mask |= (1 << state->locked_group);
619         if ((map->groups & group_mask))
620             state->leds |= (1 << led);
621
622         if (map->ctrls) {
623             if ((map->ctrls & state->keymap->enabled_ctrls))
624                 state->leds |= (1 << led);
625         }
626     }
627 }
628
629 /**
630  * Calculates the derived state (effective mods/group and LEDs) from an
631  * up-to-date xkb_state.
632  */
633 static void
634 xkb_state_update_derived(struct xkb_state *state)
635 {
636     xkb_layout_index_t num_groups = xkb_keymap_num_layouts(state->keymap);
637
638     state->mods = (state->base_mods |
639                    state->latched_mods |
640                    state->locked_mods);
641
642     /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
643
644     state->locked_group = wrap_group_into_range(state->locked_group,
645                                                 num_groups,
646                                                 RANGE_WRAP, 0);
647
648     state->group = wrap_group_into_range(state->base_group +
649                                          state->latched_group +
650                                          state->locked_group,
651                                          num_groups,
652                                          RANGE_WRAP, 0);
653
654     xkb_state_led_update_all(state);
655 }
656
657 /**
658  * Given a particular key event, updates the state structure to reflect the
659  * new modifiers.
660  */
661 XKB_EXPORT void
662 xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
663                      enum xkb_key_direction direction)
664 {
665     xkb_mod_index_t i;
666     xkb_mod_mask_t bit;
667     const struct xkb_key *key = XkbKey(state->keymap, kc);
668
669     if (!key)
670         return;
671
672     state->set_mods = 0;
673     state->clear_mods = 0;
674
675     xkb_filter_apply_all(state, key, direction);
676
677     for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
678         if (state->set_mods & bit) {
679             state->mod_key_count[i]++;
680             state->base_mods |= bit;
681             state->set_mods &= ~bit;
682         }
683     }
684
685     for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
686         if (state->clear_mods & bit) {
687             state->mod_key_count[i]--;
688             if (state->mod_key_count[i] <= 0) {
689                 state->base_mods &= ~bit;
690                 state->mod_key_count[i] = 0;
691             }
692             state->clear_mods &= ~bit;
693         }
694     }
695
696     xkb_state_update_derived(state);
697 }
698
699 /**
700  * Updates the state from a set of explicit masks as gained from
701  * xkb_state_serialize_mods and xkb_state_serialize_groups.  As noted in the
702  * documentation for these functions in xkbcommon.h, this round-trip is
703  * lossy, and should only be used to update a slave state mirroring the
704  * master, e.g. in a client/server window system.
705  */
706 XKB_EXPORT void
707 xkb_state_update_mask(struct xkb_state *state,
708                       xkb_mod_mask_t base_mods,
709                       xkb_mod_mask_t latched_mods,
710                       xkb_mod_mask_t locked_mods,
711                       xkb_layout_index_t base_group,
712                       xkb_layout_index_t latched_group,
713                       xkb_layout_index_t locked_group)
714 {
715     xkb_mod_index_t num_mods;
716     xkb_mod_index_t idx;
717
718     state->base_mods = 0;
719     state->latched_mods = 0;
720     state->locked_mods = 0;
721     num_mods = xkb_keymap_num_mods(state->keymap);
722
723     for (idx = 0; idx < num_mods; idx++) {
724         xkb_mod_mask_t mod = (1 << idx);
725         if (base_mods & mod)
726             state->base_mods |= mod;
727         if (latched_mods & mod)
728             state->latched_mods |= mod;
729         if (locked_mods & mod)
730             state->locked_mods |= mod;
731     }
732
733     state->base_group = base_group;
734     state->latched_group = latched_group;
735     state->locked_group = locked_group;
736
737     xkb_state_update_derived(state);
738 }
739
740 /**
741  * Provides the symbols to use for the given key and state.  Returns the
742  * number of symbols pointed to in syms_out.
743  */
744 XKB_EXPORT int
745 xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
746                        const xkb_keysym_t **syms_out)
747 {
748     xkb_layout_index_t layout;
749     xkb_level_index_t level;
750     const struct xkb_key *key = XkbKey(state->keymap, kc);
751
752     if (!key)
753         return -1;
754
755     layout = xkb_state_key_get_layout(state, kc);
756     if (layout == XKB_LAYOUT_INVALID)
757         goto err;
758
759     level = xkb_state_key_get_level(state, kc, layout);
760     if (level == XKB_LEVEL_INVALID)
761         goto err;
762
763     return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
764                                             syms_out);
765
766 err:
767     *syms_out = NULL;
768     return 0;
769 }
770
771 /**
772  * Serialises the requested modifier state into an xkb_mod_mask_t, with all
773  * the same disclaimers as in xkb_state_update_mask.
774  */
775 XKB_EXPORT xkb_mod_mask_t
776 xkb_state_serialize_mods(struct xkb_state *state,
777                          enum xkb_state_component type)
778 {
779     xkb_mod_mask_t ret = 0;
780
781     if (type == XKB_STATE_EFFECTIVE)
782         return state->mods;
783
784     if (type & XKB_STATE_DEPRESSED)
785         ret |= state->base_mods;
786     if (type & XKB_STATE_LATCHED)
787         ret |= state->latched_mods;
788     if (type & XKB_STATE_LOCKED)
789         ret |= state->locked_mods;
790
791     return ret;
792 }
793
794 /**
795  * Serialises the requested group state, with all the same disclaimers as
796  * in xkb_state_update_mask.
797  */
798 XKB_EXPORT xkb_layout_index_t
799 xkb_state_serialize_layout(struct xkb_state *state,
800                            enum xkb_state_component type)
801 {
802     xkb_layout_index_t ret = 0;
803
804     if (type == XKB_STATE_EFFECTIVE)
805         return state->group;
806
807     if (type & XKB_STATE_DEPRESSED)
808         ret += state->base_group;
809     if (type & XKB_STATE_LATCHED)
810         ret += state->latched_group;
811     if (type & XKB_STATE_LOCKED)
812         ret += state->locked_group;
813
814     return ret;
815 }
816
817 /**
818  * Returns 1 if the given modifier is active with the specified type(s), 0 if
819  * not, or -1 if the modifier is invalid.
820  */
821 XKB_EXPORT int
822 xkb_state_mod_index_is_active(struct xkb_state *state,
823                               xkb_mod_index_t idx,
824                               enum xkb_state_component type)
825 {
826     int ret = 0;
827
828     if (idx >= xkb_keymap_num_mods(state->keymap))
829         return -1;
830
831     if (type & XKB_STATE_EFFECTIVE)
832         return !!(state->mods & (1 << idx));
833
834     if (type & XKB_STATE_DEPRESSED)
835         ret |= (state->base_mods & (1 << idx));
836     if (type & XKB_STATE_LATCHED)
837         ret |= (state->latched_mods & (1 << idx));
838     if (type & XKB_STATE_LOCKED)
839         ret |= (state->locked_mods & (1 << idx));
840
841     return !!ret;
842 }
843
844 /**
845  * Helper function for xkb_state_mod_indices_are_active and
846  * xkb_state_mod_names_are_active.
847  */
848 static int
849 match_mod_masks(struct xkb_state *state, enum xkb_state_match match,
850                 uint32_t wanted)
851 {
852     uint32_t active = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE);
853
854     if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
855         return 0;
856
857     if (match & XKB_STATE_MATCH_ANY)
858         return !!(active & wanted);
859     else
860         return (active & wanted) == wanted;
861
862     return 0;
863 }
864
865 /**
866  * Returns 1 if the modifiers are active with the specified type(s), 0 if
867  * not, or -1 if any of the modifiers are invalid.
868  */
869 XKB_EXPORT int
870 xkb_state_mod_indices_are_active(struct xkb_state *state,
871                                  enum xkb_state_component type,
872                                  enum xkb_state_match match,
873                                  ...)
874 {
875     va_list ap;
876     xkb_mod_index_t idx = 0;
877     uint32_t wanted = 0;
878     int ret = 0;
879     xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
880
881     va_start(ap, match);
882     while (1) {
883         idx = va_arg(ap, xkb_mod_index_t);
884         if (idx == XKB_MOD_INVALID)
885             break;
886         if (idx >= num_mods) {
887             ret = -1;
888             break;
889         }
890         wanted |= (1 << idx);
891     }
892     va_end(ap);
893
894     if (ret == -1)
895         return ret;
896
897     return match_mod_masks(state, match, wanted);
898 }
899
900 /**
901  * Returns 1 if the given modifier is active with the specified type(s), 0 if
902  * not, or -1 if the modifier is invalid.
903  */
904 XKB_EXPORT int
905 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
906                              enum xkb_state_component type)
907 {
908     xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
909
910     if (idx == XKB_MOD_INVALID)
911         return -1;
912
913     return xkb_state_mod_index_is_active(state, idx, type);
914 }
915
916 /**
917  * Returns 1 if the modifiers are active with the specified type(s), 0 if
918  * not, or -1 if any of the modifiers are invalid.
919  */
920 XKB_EXPORT ATTR_NULL_SENTINEL int
921 xkb_state_mod_names_are_active(struct xkb_state *state,
922                                enum xkb_state_component type,
923                                enum xkb_state_match match,
924                                ...)
925 {
926     va_list ap;
927     xkb_mod_index_t idx = 0;
928     const char *str;
929     uint32_t wanted = 0;
930     int ret = 0;
931
932     va_start(ap, match);
933     while (1) {
934         str = va_arg(ap, const char *);
935         if (str == NULL)
936             break;
937         idx = xkb_keymap_mod_get_index(state->keymap, str);
938         if (idx == XKB_MOD_INVALID) {
939             ret = -1;
940             break;
941         }
942         wanted |= (1 << idx);
943     }
944     va_end(ap);
945
946     if (ret == -1)
947         return ret;
948
949     return match_mod_masks(state, match, wanted);
950 }
951
952 /**
953  * Returns 1 if the given group is active with the specified type(s), 0 if
954  * not, or -1 if the group is invalid.
955  */
956 XKB_EXPORT int
957 xkb_state_layout_index_is_active(struct xkb_state *state,
958                                 xkb_layout_index_t idx,
959                                 enum xkb_state_component type)
960 {
961     int ret = 0;
962
963     if (idx >= xkb_keymap_num_layouts(state->keymap))
964         return -1;
965
966     /* Can only have one effective group. */
967     if (type & XKB_STATE_EFFECTIVE)
968         return state->group == idx;
969
970     if (type & XKB_STATE_DEPRESSED)
971         ret |= (state->base_group == idx);
972     if (type & XKB_STATE_LATCHED)
973         ret |= (state->latched_group == idx);
974     if (type & XKB_STATE_LOCKED)
975         ret |= (state->locked_group == idx);
976
977     return ret;
978 }
979
980 /**
981  * Returns 1 if the given modifier is active with the specified type(s), 0 if
982  * not, or -1 if the modifier is invalid.
983  */
984 XKB_EXPORT int
985 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
986                                 enum xkb_state_component type)
987 {
988     xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
989
990     if (idx == XKB_LAYOUT_INVALID)
991         return -1;
992
993     return xkb_state_layout_index_is_active(state, idx, type);
994 }
995
996 /**
997  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
998  */
999 XKB_EXPORT int
1000 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1001 {
1002     if (idx >= xkb_keymap_num_leds(state->keymap))
1003         return -1;
1004
1005     return !!(state->leds & (1 << idx));
1006 }
1007
1008 /**
1009  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1010  */
1011 XKB_EXPORT int
1012 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1013 {
1014     xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1015
1016     if (idx == XKB_LED_INVALID)
1017         return -1;
1018
1019     return xkb_state_led_index_is_active(state, idx);
1020 }
1021
1022 static xkb_mod_mask_t
1023 key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
1024 {
1025     struct xkb_kt_map_entry *entry;
1026     xkb_layout_index_t group;
1027
1028     group = xkb_state_key_get_layout(state, key->keycode);
1029     if (group == XKB_LAYOUT_INVALID)
1030         return 0;
1031
1032     entry = get_entry_for_key_state(state, key, group);
1033     if (!entry)
1034         return 0;
1035
1036     return entry->mods.mask & ~entry->preserve.mask;
1037 }
1038
1039 /**
1040  * Tests to see if a modifier is used up by our translation of a
1041  * keycode to keysyms, taking note of the current modifier state and
1042  * the appropriate key type's preserve information, if any. This allows
1043  * the user to mask out the modifier in later processing of the
1044  * modifiers, e.g. when implementing hot keys or accelerators.
1045  *
1046  * See also, for example:
1047  * - XkbTranslateKeyCode(3), mod_rtrn retrun value, from libX11.
1048  * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
1049  *   from gtk+.
1050  */
1051 XKB_EXPORT int
1052 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1053                                 xkb_mod_index_t idx)
1054 {
1055     const struct xkb_key *key = XkbKey(state->keymap, kc);
1056
1057     if (!key)
1058         return 0;
1059
1060     return !!((1 << idx) & key_get_consumed(state, key));
1061 }
1062
1063 /**
1064  * Calculates which modifiers should be consumed during key processing,
1065  * and returns the mask with all these modifiers removed.  e.g. if
1066  * given a state of Alt and Shift active for a two-level alphabetic
1067  * key containing plus and equal on the first and second level
1068  * respectively, will return a mask of only Alt, as Shift has been
1069  * consumed by the type handling.
1070  */
1071 XKB_EXPORT xkb_mod_mask_t
1072 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1073                                    xkb_mod_mask_t mask)
1074 {
1075     const struct xkb_key *key = XkbKey(state->keymap, kc);
1076
1077     if (!key)
1078         return 0;
1079
1080     return mask & ~key_get_consumed(state, key);
1081 }