keymap, symbols: improve xkb_key memory layout
[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     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 XkbKeyActionEntry(key, layout, level);
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  * Serialises the requested modifier state into an xkb_mod_mask_t, with all
770  * the same disclaimers as in xkb_state_update_mask.
771  */
772 XKB_EXPORT xkb_mod_mask_t
773 xkb_state_serialize_mods(struct xkb_state *state,
774                          enum xkb_state_component type)
775 {
776     xkb_mod_mask_t ret = 0;
777
778     if (type == XKB_STATE_EFFECTIVE)
779         return state->mods;
780
781     if (type & XKB_STATE_DEPRESSED)
782         ret |= state->base_mods;
783     if (type & XKB_STATE_LATCHED)
784         ret |= state->latched_mods;
785     if (type & XKB_STATE_LOCKED)
786         ret |= state->locked_mods;
787
788     return ret;
789 }
790
791 /**
792  * Serialises the requested group state, with all the same disclaimers as
793  * in xkb_state_update_mask.
794  */
795 XKB_EXPORT xkb_layout_index_t
796 xkb_state_serialize_layout(struct xkb_state *state,
797                            enum xkb_state_component type)
798 {
799     xkb_layout_index_t ret = 0;
800
801     if (type == XKB_STATE_EFFECTIVE)
802         return state->group;
803
804     if (type & XKB_STATE_DEPRESSED)
805         ret += state->base_group;
806     if (type & XKB_STATE_LATCHED)
807         ret += state->latched_group;
808     if (type & XKB_STATE_LOCKED)
809         ret += state->locked_group;
810
811     return ret;
812 }
813
814 /**
815  * Returns 1 if the given modifier is active with the specified type(s), 0 if
816  * not, or -1 if the modifier is invalid.
817  */
818 XKB_EXPORT int
819 xkb_state_mod_index_is_active(struct xkb_state *state,
820                               xkb_mod_index_t idx,
821                               enum xkb_state_component type)
822 {
823     int ret = 0;
824
825     if (idx >= xkb_keymap_num_mods(state->keymap))
826         return -1;
827
828     if (type & XKB_STATE_EFFECTIVE)
829         return !!(state->mods & (1 << idx));
830
831     if (type & XKB_STATE_DEPRESSED)
832         ret |= (state->base_mods & (1 << idx));
833     if (type & XKB_STATE_LATCHED)
834         ret |= (state->latched_mods & (1 << idx));
835     if (type & XKB_STATE_LOCKED)
836         ret |= (state->locked_mods & (1 << idx));
837
838     return !!ret;
839 }
840
841 /**
842  * Helper function for xkb_state_mod_indices_are_active and
843  * xkb_state_mod_names_are_active.
844  */
845 static int
846 match_mod_masks(struct xkb_state *state, enum xkb_state_match match,
847                 uint32_t wanted)
848 {
849     uint32_t active = xkb_state_serialize_mods(state, XKB_STATE_EFFECTIVE);
850
851     if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
852         return 0;
853
854     if (match & XKB_STATE_MATCH_ANY)
855         return !!(active & wanted);
856     else
857         return (active & wanted) == wanted;
858
859     return 0;
860 }
861
862 /**
863  * Returns 1 if the modifiers are active with the specified type(s), 0 if
864  * not, or -1 if any of the modifiers are invalid.
865  */
866 XKB_EXPORT int
867 xkb_state_mod_indices_are_active(struct xkb_state *state,
868                                  enum xkb_state_component type,
869                                  enum xkb_state_match match,
870                                  ...)
871 {
872     va_list ap;
873     xkb_mod_index_t idx = 0;
874     uint32_t wanted = 0;
875     int ret = 0;
876     xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
877
878     va_start(ap, match);
879     while (1) {
880         idx = va_arg(ap, xkb_mod_index_t);
881         if (idx == XKB_MOD_INVALID)
882             break;
883         if (idx >= num_mods) {
884             ret = -1;
885             break;
886         }
887         wanted |= (1 << idx);
888     }
889     va_end(ap);
890
891     if (ret == -1)
892         return ret;
893
894     return match_mod_masks(state, match, wanted);
895 }
896
897 /**
898  * Returns 1 if the given modifier is active with the specified type(s), 0 if
899  * not, or -1 if the modifier is invalid.
900  */
901 XKB_EXPORT int
902 xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
903                              enum xkb_state_component type)
904 {
905     xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
906
907     if (idx == XKB_MOD_INVALID)
908         return -1;
909
910     return xkb_state_mod_index_is_active(state, idx, type);
911 }
912
913 /**
914  * Returns 1 if the modifiers are active with the specified type(s), 0 if
915  * not, or -1 if any of the modifiers are invalid.
916  */
917 XKB_EXPORT ATTR_NULL_SENTINEL int
918 xkb_state_mod_names_are_active(struct xkb_state *state,
919                                enum xkb_state_component type,
920                                enum xkb_state_match match,
921                                ...)
922 {
923     va_list ap;
924     xkb_mod_index_t idx = 0;
925     const char *str;
926     uint32_t wanted = 0;
927     int ret = 0;
928
929     va_start(ap, match);
930     while (1) {
931         str = va_arg(ap, const char *);
932         if (str == NULL)
933             break;
934         idx = xkb_keymap_mod_get_index(state->keymap, str);
935         if (idx == XKB_MOD_INVALID) {
936             ret = -1;
937             break;
938         }
939         wanted |= (1 << idx);
940     }
941     va_end(ap);
942
943     if (ret == -1)
944         return ret;
945
946     return match_mod_masks(state, match, wanted);
947 }
948
949 /**
950  * Returns 1 if the given group is active with the specified type(s), 0 if
951  * not, or -1 if the group is invalid.
952  */
953 XKB_EXPORT int
954 xkb_state_layout_index_is_active(struct xkb_state *state,
955                                 xkb_layout_index_t idx,
956                                 enum xkb_state_component type)
957 {
958     int ret = 0;
959
960     if (idx >= xkb_keymap_num_layouts(state->keymap))
961         return -1;
962
963     /* Can only have one effective group. */
964     if (type & XKB_STATE_EFFECTIVE)
965         return state->group == idx;
966
967     if (type & XKB_STATE_DEPRESSED)
968         ret |= (state->base_group == idx);
969     if (type & XKB_STATE_LATCHED)
970         ret |= (state->latched_group == idx);
971     if (type & XKB_STATE_LOCKED)
972         ret |= (state->locked_group == idx);
973
974     return ret;
975 }
976
977 /**
978  * Returns 1 if the given modifier is active with the specified type(s), 0 if
979  * not, or -1 if the modifier is invalid.
980  */
981 XKB_EXPORT int
982 xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
983                                 enum xkb_state_component type)
984 {
985     xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
986
987     if (idx == XKB_LAYOUT_INVALID)
988         return -1;
989
990     return xkb_state_layout_index_is_active(state, idx, type);
991 }
992
993 /**
994  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
995  */
996 XKB_EXPORT int
997 xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
998 {
999     if (idx >= xkb_keymap_num_leds(state->keymap))
1000         return -1;
1001
1002     return !!(state->leds & (1 << idx));
1003 }
1004
1005 /**
1006  * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1007  */
1008 XKB_EXPORT int
1009 xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1010 {
1011     xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1012
1013     if (idx == XKB_LED_INVALID)
1014         return -1;
1015
1016     return xkb_state_led_index_is_active(state, idx);
1017 }
1018
1019 static xkb_mod_mask_t
1020 key_get_consumed(struct xkb_state *state, const struct xkb_key *key)
1021 {
1022     struct xkb_kt_map_entry *entry;
1023     xkb_layout_index_t group;
1024
1025     group = xkb_state_key_get_layout(state, key->keycode);
1026     if (group == XKB_LAYOUT_INVALID)
1027         return 0;
1028
1029     entry = get_entry_for_key_state(state, key, group);
1030     if (!entry)
1031         return 0;
1032
1033     return entry->mods.mask & ~entry->preserve.mask;
1034 }
1035
1036 /**
1037  * Tests to see if a modifier is used up by our translation of a
1038  * keycode to keysyms, taking note of the current modifier state and
1039  * the appropriate key type's preserve information, if any. This allows
1040  * the user to mask out the modifier in later processing of the
1041  * modifiers, e.g. when implementing hot keys or accelerators.
1042  *
1043  * See also, for example:
1044  * - XkbTranslateKeyCode(3), mod_rtrn retrun value, from libX11.
1045  * - gdk_keymap_translate_keyboard_state, consumed_modifiers return value,
1046  *   from gtk+.
1047  */
1048 XKB_EXPORT int
1049 xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1050                                 xkb_mod_index_t idx)
1051 {
1052     const struct xkb_key *key = XkbKey(state->keymap, kc);
1053
1054     if (!key)
1055         return 0;
1056
1057     return !!((1 << idx) & key_get_consumed(state, key));
1058 }
1059
1060 /**
1061  * Calculates which modifiers should be consumed during key processing,
1062  * and returns the mask with all these modifiers removed.  e.g. if
1063  * given a state of Alt and Shift active for a two-level alphabetic
1064  * key containing plus and equal on the first and second level
1065  * respectively, will return a mask of only Alt, as Shift has been
1066  * consumed by the type handling.
1067  */
1068 XKB_EXPORT xkb_mod_mask_t
1069 xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1070                                    xkb_mod_mask_t mask)
1071 {
1072     const struct xkb_key *key = XkbKey(state->keymap, kc);
1073
1074     if (!key)
1075         return 0;
1076
1077     return mask & ~key_get_consumed(state, key);
1078 }