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