1*2b949d04SAndroid Build Coastguard Worker /************************************************************
2*2b949d04SAndroid Build Coastguard Worker * Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3*2b949d04SAndroid Build Coastguard Worker *
4*2b949d04SAndroid Build Coastguard Worker * Permission to use, copy, modify, and distribute this
5*2b949d04SAndroid Build Coastguard Worker * software and its documentation for any purpose and without
6*2b949d04SAndroid Build Coastguard Worker * fee is hereby granted, provided that the above copyright
7*2b949d04SAndroid Build Coastguard Worker * notice appear in all copies and that both that copyright
8*2b949d04SAndroid Build Coastguard Worker * notice and this permission notice appear in supporting
9*2b949d04SAndroid Build Coastguard Worker * documentation, and that the name of Silicon Graphics not be
10*2b949d04SAndroid Build Coastguard Worker * used in advertising or publicity pertaining to distribution
11*2b949d04SAndroid Build Coastguard Worker * of the software without specific prior written permission.
12*2b949d04SAndroid Build Coastguard Worker * Silicon Graphics makes no representation about the suitability
13*2b949d04SAndroid Build Coastguard Worker * of this software for any purpose. It is provided "as is"
14*2b949d04SAndroid Build Coastguard Worker * without any express or implied warranty.
15*2b949d04SAndroid Build Coastguard Worker *
16*2b949d04SAndroid Build Coastguard Worker * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17*2b949d04SAndroid Build Coastguard Worker * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18*2b949d04SAndroid Build Coastguard Worker * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19*2b949d04SAndroid Build Coastguard Worker * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20*2b949d04SAndroid Build Coastguard Worker * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*2b949d04SAndroid Build Coastguard Worker * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22*2b949d04SAndroid Build Coastguard Worker * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23*2b949d04SAndroid Build Coastguard Worker * THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*2b949d04SAndroid Build Coastguard Worker *
25*2b949d04SAndroid Build Coastguard Worker ********************************************************/
26*2b949d04SAndroid Build Coastguard Worker
27*2b949d04SAndroid Build Coastguard Worker /*
28*2b949d04SAndroid Build Coastguard Worker * Copyright © 2012 Intel Corporation
29*2b949d04SAndroid Build Coastguard Worker * Copyright © 2012 Ran Benita <[email protected]>
30*2b949d04SAndroid Build Coastguard Worker *
31*2b949d04SAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a
32*2b949d04SAndroid Build Coastguard Worker * copy of this software and associated documentation files (the "Software"),
33*2b949d04SAndroid Build Coastguard Worker * to deal in the Software without restriction, including without limitation
34*2b949d04SAndroid Build Coastguard Worker * the rights to use, copy, modify, merge, publish, distribute, sublicense,
35*2b949d04SAndroid Build Coastguard Worker * and/or sell copies of the Software, and to permit persons to whom the
36*2b949d04SAndroid Build Coastguard Worker * Software is furnished to do so, subject to the following conditions:
37*2b949d04SAndroid Build Coastguard Worker *
38*2b949d04SAndroid Build Coastguard Worker * The above copyright notice and this permission notice (including the next
39*2b949d04SAndroid Build Coastguard Worker * paragraph) shall be included in all copies or substantial portions of the
40*2b949d04SAndroid Build Coastguard Worker * Software.
41*2b949d04SAndroid Build Coastguard Worker *
42*2b949d04SAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43*2b949d04SAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44*2b949d04SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
45*2b949d04SAndroid Build Coastguard Worker * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46*2b949d04SAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47*2b949d04SAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
48*2b949d04SAndroid Build Coastguard Worker * DEALINGS IN THE SOFTWARE.
49*2b949d04SAndroid Build Coastguard Worker *
50*2b949d04SAndroid Build Coastguard Worker * Author: Daniel Stone <[email protected]>
51*2b949d04SAndroid Build Coastguard Worker */
52*2b949d04SAndroid Build Coastguard Worker
53*2b949d04SAndroid Build Coastguard Worker /*
54*2b949d04SAndroid Build Coastguard Worker * This is a bastardised version of xkbActions.c from the X server which
55*2b949d04SAndroid Build Coastguard Worker * does not support, for the moment:
56*2b949d04SAndroid Build Coastguard Worker * - AccessX sticky/debounce/etc (will come later)
57*2b949d04SAndroid Build Coastguard Worker * - pointer keys (may come later)
58*2b949d04SAndroid Build Coastguard Worker * - key redirects (unlikely)
59*2b949d04SAndroid Build Coastguard Worker * - messages (very unlikely)
60*2b949d04SAndroid Build Coastguard Worker */
61*2b949d04SAndroid Build Coastguard Worker
62*2b949d04SAndroid Build Coastguard Worker #include "config.h"
63*2b949d04SAndroid Build Coastguard Worker
64*2b949d04SAndroid Build Coastguard Worker #include "keymap.h"
65*2b949d04SAndroid Build Coastguard Worker #include "keysym.h"
66*2b949d04SAndroid Build Coastguard Worker #include "utf8.h"
67*2b949d04SAndroid Build Coastguard Worker
68*2b949d04SAndroid Build Coastguard Worker struct xkb_filter {
69*2b949d04SAndroid Build Coastguard Worker union xkb_action action;
70*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key;
71*2b949d04SAndroid Build Coastguard Worker uint32_t priv;
72*2b949d04SAndroid Build Coastguard Worker bool (*func)(struct xkb_state *state,
73*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter,
74*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key,
75*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction);
76*2b949d04SAndroid Build Coastguard Worker int refcnt;
77*2b949d04SAndroid Build Coastguard Worker };
78*2b949d04SAndroid Build Coastguard Worker
79*2b949d04SAndroid Build Coastguard Worker struct state_components {
80*2b949d04SAndroid Build Coastguard Worker /* These may be negative, because of -1 group actions. */
81*2b949d04SAndroid Build Coastguard Worker int32_t base_group; /**< depressed */
82*2b949d04SAndroid Build Coastguard Worker int32_t latched_group;
83*2b949d04SAndroid Build Coastguard Worker int32_t locked_group;
84*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t group; /**< effective */
85*2b949d04SAndroid Build Coastguard Worker
86*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t base_mods; /**< depressed */
87*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t latched_mods;
88*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t locked_mods;
89*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t mods; /**< effective */
90*2b949d04SAndroid Build Coastguard Worker
91*2b949d04SAndroid Build Coastguard Worker xkb_led_mask_t leds;
92*2b949d04SAndroid Build Coastguard Worker };
93*2b949d04SAndroid Build Coastguard Worker
94*2b949d04SAndroid Build Coastguard Worker struct xkb_state {
95*2b949d04SAndroid Build Coastguard Worker /*
96*2b949d04SAndroid Build Coastguard Worker * Before updating the state, we keep a copy of just this struct. This
97*2b949d04SAndroid Build Coastguard Worker * allows us to report which components of the state have changed.
98*2b949d04SAndroid Build Coastguard Worker */
99*2b949d04SAndroid Build Coastguard Worker struct state_components components;
100*2b949d04SAndroid Build Coastguard Worker
101*2b949d04SAndroid Build Coastguard Worker /*
102*2b949d04SAndroid Build Coastguard Worker * At each event, we accumulate all the needed modifications to the base
103*2b949d04SAndroid Build Coastguard Worker * modifiers, and apply them at the end. These keep track of this state.
104*2b949d04SAndroid Build Coastguard Worker */
105*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t set_mods;
106*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t clear_mods;
107*2b949d04SAndroid Build Coastguard Worker
108*2b949d04SAndroid Build Coastguard Worker /*
109*2b949d04SAndroid Build Coastguard Worker * We mustn't clear a base modifier if there's another depressed key
110*2b949d04SAndroid Build Coastguard Worker * which affects it, e.g. given this sequence
111*2b949d04SAndroid Build Coastguard Worker * < Left Shift down, Right Shift down, Left Shift Up >
112*2b949d04SAndroid Build Coastguard Worker * the modifier should still be set. This keeps the count.
113*2b949d04SAndroid Build Coastguard Worker */
114*2b949d04SAndroid Build Coastguard Worker int16_t mod_key_count[XKB_MAX_MODS];
115*2b949d04SAndroid Build Coastguard Worker
116*2b949d04SAndroid Build Coastguard Worker int refcnt;
117*2b949d04SAndroid Build Coastguard Worker darray(struct xkb_filter) filters;
118*2b949d04SAndroid Build Coastguard Worker struct xkb_keymap *keymap;
119*2b949d04SAndroid Build Coastguard Worker };
120*2b949d04SAndroid Build Coastguard Worker
121*2b949d04SAndroid Build Coastguard Worker static const struct xkb_key_type_entry *
get_entry_for_mods(const struct xkb_key_type * type,xkb_mod_mask_t mods)122*2b949d04SAndroid Build Coastguard Worker get_entry_for_mods(const struct xkb_key_type *type, xkb_mod_mask_t mods)
123*2b949d04SAndroid Build Coastguard Worker {
124*2b949d04SAndroid Build Coastguard Worker for (unsigned i = 0; i < type->num_entries; i++)
125*2b949d04SAndroid Build Coastguard Worker if (entry_is_active(&type->entries[i]) &&
126*2b949d04SAndroid Build Coastguard Worker type->entries[i].mods.mask == mods)
127*2b949d04SAndroid Build Coastguard Worker return &type->entries[i];
128*2b949d04SAndroid Build Coastguard Worker return NULL;
129*2b949d04SAndroid Build Coastguard Worker }
130*2b949d04SAndroid Build Coastguard Worker
131*2b949d04SAndroid Build Coastguard Worker static const struct xkb_key_type_entry *
get_entry_for_key_state(struct xkb_state * state,const struct xkb_key * key,xkb_layout_index_t group)132*2b949d04SAndroid Build Coastguard Worker get_entry_for_key_state(struct xkb_state *state, const struct xkb_key *key,
133*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t group)
134*2b949d04SAndroid Build Coastguard Worker {
135*2b949d04SAndroid Build Coastguard Worker const struct xkb_key_type *type = key->groups[group].type;
136*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t active_mods = state->components.mods & type->mods.mask;
137*2b949d04SAndroid Build Coastguard Worker return get_entry_for_mods(type, active_mods);
138*2b949d04SAndroid Build Coastguard Worker }
139*2b949d04SAndroid Build Coastguard Worker
140*2b949d04SAndroid Build Coastguard Worker /**
141*2b949d04SAndroid Build Coastguard Worker * Returns the level to use for the given key and state, or
142*2b949d04SAndroid Build Coastguard Worker * XKB_LEVEL_INVALID.
143*2b949d04SAndroid Build Coastguard Worker */
144*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_level_index_t
xkb_state_key_get_level(struct xkb_state * state,xkb_keycode_t kc,xkb_layout_index_t layout)145*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_level(struct xkb_state *state, xkb_keycode_t kc,
146*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t layout)
147*2b949d04SAndroid Build Coastguard Worker {
148*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key = XkbKey(state->keymap, kc);
149*2b949d04SAndroid Build Coastguard Worker const struct xkb_key_type_entry *entry;
150*2b949d04SAndroid Build Coastguard Worker
151*2b949d04SAndroid Build Coastguard Worker if (!key || layout >= key->num_groups)
152*2b949d04SAndroid Build Coastguard Worker return XKB_LEVEL_INVALID;
153*2b949d04SAndroid Build Coastguard Worker
154*2b949d04SAndroid Build Coastguard Worker /* If we don't find an explicit match the default is 0. */
155*2b949d04SAndroid Build Coastguard Worker entry = get_entry_for_key_state(state, key, layout);
156*2b949d04SAndroid Build Coastguard Worker if (!entry)
157*2b949d04SAndroid Build Coastguard Worker return 0;
158*2b949d04SAndroid Build Coastguard Worker
159*2b949d04SAndroid Build Coastguard Worker return entry->level;
160*2b949d04SAndroid Build Coastguard Worker }
161*2b949d04SAndroid Build Coastguard Worker
162*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t
XkbWrapGroupIntoRange(int32_t group,xkb_layout_index_t num_groups,enum xkb_range_exceed_type out_of_range_group_action,xkb_layout_index_t out_of_range_group_number)163*2b949d04SAndroid Build Coastguard Worker XkbWrapGroupIntoRange(int32_t group,
164*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t num_groups,
165*2b949d04SAndroid Build Coastguard Worker enum xkb_range_exceed_type out_of_range_group_action,
166*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t out_of_range_group_number)
167*2b949d04SAndroid Build Coastguard Worker {
168*2b949d04SAndroid Build Coastguard Worker if (num_groups == 0)
169*2b949d04SAndroid Build Coastguard Worker return XKB_LAYOUT_INVALID;
170*2b949d04SAndroid Build Coastguard Worker
171*2b949d04SAndroid Build Coastguard Worker if (group >= 0 && (xkb_layout_index_t) group < num_groups)
172*2b949d04SAndroid Build Coastguard Worker return group;
173*2b949d04SAndroid Build Coastguard Worker
174*2b949d04SAndroid Build Coastguard Worker switch (out_of_range_group_action) {
175*2b949d04SAndroid Build Coastguard Worker case RANGE_REDIRECT:
176*2b949d04SAndroid Build Coastguard Worker if (out_of_range_group_number >= num_groups)
177*2b949d04SAndroid Build Coastguard Worker return 0;
178*2b949d04SAndroid Build Coastguard Worker return out_of_range_group_number;
179*2b949d04SAndroid Build Coastguard Worker
180*2b949d04SAndroid Build Coastguard Worker case RANGE_SATURATE:
181*2b949d04SAndroid Build Coastguard Worker if (group < 0)
182*2b949d04SAndroid Build Coastguard Worker return 0;
183*2b949d04SAndroid Build Coastguard Worker else
184*2b949d04SAndroid Build Coastguard Worker return num_groups - 1;
185*2b949d04SAndroid Build Coastguard Worker
186*2b949d04SAndroid Build Coastguard Worker case RANGE_WRAP:
187*2b949d04SAndroid Build Coastguard Worker default:
188*2b949d04SAndroid Build Coastguard Worker /*
189*2b949d04SAndroid Build Coastguard Worker * C99 says a negative dividend in a modulo operation always
190*2b949d04SAndroid Build Coastguard Worker * gives a negative result.
191*2b949d04SAndroid Build Coastguard Worker */
192*2b949d04SAndroid Build Coastguard Worker if (group < 0)
193*2b949d04SAndroid Build Coastguard Worker return ((int) num_groups + (group % (int) num_groups));
194*2b949d04SAndroid Build Coastguard Worker else
195*2b949d04SAndroid Build Coastguard Worker return group % num_groups;
196*2b949d04SAndroid Build Coastguard Worker }
197*2b949d04SAndroid Build Coastguard Worker }
198*2b949d04SAndroid Build Coastguard Worker
199*2b949d04SAndroid Build Coastguard Worker /**
200*2b949d04SAndroid Build Coastguard Worker * Returns the layout to use for the given key and state, taking
201*2b949d04SAndroid Build Coastguard Worker * wrapping/clamping/etc into account, or XKB_LAYOUT_INVALID.
202*2b949d04SAndroid Build Coastguard Worker */
203*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_layout_index_t
xkb_state_key_get_layout(struct xkb_state * state,xkb_keycode_t kc)204*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_layout(struct xkb_state *state, xkb_keycode_t kc)
205*2b949d04SAndroid Build Coastguard Worker {
206*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key = XkbKey(state->keymap, kc);
207*2b949d04SAndroid Build Coastguard Worker
208*2b949d04SAndroid Build Coastguard Worker if (!key)
209*2b949d04SAndroid Build Coastguard Worker return XKB_LAYOUT_INVALID;
210*2b949d04SAndroid Build Coastguard Worker
211*2b949d04SAndroid Build Coastguard Worker return XkbWrapGroupIntoRange(state->components.group, key->num_groups,
212*2b949d04SAndroid Build Coastguard Worker key->out_of_range_group_action,
213*2b949d04SAndroid Build Coastguard Worker key->out_of_range_group_number);
214*2b949d04SAndroid Build Coastguard Worker }
215*2b949d04SAndroid Build Coastguard Worker
216*2b949d04SAndroid Build Coastguard Worker static const union xkb_action *
xkb_key_get_action(struct xkb_state * state,const struct xkb_key * key)217*2b949d04SAndroid Build Coastguard Worker xkb_key_get_action(struct xkb_state *state, const struct xkb_key *key)
218*2b949d04SAndroid Build Coastguard Worker {
219*2b949d04SAndroid Build Coastguard Worker static const union xkb_action dummy = { .type = ACTION_TYPE_NONE };
220*2b949d04SAndroid Build Coastguard Worker
221*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t layout;
222*2b949d04SAndroid Build Coastguard Worker xkb_level_index_t level;
223*2b949d04SAndroid Build Coastguard Worker
224*2b949d04SAndroid Build Coastguard Worker layout = xkb_state_key_get_layout(state, key->keycode);
225*2b949d04SAndroid Build Coastguard Worker if (layout == XKB_LAYOUT_INVALID)
226*2b949d04SAndroid Build Coastguard Worker return &dummy;
227*2b949d04SAndroid Build Coastguard Worker
228*2b949d04SAndroid Build Coastguard Worker level = xkb_state_key_get_level(state, key->keycode, layout);
229*2b949d04SAndroid Build Coastguard Worker if (level == XKB_LEVEL_INVALID)
230*2b949d04SAndroid Build Coastguard Worker return &dummy;
231*2b949d04SAndroid Build Coastguard Worker
232*2b949d04SAndroid Build Coastguard Worker return &key->groups[layout].levels[level].action;
233*2b949d04SAndroid Build Coastguard Worker }
234*2b949d04SAndroid Build Coastguard Worker
235*2b949d04SAndroid Build Coastguard Worker static struct xkb_filter *
xkb_filter_new(struct xkb_state * state)236*2b949d04SAndroid Build Coastguard Worker xkb_filter_new(struct xkb_state *state)
237*2b949d04SAndroid Build Coastguard Worker {
238*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter = NULL, *iter;
239*2b949d04SAndroid Build Coastguard Worker
240*2b949d04SAndroid Build Coastguard Worker darray_foreach(iter, state->filters) {
241*2b949d04SAndroid Build Coastguard Worker if (iter->func)
242*2b949d04SAndroid Build Coastguard Worker continue;
243*2b949d04SAndroid Build Coastguard Worker filter = iter;
244*2b949d04SAndroid Build Coastguard Worker break;
245*2b949d04SAndroid Build Coastguard Worker }
246*2b949d04SAndroid Build Coastguard Worker
247*2b949d04SAndroid Build Coastguard Worker if (!filter) {
248*2b949d04SAndroid Build Coastguard Worker darray_resize0(state->filters, darray_size(state->filters) + 1);
249*2b949d04SAndroid Build Coastguard Worker filter = &darray_item(state->filters, darray_size(state->filters) -1);
250*2b949d04SAndroid Build Coastguard Worker }
251*2b949d04SAndroid Build Coastguard Worker
252*2b949d04SAndroid Build Coastguard Worker filter->refcnt = 1;
253*2b949d04SAndroid Build Coastguard Worker return filter;
254*2b949d04SAndroid Build Coastguard Worker }
255*2b949d04SAndroid Build Coastguard Worker
256*2b949d04SAndroid Build Coastguard Worker /***====================================================================***/
257*2b949d04SAndroid Build Coastguard Worker
258*2b949d04SAndroid Build Coastguard Worker enum xkb_filter_result {
259*2b949d04SAndroid Build Coastguard Worker /*
260*2b949d04SAndroid Build Coastguard Worker * The event is consumed by the filters.
261*2b949d04SAndroid Build Coastguard Worker *
262*2b949d04SAndroid Build Coastguard Worker * An event is always processed by all filters, but any filter can
263*2b949d04SAndroid Build Coastguard Worker * prevent it from being processed further by consuming it.
264*2b949d04SAndroid Build Coastguard Worker */
265*2b949d04SAndroid Build Coastguard Worker XKB_FILTER_CONSUME,
266*2b949d04SAndroid Build Coastguard Worker /*
267*2b949d04SAndroid Build Coastguard Worker * The event may continue to be processed as far as this filter is
268*2b949d04SAndroid Build Coastguard Worker * concerned.
269*2b949d04SAndroid Build Coastguard Worker */
270*2b949d04SAndroid Build Coastguard Worker XKB_FILTER_CONTINUE,
271*2b949d04SAndroid Build Coastguard Worker };
272*2b949d04SAndroid Build Coastguard Worker
273*2b949d04SAndroid Build Coastguard Worker static void
xkb_filter_group_set_new(struct xkb_state * state,struct xkb_filter * filter)274*2b949d04SAndroid Build Coastguard Worker xkb_filter_group_set_new(struct xkb_state *state, struct xkb_filter *filter)
275*2b949d04SAndroid Build Coastguard Worker {
276*2b949d04SAndroid Build Coastguard Worker filter->priv = state->components.base_group;
277*2b949d04SAndroid Build Coastguard Worker if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
278*2b949d04SAndroid Build Coastguard Worker state->components.base_group = filter->action.group.group;
279*2b949d04SAndroid Build Coastguard Worker else
280*2b949d04SAndroid Build Coastguard Worker state->components.base_group += filter->action.group.group;
281*2b949d04SAndroid Build Coastguard Worker }
282*2b949d04SAndroid Build Coastguard Worker
283*2b949d04SAndroid Build Coastguard Worker static bool
xkb_filter_group_set_func(struct xkb_state * state,struct xkb_filter * filter,const struct xkb_key * key,enum xkb_key_direction direction)284*2b949d04SAndroid Build Coastguard Worker xkb_filter_group_set_func(struct xkb_state *state,
285*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter,
286*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key,
287*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction)
288*2b949d04SAndroid Build Coastguard Worker {
289*2b949d04SAndroid Build Coastguard Worker if (key != filter->key) {
290*2b949d04SAndroid Build Coastguard Worker filter->action.group.flags &= ~ACTION_LOCK_CLEAR;
291*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
292*2b949d04SAndroid Build Coastguard Worker }
293*2b949d04SAndroid Build Coastguard Worker
294*2b949d04SAndroid Build Coastguard Worker if (direction == XKB_KEY_DOWN) {
295*2b949d04SAndroid Build Coastguard Worker filter->refcnt++;
296*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
297*2b949d04SAndroid Build Coastguard Worker }
298*2b949d04SAndroid Build Coastguard Worker else if (--filter->refcnt > 0) {
299*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
300*2b949d04SAndroid Build Coastguard Worker }
301*2b949d04SAndroid Build Coastguard Worker
302*2b949d04SAndroid Build Coastguard Worker state->components.base_group = filter->priv;
303*2b949d04SAndroid Build Coastguard Worker
304*2b949d04SAndroid Build Coastguard Worker if (filter->action.group.flags & ACTION_LOCK_CLEAR)
305*2b949d04SAndroid Build Coastguard Worker state->components.locked_group = 0;
306*2b949d04SAndroid Build Coastguard Worker
307*2b949d04SAndroid Build Coastguard Worker filter->func = NULL;
308*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
309*2b949d04SAndroid Build Coastguard Worker }
310*2b949d04SAndroid Build Coastguard Worker
311*2b949d04SAndroid Build Coastguard Worker static void
xkb_filter_group_lock_new(struct xkb_state * state,struct xkb_filter * filter)312*2b949d04SAndroid Build Coastguard Worker xkb_filter_group_lock_new(struct xkb_state *state, struct xkb_filter *filter)
313*2b949d04SAndroid Build Coastguard Worker {
314*2b949d04SAndroid Build Coastguard Worker if (filter->action.group.flags & ACTION_ABSOLUTE_SWITCH)
315*2b949d04SAndroid Build Coastguard Worker state->components.locked_group = filter->action.group.group;
316*2b949d04SAndroid Build Coastguard Worker else
317*2b949d04SAndroid Build Coastguard Worker state->components.locked_group += filter->action.group.group;
318*2b949d04SAndroid Build Coastguard Worker }
319*2b949d04SAndroid Build Coastguard Worker
320*2b949d04SAndroid Build Coastguard Worker static bool
xkb_filter_group_lock_func(struct xkb_state * state,struct xkb_filter * filter,const struct xkb_key * key,enum xkb_key_direction direction)321*2b949d04SAndroid Build Coastguard Worker xkb_filter_group_lock_func(struct xkb_state *state,
322*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter,
323*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key,
324*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction)
325*2b949d04SAndroid Build Coastguard Worker {
326*2b949d04SAndroid Build Coastguard Worker if (key != filter->key)
327*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
328*2b949d04SAndroid Build Coastguard Worker
329*2b949d04SAndroid Build Coastguard Worker if (direction == XKB_KEY_DOWN) {
330*2b949d04SAndroid Build Coastguard Worker filter->refcnt++;
331*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
332*2b949d04SAndroid Build Coastguard Worker }
333*2b949d04SAndroid Build Coastguard Worker if (--filter->refcnt > 0)
334*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
335*2b949d04SAndroid Build Coastguard Worker
336*2b949d04SAndroid Build Coastguard Worker filter->func = NULL;
337*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
338*2b949d04SAndroid Build Coastguard Worker }
339*2b949d04SAndroid Build Coastguard Worker
340*2b949d04SAndroid Build Coastguard Worker static void
xkb_filter_mod_set_new(struct xkb_state * state,struct xkb_filter * filter)341*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_set_new(struct xkb_state *state, struct xkb_filter *filter)
342*2b949d04SAndroid Build Coastguard Worker {
343*2b949d04SAndroid Build Coastguard Worker state->set_mods = filter->action.mods.mods.mask;
344*2b949d04SAndroid Build Coastguard Worker }
345*2b949d04SAndroid Build Coastguard Worker
346*2b949d04SAndroid Build Coastguard Worker static bool
xkb_filter_mod_set_func(struct xkb_state * state,struct xkb_filter * filter,const struct xkb_key * key,enum xkb_key_direction direction)347*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_set_func(struct xkb_state *state,
348*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter,
349*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key,
350*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction)
351*2b949d04SAndroid Build Coastguard Worker {
352*2b949d04SAndroid Build Coastguard Worker if (key != filter->key) {
353*2b949d04SAndroid Build Coastguard Worker filter->action.mods.flags &= ~ACTION_LOCK_CLEAR;
354*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
355*2b949d04SAndroid Build Coastguard Worker }
356*2b949d04SAndroid Build Coastguard Worker
357*2b949d04SAndroid Build Coastguard Worker if (direction == XKB_KEY_DOWN) {
358*2b949d04SAndroid Build Coastguard Worker filter->refcnt++;
359*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
360*2b949d04SAndroid Build Coastguard Worker }
361*2b949d04SAndroid Build Coastguard Worker else if (--filter->refcnt > 0) {
362*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
363*2b949d04SAndroid Build Coastguard Worker }
364*2b949d04SAndroid Build Coastguard Worker
365*2b949d04SAndroid Build Coastguard Worker state->clear_mods = filter->action.mods.mods.mask;
366*2b949d04SAndroid Build Coastguard Worker if (filter->action.mods.flags & ACTION_LOCK_CLEAR)
367*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods &= ~filter->action.mods.mods.mask;
368*2b949d04SAndroid Build Coastguard Worker
369*2b949d04SAndroid Build Coastguard Worker filter->func = NULL;
370*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
371*2b949d04SAndroid Build Coastguard Worker }
372*2b949d04SAndroid Build Coastguard Worker
373*2b949d04SAndroid Build Coastguard Worker static void
xkb_filter_mod_lock_new(struct xkb_state * state,struct xkb_filter * filter)374*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_lock_new(struct xkb_state *state, struct xkb_filter *filter)
375*2b949d04SAndroid Build Coastguard Worker {
376*2b949d04SAndroid Build Coastguard Worker filter->priv = (state->components.locked_mods &
377*2b949d04SAndroid Build Coastguard Worker filter->action.mods.mods.mask);
378*2b949d04SAndroid Build Coastguard Worker state->set_mods |= filter->action.mods.mods.mask;
379*2b949d04SAndroid Build Coastguard Worker if (!(filter->action.mods.flags & ACTION_LOCK_NO_LOCK))
380*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods |= filter->action.mods.mods.mask;
381*2b949d04SAndroid Build Coastguard Worker }
382*2b949d04SAndroid Build Coastguard Worker
383*2b949d04SAndroid Build Coastguard Worker static bool
xkb_filter_mod_lock_func(struct xkb_state * state,struct xkb_filter * filter,const struct xkb_key * key,enum xkb_key_direction direction)384*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_lock_func(struct xkb_state *state,
385*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter,
386*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key,
387*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction)
388*2b949d04SAndroid Build Coastguard Worker {
389*2b949d04SAndroid Build Coastguard Worker if (key != filter->key)
390*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
391*2b949d04SAndroid Build Coastguard Worker
392*2b949d04SAndroid Build Coastguard Worker if (direction == XKB_KEY_DOWN) {
393*2b949d04SAndroid Build Coastguard Worker filter->refcnt++;
394*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
395*2b949d04SAndroid Build Coastguard Worker }
396*2b949d04SAndroid Build Coastguard Worker if (--filter->refcnt > 0)
397*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
398*2b949d04SAndroid Build Coastguard Worker
399*2b949d04SAndroid Build Coastguard Worker state->clear_mods |= filter->action.mods.mods.mask;
400*2b949d04SAndroid Build Coastguard Worker if (!(filter->action.mods.flags & ACTION_LOCK_NO_UNLOCK))
401*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods &= ~filter->priv;
402*2b949d04SAndroid Build Coastguard Worker
403*2b949d04SAndroid Build Coastguard Worker filter->func = NULL;
404*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
405*2b949d04SAndroid Build Coastguard Worker }
406*2b949d04SAndroid Build Coastguard Worker
407*2b949d04SAndroid Build Coastguard Worker enum xkb_key_latch_state {
408*2b949d04SAndroid Build Coastguard Worker NO_LATCH,
409*2b949d04SAndroid Build Coastguard Worker LATCH_KEY_DOWN,
410*2b949d04SAndroid Build Coastguard Worker LATCH_PENDING,
411*2b949d04SAndroid Build Coastguard Worker };
412*2b949d04SAndroid Build Coastguard Worker
413*2b949d04SAndroid Build Coastguard Worker static bool
xkb_action_breaks_latch(const union xkb_action * action)414*2b949d04SAndroid Build Coastguard Worker xkb_action_breaks_latch(const union xkb_action *action)
415*2b949d04SAndroid Build Coastguard Worker {
416*2b949d04SAndroid Build Coastguard Worker switch (action->type) {
417*2b949d04SAndroid Build Coastguard Worker case ACTION_TYPE_NONE:
418*2b949d04SAndroid Build Coastguard Worker case ACTION_TYPE_PTR_BUTTON:
419*2b949d04SAndroid Build Coastguard Worker case ACTION_TYPE_PTR_LOCK:
420*2b949d04SAndroid Build Coastguard Worker case ACTION_TYPE_CTRL_SET:
421*2b949d04SAndroid Build Coastguard Worker case ACTION_TYPE_CTRL_LOCK:
422*2b949d04SAndroid Build Coastguard Worker case ACTION_TYPE_SWITCH_VT:
423*2b949d04SAndroid Build Coastguard Worker case ACTION_TYPE_TERMINATE:
424*2b949d04SAndroid Build Coastguard Worker return true;
425*2b949d04SAndroid Build Coastguard Worker default:
426*2b949d04SAndroid Build Coastguard Worker return false;
427*2b949d04SAndroid Build Coastguard Worker }
428*2b949d04SAndroid Build Coastguard Worker }
429*2b949d04SAndroid Build Coastguard Worker
430*2b949d04SAndroid Build Coastguard Worker static void
xkb_filter_mod_latch_new(struct xkb_state * state,struct xkb_filter * filter)431*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_latch_new(struct xkb_state *state, struct xkb_filter *filter)
432*2b949d04SAndroid Build Coastguard Worker {
433*2b949d04SAndroid Build Coastguard Worker filter->priv = LATCH_KEY_DOWN;
434*2b949d04SAndroid Build Coastguard Worker state->set_mods = filter->action.mods.mods.mask;
435*2b949d04SAndroid Build Coastguard Worker }
436*2b949d04SAndroid Build Coastguard Worker
437*2b949d04SAndroid Build Coastguard Worker static bool
xkb_filter_mod_latch_func(struct xkb_state * state,struct xkb_filter * filter,const struct xkb_key * key,enum xkb_key_direction direction)438*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_latch_func(struct xkb_state *state,
439*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter,
440*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key,
441*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction)
442*2b949d04SAndroid Build Coastguard Worker {
443*2b949d04SAndroid Build Coastguard Worker enum xkb_key_latch_state latch = filter->priv;
444*2b949d04SAndroid Build Coastguard Worker
445*2b949d04SAndroid Build Coastguard Worker if (direction == XKB_KEY_DOWN && latch == LATCH_PENDING) {
446*2b949d04SAndroid Build Coastguard Worker /* If this is a new keypress and we're awaiting our single latched
447*2b949d04SAndroid Build Coastguard Worker * keypress, then either break the latch if any random key is pressed,
448*2b949d04SAndroid Build Coastguard Worker * or promote it to a lock or plain base set if it's the same
449*2b949d04SAndroid Build Coastguard Worker * modifier. */
450*2b949d04SAndroid Build Coastguard Worker const union xkb_action *action = xkb_key_get_action(state, key);
451*2b949d04SAndroid Build Coastguard Worker if (action->type == ACTION_TYPE_MOD_LATCH &&
452*2b949d04SAndroid Build Coastguard Worker action->mods.flags == filter->action.mods.flags &&
453*2b949d04SAndroid Build Coastguard Worker action->mods.mods.mask == filter->action.mods.mods.mask) {
454*2b949d04SAndroid Build Coastguard Worker filter->action = *action;
455*2b949d04SAndroid Build Coastguard Worker if (filter->action.mods.flags & ACTION_LATCH_TO_LOCK) {
456*2b949d04SAndroid Build Coastguard Worker filter->action.type = ACTION_TYPE_MOD_LOCK;
457*2b949d04SAndroid Build Coastguard Worker filter->func = xkb_filter_mod_lock_func;
458*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods |= filter->action.mods.mods.mask;
459*2b949d04SAndroid Build Coastguard Worker }
460*2b949d04SAndroid Build Coastguard Worker else {
461*2b949d04SAndroid Build Coastguard Worker filter->action.type = ACTION_TYPE_MOD_SET;
462*2b949d04SAndroid Build Coastguard Worker filter->func = xkb_filter_mod_set_func;
463*2b949d04SAndroid Build Coastguard Worker state->set_mods = filter->action.mods.mods.mask;
464*2b949d04SAndroid Build Coastguard Worker }
465*2b949d04SAndroid Build Coastguard Worker filter->key = key;
466*2b949d04SAndroid Build Coastguard Worker state->components.latched_mods &= ~filter->action.mods.mods.mask;
467*2b949d04SAndroid Build Coastguard Worker /* XXX beep beep! */
468*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONSUME;
469*2b949d04SAndroid Build Coastguard Worker }
470*2b949d04SAndroid Build Coastguard Worker else if (xkb_action_breaks_latch(action)) {
471*2b949d04SAndroid Build Coastguard Worker /* XXX: This may be totally broken, we might need to break the
472*2b949d04SAndroid Build Coastguard Worker * latch in the next run after this press? */
473*2b949d04SAndroid Build Coastguard Worker state->components.latched_mods &= ~filter->action.mods.mods.mask;
474*2b949d04SAndroid Build Coastguard Worker filter->func = NULL;
475*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
476*2b949d04SAndroid Build Coastguard Worker }
477*2b949d04SAndroid Build Coastguard Worker }
478*2b949d04SAndroid Build Coastguard Worker else if (direction == XKB_KEY_UP && key == filter->key) {
479*2b949d04SAndroid Build Coastguard Worker /* Our key got released. If we've set it to clear locks, and we
480*2b949d04SAndroid Build Coastguard Worker * currently have the same modifiers locked, then release them and
481*2b949d04SAndroid Build Coastguard Worker * don't actually latch. Else we've actually hit the latching
482*2b949d04SAndroid Build Coastguard Worker * stage, so set PENDING and move our modifier from base to
483*2b949d04SAndroid Build Coastguard Worker * latched. */
484*2b949d04SAndroid Build Coastguard Worker if (latch == NO_LATCH ||
485*2b949d04SAndroid Build Coastguard Worker ((filter->action.mods.flags & ACTION_LOCK_CLEAR) &&
486*2b949d04SAndroid Build Coastguard Worker (state->components.locked_mods & filter->action.mods.mods.mask) ==
487*2b949d04SAndroid Build Coastguard Worker filter->action.mods.mods.mask)) {
488*2b949d04SAndroid Build Coastguard Worker /* XXX: We might be a bit overenthusiastic about clearing
489*2b949d04SAndroid Build Coastguard Worker * mods other filters have set here? */
490*2b949d04SAndroid Build Coastguard Worker if (latch == LATCH_PENDING)
491*2b949d04SAndroid Build Coastguard Worker state->components.latched_mods &=
492*2b949d04SAndroid Build Coastguard Worker ~filter->action.mods.mods.mask;
493*2b949d04SAndroid Build Coastguard Worker else
494*2b949d04SAndroid Build Coastguard Worker state->clear_mods = filter->action.mods.mods.mask;
495*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods &= ~filter->action.mods.mods.mask;
496*2b949d04SAndroid Build Coastguard Worker filter->func = NULL;
497*2b949d04SAndroid Build Coastguard Worker }
498*2b949d04SAndroid Build Coastguard Worker else {
499*2b949d04SAndroid Build Coastguard Worker latch = LATCH_PENDING;
500*2b949d04SAndroid Build Coastguard Worker state->clear_mods = filter->action.mods.mods.mask;
501*2b949d04SAndroid Build Coastguard Worker state->components.latched_mods |= filter->action.mods.mods.mask;
502*2b949d04SAndroid Build Coastguard Worker /* XXX beep beep! */
503*2b949d04SAndroid Build Coastguard Worker }
504*2b949d04SAndroid Build Coastguard Worker }
505*2b949d04SAndroid Build Coastguard Worker else if (direction == XKB_KEY_DOWN && latch == LATCH_KEY_DOWN) {
506*2b949d04SAndroid Build Coastguard Worker /* Someone's pressed another key while we've still got the latching
507*2b949d04SAndroid Build Coastguard Worker * key held down, so keep the base modifier state active (from
508*2b949d04SAndroid Build Coastguard Worker * xkb_filter_mod_latch_new), but don't trip the latch, just clear
509*2b949d04SAndroid Build Coastguard Worker * it as soon as the modifier gets released. */
510*2b949d04SAndroid Build Coastguard Worker latch = NO_LATCH;
511*2b949d04SAndroid Build Coastguard Worker }
512*2b949d04SAndroid Build Coastguard Worker
513*2b949d04SAndroid Build Coastguard Worker filter->priv = latch;
514*2b949d04SAndroid Build Coastguard Worker
515*2b949d04SAndroid Build Coastguard Worker return XKB_FILTER_CONTINUE;
516*2b949d04SAndroid Build Coastguard Worker }
517*2b949d04SAndroid Build Coastguard Worker
518*2b949d04SAndroid Build Coastguard Worker static const struct {
519*2b949d04SAndroid Build Coastguard Worker void (*new)(struct xkb_state *state, struct xkb_filter *filter);
520*2b949d04SAndroid Build Coastguard Worker bool (*func)(struct xkb_state *state, struct xkb_filter *filter,
521*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key, enum xkb_key_direction direction);
522*2b949d04SAndroid Build Coastguard Worker } filter_action_funcs[_ACTION_TYPE_NUM_ENTRIES] = {
523*2b949d04SAndroid Build Coastguard Worker [ACTION_TYPE_MOD_SET] = { xkb_filter_mod_set_new,
524*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_set_func },
525*2b949d04SAndroid Build Coastguard Worker [ACTION_TYPE_MOD_LATCH] = { xkb_filter_mod_latch_new,
526*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_latch_func },
527*2b949d04SAndroid Build Coastguard Worker [ACTION_TYPE_MOD_LOCK] = { xkb_filter_mod_lock_new,
528*2b949d04SAndroid Build Coastguard Worker xkb_filter_mod_lock_func },
529*2b949d04SAndroid Build Coastguard Worker [ACTION_TYPE_GROUP_SET] = { xkb_filter_group_set_new,
530*2b949d04SAndroid Build Coastguard Worker xkb_filter_group_set_func },
531*2b949d04SAndroid Build Coastguard Worker [ACTION_TYPE_GROUP_LOCK] = { xkb_filter_group_lock_new,
532*2b949d04SAndroid Build Coastguard Worker xkb_filter_group_lock_func },
533*2b949d04SAndroid Build Coastguard Worker };
534*2b949d04SAndroid Build Coastguard Worker
535*2b949d04SAndroid Build Coastguard Worker /**
536*2b949d04SAndroid Build Coastguard Worker * Applies any relevant filters to the key, first from the list of filters
537*2b949d04SAndroid Build Coastguard Worker * that are currently active, then if no filter has claimed the key, possibly
538*2b949d04SAndroid Build Coastguard Worker * apply a new filter from the key action.
539*2b949d04SAndroid Build Coastguard Worker */
540*2b949d04SAndroid Build Coastguard Worker static void
xkb_filter_apply_all(struct xkb_state * state,const struct xkb_key * key,enum xkb_key_direction direction)541*2b949d04SAndroid Build Coastguard Worker xkb_filter_apply_all(struct xkb_state *state,
542*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key,
543*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction)
544*2b949d04SAndroid Build Coastguard Worker {
545*2b949d04SAndroid Build Coastguard Worker struct xkb_filter *filter;
546*2b949d04SAndroid Build Coastguard Worker const union xkb_action *action;
547*2b949d04SAndroid Build Coastguard Worker bool consumed;
548*2b949d04SAndroid Build Coastguard Worker
549*2b949d04SAndroid Build Coastguard Worker /* First run through all the currently active filters and see if any of
550*2b949d04SAndroid Build Coastguard Worker * them have consumed this event. */
551*2b949d04SAndroid Build Coastguard Worker consumed = false;
552*2b949d04SAndroid Build Coastguard Worker darray_foreach(filter, state->filters) {
553*2b949d04SAndroid Build Coastguard Worker if (!filter->func)
554*2b949d04SAndroid Build Coastguard Worker continue;
555*2b949d04SAndroid Build Coastguard Worker
556*2b949d04SAndroid Build Coastguard Worker if (filter->func(state, filter, key, direction) == XKB_FILTER_CONSUME)
557*2b949d04SAndroid Build Coastguard Worker consumed = true;
558*2b949d04SAndroid Build Coastguard Worker }
559*2b949d04SAndroid Build Coastguard Worker if (consumed || direction == XKB_KEY_UP)
560*2b949d04SAndroid Build Coastguard Worker return;
561*2b949d04SAndroid Build Coastguard Worker
562*2b949d04SAndroid Build Coastguard Worker action = xkb_key_get_action(state, key);
563*2b949d04SAndroid Build Coastguard Worker
564*2b949d04SAndroid Build Coastguard Worker /*
565*2b949d04SAndroid Build Coastguard Worker * It's possible for the keymap to set action->type explicitly, like so:
566*2b949d04SAndroid Build Coastguard Worker * interpret XF86_Next_VMode {
567*2b949d04SAndroid Build Coastguard Worker * action = Private(type=0x86, data="+VMode");
568*2b949d04SAndroid Build Coastguard Worker * };
569*2b949d04SAndroid Build Coastguard Worker * We don't handle those.
570*2b949d04SAndroid Build Coastguard Worker */
571*2b949d04SAndroid Build Coastguard Worker if (action->type >= _ACTION_TYPE_NUM_ENTRIES)
572*2b949d04SAndroid Build Coastguard Worker return;
573*2b949d04SAndroid Build Coastguard Worker
574*2b949d04SAndroid Build Coastguard Worker if (!filter_action_funcs[action->type].new)
575*2b949d04SAndroid Build Coastguard Worker return;
576*2b949d04SAndroid Build Coastguard Worker
577*2b949d04SAndroid Build Coastguard Worker filter = xkb_filter_new(state);
578*2b949d04SAndroid Build Coastguard Worker filter->key = key;
579*2b949d04SAndroid Build Coastguard Worker filter->func = filter_action_funcs[action->type].func;
580*2b949d04SAndroid Build Coastguard Worker filter->action = *action;
581*2b949d04SAndroid Build Coastguard Worker filter_action_funcs[action->type].new(state, filter);
582*2b949d04SAndroid Build Coastguard Worker }
583*2b949d04SAndroid Build Coastguard Worker
584*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT struct xkb_state *
xkb_state_new(struct xkb_keymap * keymap)585*2b949d04SAndroid Build Coastguard Worker xkb_state_new(struct xkb_keymap *keymap)
586*2b949d04SAndroid Build Coastguard Worker {
587*2b949d04SAndroid Build Coastguard Worker struct xkb_state *ret;
588*2b949d04SAndroid Build Coastguard Worker
589*2b949d04SAndroid Build Coastguard Worker ret = calloc(sizeof(*ret), 1);
590*2b949d04SAndroid Build Coastguard Worker if (!ret)
591*2b949d04SAndroid Build Coastguard Worker return NULL;
592*2b949d04SAndroid Build Coastguard Worker
593*2b949d04SAndroid Build Coastguard Worker ret->refcnt = 1;
594*2b949d04SAndroid Build Coastguard Worker ret->keymap = xkb_keymap_ref(keymap);
595*2b949d04SAndroid Build Coastguard Worker
596*2b949d04SAndroid Build Coastguard Worker return ret;
597*2b949d04SAndroid Build Coastguard Worker }
598*2b949d04SAndroid Build Coastguard Worker
599*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT struct xkb_state *
xkb_state_ref(struct xkb_state * state)600*2b949d04SAndroid Build Coastguard Worker xkb_state_ref(struct xkb_state *state)
601*2b949d04SAndroid Build Coastguard Worker {
602*2b949d04SAndroid Build Coastguard Worker state->refcnt++;
603*2b949d04SAndroid Build Coastguard Worker return state;
604*2b949d04SAndroid Build Coastguard Worker }
605*2b949d04SAndroid Build Coastguard Worker
606*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT void
xkb_state_unref(struct xkb_state * state)607*2b949d04SAndroid Build Coastguard Worker xkb_state_unref(struct xkb_state *state)
608*2b949d04SAndroid Build Coastguard Worker {
609*2b949d04SAndroid Build Coastguard Worker if (!state || --state->refcnt > 0)
610*2b949d04SAndroid Build Coastguard Worker return;
611*2b949d04SAndroid Build Coastguard Worker
612*2b949d04SAndroid Build Coastguard Worker xkb_keymap_unref(state->keymap);
613*2b949d04SAndroid Build Coastguard Worker darray_free(state->filters);
614*2b949d04SAndroid Build Coastguard Worker free(state);
615*2b949d04SAndroid Build Coastguard Worker }
616*2b949d04SAndroid Build Coastguard Worker
617*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT struct xkb_keymap *
xkb_state_get_keymap(struct xkb_state * state)618*2b949d04SAndroid Build Coastguard Worker xkb_state_get_keymap(struct xkb_state *state)
619*2b949d04SAndroid Build Coastguard Worker {
620*2b949d04SAndroid Build Coastguard Worker return state->keymap;
621*2b949d04SAndroid Build Coastguard Worker }
622*2b949d04SAndroid Build Coastguard Worker
623*2b949d04SAndroid Build Coastguard Worker /**
624*2b949d04SAndroid Build Coastguard Worker * Update the LED state to match the rest of the xkb_state.
625*2b949d04SAndroid Build Coastguard Worker */
626*2b949d04SAndroid Build Coastguard Worker static void
xkb_state_led_update_all(struct xkb_state * state)627*2b949d04SAndroid Build Coastguard Worker xkb_state_led_update_all(struct xkb_state *state)
628*2b949d04SAndroid Build Coastguard Worker {
629*2b949d04SAndroid Build Coastguard Worker xkb_led_index_t idx;
630*2b949d04SAndroid Build Coastguard Worker const struct xkb_led *led;
631*2b949d04SAndroid Build Coastguard Worker
632*2b949d04SAndroid Build Coastguard Worker state->components.leds = 0;
633*2b949d04SAndroid Build Coastguard Worker
634*2b949d04SAndroid Build Coastguard Worker xkb_leds_enumerate(idx, led, state->keymap) {
635*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t mod_mask = 0;
636*2b949d04SAndroid Build Coastguard Worker xkb_layout_mask_t group_mask = 0;
637*2b949d04SAndroid Build Coastguard Worker
638*2b949d04SAndroid Build Coastguard Worker if (led->which_mods != 0 && led->mods.mask != 0) {
639*2b949d04SAndroid Build Coastguard Worker if (led->which_mods & XKB_STATE_MODS_EFFECTIVE)
640*2b949d04SAndroid Build Coastguard Worker mod_mask |= state->components.mods;
641*2b949d04SAndroid Build Coastguard Worker if (led->which_mods & XKB_STATE_MODS_DEPRESSED)
642*2b949d04SAndroid Build Coastguard Worker mod_mask |= state->components.base_mods;
643*2b949d04SAndroid Build Coastguard Worker if (led->which_mods & XKB_STATE_MODS_LATCHED)
644*2b949d04SAndroid Build Coastguard Worker mod_mask |= state->components.latched_mods;
645*2b949d04SAndroid Build Coastguard Worker if (led->which_mods & XKB_STATE_MODS_LOCKED)
646*2b949d04SAndroid Build Coastguard Worker mod_mask |= state->components.locked_mods;
647*2b949d04SAndroid Build Coastguard Worker
648*2b949d04SAndroid Build Coastguard Worker if (led->mods.mask & mod_mask) {
649*2b949d04SAndroid Build Coastguard Worker state->components.leds |= (1u << idx);
650*2b949d04SAndroid Build Coastguard Worker continue;
651*2b949d04SAndroid Build Coastguard Worker }
652*2b949d04SAndroid Build Coastguard Worker }
653*2b949d04SAndroid Build Coastguard Worker
654*2b949d04SAndroid Build Coastguard Worker if (led->which_groups != 0 && led->groups != 0) {
655*2b949d04SAndroid Build Coastguard Worker if (led->which_groups & XKB_STATE_LAYOUT_EFFECTIVE)
656*2b949d04SAndroid Build Coastguard Worker group_mask |= (1u << state->components.group);
657*2b949d04SAndroid Build Coastguard Worker if (led->which_groups & XKB_STATE_LAYOUT_DEPRESSED)
658*2b949d04SAndroid Build Coastguard Worker group_mask |= (1u << state->components.base_group);
659*2b949d04SAndroid Build Coastguard Worker if (led->which_groups & XKB_STATE_LAYOUT_LATCHED)
660*2b949d04SAndroid Build Coastguard Worker group_mask |= (1u << state->components.latched_group);
661*2b949d04SAndroid Build Coastguard Worker if (led->which_groups & XKB_STATE_LAYOUT_LOCKED)
662*2b949d04SAndroid Build Coastguard Worker group_mask |= (1u << state->components.locked_group);
663*2b949d04SAndroid Build Coastguard Worker
664*2b949d04SAndroid Build Coastguard Worker if (led->groups & group_mask) {
665*2b949d04SAndroid Build Coastguard Worker state->components.leds |= (1u << idx);
666*2b949d04SAndroid Build Coastguard Worker continue;
667*2b949d04SAndroid Build Coastguard Worker }
668*2b949d04SAndroid Build Coastguard Worker }
669*2b949d04SAndroid Build Coastguard Worker
670*2b949d04SAndroid Build Coastguard Worker if (led->ctrls & state->keymap->enabled_ctrls) {
671*2b949d04SAndroid Build Coastguard Worker state->components.leds |= (1u << idx);
672*2b949d04SAndroid Build Coastguard Worker continue;
673*2b949d04SAndroid Build Coastguard Worker }
674*2b949d04SAndroid Build Coastguard Worker }
675*2b949d04SAndroid Build Coastguard Worker }
676*2b949d04SAndroid Build Coastguard Worker
677*2b949d04SAndroid Build Coastguard Worker /**
678*2b949d04SAndroid Build Coastguard Worker * Calculates the derived state (effective mods/group and LEDs) from an
679*2b949d04SAndroid Build Coastguard Worker * up-to-date xkb_state.
680*2b949d04SAndroid Build Coastguard Worker */
681*2b949d04SAndroid Build Coastguard Worker static void
xkb_state_update_derived(struct xkb_state * state)682*2b949d04SAndroid Build Coastguard Worker xkb_state_update_derived(struct xkb_state *state)
683*2b949d04SAndroid Build Coastguard Worker {
684*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t wrapped;
685*2b949d04SAndroid Build Coastguard Worker
686*2b949d04SAndroid Build Coastguard Worker state->components.mods = (state->components.base_mods |
687*2b949d04SAndroid Build Coastguard Worker state->components.latched_mods |
688*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods);
689*2b949d04SAndroid Build Coastguard Worker
690*2b949d04SAndroid Build Coastguard Worker /* TODO: Use groups_wrap control instead of always RANGE_WRAP. */
691*2b949d04SAndroid Build Coastguard Worker
692*2b949d04SAndroid Build Coastguard Worker wrapped = XkbWrapGroupIntoRange(state->components.locked_group,
693*2b949d04SAndroid Build Coastguard Worker state->keymap->num_groups,
694*2b949d04SAndroid Build Coastguard Worker RANGE_WRAP, 0);
695*2b949d04SAndroid Build Coastguard Worker state->components.locked_group =
696*2b949d04SAndroid Build Coastguard Worker (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
697*2b949d04SAndroid Build Coastguard Worker
698*2b949d04SAndroid Build Coastguard Worker wrapped = XkbWrapGroupIntoRange(state->components.base_group +
699*2b949d04SAndroid Build Coastguard Worker state->components.latched_group +
700*2b949d04SAndroid Build Coastguard Worker state->components.locked_group,
701*2b949d04SAndroid Build Coastguard Worker state->keymap->num_groups,
702*2b949d04SAndroid Build Coastguard Worker RANGE_WRAP, 0);
703*2b949d04SAndroid Build Coastguard Worker state->components.group =
704*2b949d04SAndroid Build Coastguard Worker (wrapped == XKB_LAYOUT_INVALID ? 0 : wrapped);
705*2b949d04SAndroid Build Coastguard Worker
706*2b949d04SAndroid Build Coastguard Worker xkb_state_led_update_all(state);
707*2b949d04SAndroid Build Coastguard Worker }
708*2b949d04SAndroid Build Coastguard Worker
709*2b949d04SAndroid Build Coastguard Worker static enum xkb_state_component
get_state_component_changes(const struct state_components * a,const struct state_components * b)710*2b949d04SAndroid Build Coastguard Worker get_state_component_changes(const struct state_components *a,
711*2b949d04SAndroid Build Coastguard Worker const struct state_components *b)
712*2b949d04SAndroid Build Coastguard Worker {
713*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t mask = 0;
714*2b949d04SAndroid Build Coastguard Worker
715*2b949d04SAndroid Build Coastguard Worker if (a->group != b->group)
716*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_LAYOUT_EFFECTIVE;
717*2b949d04SAndroid Build Coastguard Worker if (a->base_group != b->base_group)
718*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_LAYOUT_DEPRESSED;
719*2b949d04SAndroid Build Coastguard Worker if (a->latched_group != b->latched_group)
720*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_LAYOUT_LATCHED;
721*2b949d04SAndroid Build Coastguard Worker if (a->locked_group != b->locked_group)
722*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_LAYOUT_LOCKED;
723*2b949d04SAndroid Build Coastguard Worker if (a->mods != b->mods)
724*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_MODS_EFFECTIVE;
725*2b949d04SAndroid Build Coastguard Worker if (a->base_mods != b->base_mods)
726*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_MODS_DEPRESSED;
727*2b949d04SAndroid Build Coastguard Worker if (a->latched_mods != b->latched_mods)
728*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_MODS_LATCHED;
729*2b949d04SAndroid Build Coastguard Worker if (a->locked_mods != b->locked_mods)
730*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_MODS_LOCKED;
731*2b949d04SAndroid Build Coastguard Worker if (a->leds != b->leds)
732*2b949d04SAndroid Build Coastguard Worker mask |= XKB_STATE_LEDS;
733*2b949d04SAndroid Build Coastguard Worker
734*2b949d04SAndroid Build Coastguard Worker return mask;
735*2b949d04SAndroid Build Coastguard Worker }
736*2b949d04SAndroid Build Coastguard Worker
737*2b949d04SAndroid Build Coastguard Worker /**
738*2b949d04SAndroid Build Coastguard Worker * Given a particular key event, updates the state structure to reflect the
739*2b949d04SAndroid Build Coastguard Worker * new modifiers.
740*2b949d04SAndroid Build Coastguard Worker */
741*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT enum xkb_state_component
xkb_state_update_key(struct xkb_state * state,xkb_keycode_t kc,enum xkb_key_direction direction)742*2b949d04SAndroid Build Coastguard Worker xkb_state_update_key(struct xkb_state *state, xkb_keycode_t kc,
743*2b949d04SAndroid Build Coastguard Worker enum xkb_key_direction direction)
744*2b949d04SAndroid Build Coastguard Worker {
745*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t i;
746*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t bit;
747*2b949d04SAndroid Build Coastguard Worker struct state_components prev_components;
748*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key = XkbKey(state->keymap, kc);
749*2b949d04SAndroid Build Coastguard Worker
750*2b949d04SAndroid Build Coastguard Worker if (!key)
751*2b949d04SAndroid Build Coastguard Worker return 0;
752*2b949d04SAndroid Build Coastguard Worker
753*2b949d04SAndroid Build Coastguard Worker prev_components = state->components;
754*2b949d04SAndroid Build Coastguard Worker
755*2b949d04SAndroid Build Coastguard Worker state->set_mods = 0;
756*2b949d04SAndroid Build Coastguard Worker state->clear_mods = 0;
757*2b949d04SAndroid Build Coastguard Worker
758*2b949d04SAndroid Build Coastguard Worker xkb_filter_apply_all(state, key, direction);
759*2b949d04SAndroid Build Coastguard Worker
760*2b949d04SAndroid Build Coastguard Worker for (i = 0, bit = 1; state->set_mods; i++, bit <<= 1) {
761*2b949d04SAndroid Build Coastguard Worker if (state->set_mods & bit) {
762*2b949d04SAndroid Build Coastguard Worker state->mod_key_count[i]++;
763*2b949d04SAndroid Build Coastguard Worker state->components.base_mods |= bit;
764*2b949d04SAndroid Build Coastguard Worker state->set_mods &= ~bit;
765*2b949d04SAndroid Build Coastguard Worker }
766*2b949d04SAndroid Build Coastguard Worker }
767*2b949d04SAndroid Build Coastguard Worker
768*2b949d04SAndroid Build Coastguard Worker for (i = 0, bit = 1; state->clear_mods; i++, bit <<= 1) {
769*2b949d04SAndroid Build Coastguard Worker if (state->clear_mods & bit) {
770*2b949d04SAndroid Build Coastguard Worker state->mod_key_count[i]--;
771*2b949d04SAndroid Build Coastguard Worker if (state->mod_key_count[i] <= 0) {
772*2b949d04SAndroid Build Coastguard Worker state->components.base_mods &= ~bit;
773*2b949d04SAndroid Build Coastguard Worker state->mod_key_count[i] = 0;
774*2b949d04SAndroid Build Coastguard Worker }
775*2b949d04SAndroid Build Coastguard Worker state->clear_mods &= ~bit;
776*2b949d04SAndroid Build Coastguard Worker }
777*2b949d04SAndroid Build Coastguard Worker }
778*2b949d04SAndroid Build Coastguard Worker
779*2b949d04SAndroid Build Coastguard Worker xkb_state_update_derived(state);
780*2b949d04SAndroid Build Coastguard Worker
781*2b949d04SAndroid Build Coastguard Worker return get_state_component_changes(&prev_components, &state->components);
782*2b949d04SAndroid Build Coastguard Worker }
783*2b949d04SAndroid Build Coastguard Worker
784*2b949d04SAndroid Build Coastguard Worker /**
785*2b949d04SAndroid Build Coastguard Worker * Updates the state from a set of explicit masks as gained from
786*2b949d04SAndroid Build Coastguard Worker * xkb_state_serialize_mods and xkb_state_serialize_groups. As noted in the
787*2b949d04SAndroid Build Coastguard Worker * documentation for these functions in xkbcommon.h, this round-trip is
788*2b949d04SAndroid Build Coastguard Worker * lossy, and should only be used to update a slave state mirroring the
789*2b949d04SAndroid Build Coastguard Worker * master, e.g. in a client/server window system.
790*2b949d04SAndroid Build Coastguard Worker */
791*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT enum xkb_state_component
xkb_state_update_mask(struct xkb_state * state,xkb_mod_mask_t base_mods,xkb_mod_mask_t latched_mods,xkb_mod_mask_t locked_mods,xkb_layout_index_t base_group,xkb_layout_index_t latched_group,xkb_layout_index_t locked_group)792*2b949d04SAndroid Build Coastguard Worker xkb_state_update_mask(struct xkb_state *state,
793*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t base_mods,
794*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t latched_mods,
795*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t locked_mods,
796*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t base_group,
797*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t latched_group,
798*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t locked_group)
799*2b949d04SAndroid Build Coastguard Worker {
800*2b949d04SAndroid Build Coastguard Worker struct state_components prev_components;
801*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t mask;
802*2b949d04SAndroid Build Coastguard Worker
803*2b949d04SAndroid Build Coastguard Worker prev_components = state->components;
804*2b949d04SAndroid Build Coastguard Worker
805*2b949d04SAndroid Build Coastguard Worker /* Only include modifiers which exist in the keymap. */
806*2b949d04SAndroid Build Coastguard Worker mask = (xkb_mod_mask_t) ((1ull << xkb_keymap_num_mods(state->keymap)) - 1u);
807*2b949d04SAndroid Build Coastguard Worker
808*2b949d04SAndroid Build Coastguard Worker state->components.base_mods = base_mods & mask;
809*2b949d04SAndroid Build Coastguard Worker state->components.latched_mods = latched_mods & mask;
810*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods = locked_mods & mask;
811*2b949d04SAndroid Build Coastguard Worker
812*2b949d04SAndroid Build Coastguard Worker /* Make sure the mods are fully resolved - since we get arbitrary
813*2b949d04SAndroid Build Coastguard Worker * input, they might not be.
814*2b949d04SAndroid Build Coastguard Worker *
815*2b949d04SAndroid Build Coastguard Worker * It might seem more reasonable to do this only for components.mods
816*2b949d04SAndroid Build Coastguard Worker * in xkb_state_update_derived(), rather than for each component
817*2b949d04SAndroid Build Coastguard Worker * seperately. That would allow to distinguish between "really"
818*2b949d04SAndroid Build Coastguard Worker * depressed mods (would be in MODS_DEPRESSED) and indirectly
819*2b949d04SAndroid Build Coastguard Worker * depressed to to a mapping (would only be in MODS_EFFECTIVE).
820*2b949d04SAndroid Build Coastguard Worker * However, the traditional behavior of xkb_state_update_key() is that
821*2b949d04SAndroid Build Coastguard Worker * if a vmod is depressed, its mappings are depressed with it; so we're
822*2b949d04SAndroid Build Coastguard Worker * expected to do the same here. Also, LEDs (usually) look if a real
823*2b949d04SAndroid Build Coastguard Worker * mod is locked, not just effective; otherwise it won't be lit.
824*2b949d04SAndroid Build Coastguard Worker *
825*2b949d04SAndroid Build Coastguard Worker * We OR here because mod_mask_get_effective() drops vmods. */
826*2b949d04SAndroid Build Coastguard Worker state->components.base_mods |=
827*2b949d04SAndroid Build Coastguard Worker mod_mask_get_effective(state->keymap, state->components.base_mods);
828*2b949d04SAndroid Build Coastguard Worker state->components.latched_mods |=
829*2b949d04SAndroid Build Coastguard Worker mod_mask_get_effective(state->keymap, state->components.latched_mods);
830*2b949d04SAndroid Build Coastguard Worker state->components.locked_mods |=
831*2b949d04SAndroid Build Coastguard Worker mod_mask_get_effective(state->keymap, state->components.locked_mods);
832*2b949d04SAndroid Build Coastguard Worker
833*2b949d04SAndroid Build Coastguard Worker state->components.base_group = base_group;
834*2b949d04SAndroid Build Coastguard Worker state->components.latched_group = latched_group;
835*2b949d04SAndroid Build Coastguard Worker state->components.locked_group = locked_group;
836*2b949d04SAndroid Build Coastguard Worker
837*2b949d04SAndroid Build Coastguard Worker xkb_state_update_derived(state);
838*2b949d04SAndroid Build Coastguard Worker
839*2b949d04SAndroid Build Coastguard Worker return get_state_component_changes(&prev_components, &state->components);
840*2b949d04SAndroid Build Coastguard Worker }
841*2b949d04SAndroid Build Coastguard Worker
842*2b949d04SAndroid Build Coastguard Worker /**
843*2b949d04SAndroid Build Coastguard Worker * Provides the symbols to use for the given key and state. Returns the
844*2b949d04SAndroid Build Coastguard Worker * number of symbols pointed to in syms_out.
845*2b949d04SAndroid Build Coastguard Worker */
846*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_key_get_syms(struct xkb_state * state,xkb_keycode_t kc,const xkb_keysym_t ** syms_out)847*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_syms(struct xkb_state *state, xkb_keycode_t kc,
848*2b949d04SAndroid Build Coastguard Worker const xkb_keysym_t **syms_out)
849*2b949d04SAndroid Build Coastguard Worker {
850*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t layout;
851*2b949d04SAndroid Build Coastguard Worker xkb_level_index_t level;
852*2b949d04SAndroid Build Coastguard Worker
853*2b949d04SAndroid Build Coastguard Worker layout = xkb_state_key_get_layout(state, kc);
854*2b949d04SAndroid Build Coastguard Worker if (layout == XKB_LAYOUT_INVALID)
855*2b949d04SAndroid Build Coastguard Worker goto err;
856*2b949d04SAndroid Build Coastguard Worker
857*2b949d04SAndroid Build Coastguard Worker level = xkb_state_key_get_level(state, kc, layout);
858*2b949d04SAndroid Build Coastguard Worker if (level == XKB_LEVEL_INVALID)
859*2b949d04SAndroid Build Coastguard Worker goto err;
860*2b949d04SAndroid Build Coastguard Worker
861*2b949d04SAndroid Build Coastguard Worker return xkb_keymap_key_get_syms_by_level(state->keymap, kc, layout, level,
862*2b949d04SAndroid Build Coastguard Worker syms_out);
863*2b949d04SAndroid Build Coastguard Worker
864*2b949d04SAndroid Build Coastguard Worker err:
865*2b949d04SAndroid Build Coastguard Worker *syms_out = NULL;
866*2b949d04SAndroid Build Coastguard Worker return 0;
867*2b949d04SAndroid Build Coastguard Worker }
868*2b949d04SAndroid Build Coastguard Worker
869*2b949d04SAndroid Build Coastguard Worker /*
870*2b949d04SAndroid Build Coastguard Worker * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Lock_Modifier
871*2b949d04SAndroid Build Coastguard Worker */
872*2b949d04SAndroid Build Coastguard Worker static bool
should_do_caps_transformation(struct xkb_state * state,xkb_keycode_t kc)873*2b949d04SAndroid Build Coastguard Worker should_do_caps_transformation(struct xkb_state *state, xkb_keycode_t kc)
874*2b949d04SAndroid Build Coastguard Worker {
875*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t caps =
876*2b949d04SAndroid Build Coastguard Worker xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CAPS);
877*2b949d04SAndroid Build Coastguard Worker
878*2b949d04SAndroid Build Coastguard Worker return
879*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_index_is_active(state, caps, XKB_STATE_MODS_EFFECTIVE) > 0 &&
880*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_index_is_consumed(state, kc, caps) == 0;
881*2b949d04SAndroid Build Coastguard Worker }
882*2b949d04SAndroid Build Coastguard Worker
883*2b949d04SAndroid Build Coastguard Worker /*
884*2b949d04SAndroid Build Coastguard Worker * https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
885*2b949d04SAndroid Build Coastguard Worker */
886*2b949d04SAndroid Build Coastguard Worker static bool
should_do_ctrl_transformation(struct xkb_state * state,xkb_keycode_t kc)887*2b949d04SAndroid Build Coastguard Worker should_do_ctrl_transformation(struct xkb_state *state, xkb_keycode_t kc)
888*2b949d04SAndroid Build Coastguard Worker {
889*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t ctrl =
890*2b949d04SAndroid Build Coastguard Worker xkb_keymap_mod_get_index(state->keymap, XKB_MOD_NAME_CTRL);
891*2b949d04SAndroid Build Coastguard Worker
892*2b949d04SAndroid Build Coastguard Worker return
893*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_index_is_active(state, ctrl, XKB_STATE_MODS_EFFECTIVE) > 0 &&
894*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_index_is_consumed(state, kc, ctrl) == 0;
895*2b949d04SAndroid Build Coastguard Worker }
896*2b949d04SAndroid Build Coastguard Worker
897*2b949d04SAndroid Build Coastguard Worker /* Verbatim from libX11:src/xkb/XKBBind.c */
898*2b949d04SAndroid Build Coastguard Worker static char
XkbToControl(char ch)899*2b949d04SAndroid Build Coastguard Worker XkbToControl(char ch)
900*2b949d04SAndroid Build Coastguard Worker {
901*2b949d04SAndroid Build Coastguard Worker char c = ch;
902*2b949d04SAndroid Build Coastguard Worker
903*2b949d04SAndroid Build Coastguard Worker if ((c >= '@' && c < '\177') || c == ' ')
904*2b949d04SAndroid Build Coastguard Worker c &= 0x1F;
905*2b949d04SAndroid Build Coastguard Worker else if (c == '2')
906*2b949d04SAndroid Build Coastguard Worker c = '\000';
907*2b949d04SAndroid Build Coastguard Worker else if (c >= '3' && c <= '7')
908*2b949d04SAndroid Build Coastguard Worker c -= ('3' - '\033');
909*2b949d04SAndroid Build Coastguard Worker else if (c == '8')
910*2b949d04SAndroid Build Coastguard Worker c = '\177';
911*2b949d04SAndroid Build Coastguard Worker else if (c == '/')
912*2b949d04SAndroid Build Coastguard Worker c = '_' & 0x1F;
913*2b949d04SAndroid Build Coastguard Worker return c;
914*2b949d04SAndroid Build Coastguard Worker }
915*2b949d04SAndroid Build Coastguard Worker
916*2b949d04SAndroid Build Coastguard Worker /**
917*2b949d04SAndroid Build Coastguard Worker * Provides either exactly one symbol, or XKB_KEY_NoSymbol.
918*2b949d04SAndroid Build Coastguard Worker */
919*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_keysym_t
xkb_state_key_get_one_sym(struct xkb_state * state,xkb_keycode_t kc)920*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_one_sym(struct xkb_state *state, xkb_keycode_t kc)
921*2b949d04SAndroid Build Coastguard Worker {
922*2b949d04SAndroid Build Coastguard Worker const xkb_keysym_t *syms;
923*2b949d04SAndroid Build Coastguard Worker xkb_keysym_t sym;
924*2b949d04SAndroid Build Coastguard Worker int num_syms;
925*2b949d04SAndroid Build Coastguard Worker
926*2b949d04SAndroid Build Coastguard Worker num_syms = xkb_state_key_get_syms(state, kc, &syms);
927*2b949d04SAndroid Build Coastguard Worker if (num_syms != 1)
928*2b949d04SAndroid Build Coastguard Worker return XKB_KEY_NoSymbol;
929*2b949d04SAndroid Build Coastguard Worker
930*2b949d04SAndroid Build Coastguard Worker sym = syms[0];
931*2b949d04SAndroid Build Coastguard Worker
932*2b949d04SAndroid Build Coastguard Worker if (should_do_caps_transformation(state, kc))
933*2b949d04SAndroid Build Coastguard Worker sym = xkb_keysym_to_upper(sym);
934*2b949d04SAndroid Build Coastguard Worker
935*2b949d04SAndroid Build Coastguard Worker return sym;
936*2b949d04SAndroid Build Coastguard Worker }
937*2b949d04SAndroid Build Coastguard Worker
938*2b949d04SAndroid Build Coastguard Worker /*
939*2b949d04SAndroid Build Coastguard Worker * The caps and ctrl transformations require some special handling,
940*2b949d04SAndroid Build Coastguard Worker * so we cannot simply use xkb_state_get_one_sym() for them.
941*2b949d04SAndroid Build Coastguard Worker * In particular, if Control is set, we must try very hard to find
942*2b949d04SAndroid Build Coastguard Worker * some layout in which the keysym is ASCII and thus can be (maybe)
943*2b949d04SAndroid Build Coastguard Worker * converted to a control character. libX11 allows to disable this
944*2b949d04SAndroid Build Coastguard Worker * behavior with the XkbLC_ControlFallback (see XkbSetXlibControls(3)),
945*2b949d04SAndroid Build Coastguard Worker * but it is enabled by default, yippee.
946*2b949d04SAndroid Build Coastguard Worker */
947*2b949d04SAndroid Build Coastguard Worker static xkb_keysym_t
get_one_sym_for_string(struct xkb_state * state,xkb_keycode_t kc)948*2b949d04SAndroid Build Coastguard Worker get_one_sym_for_string(struct xkb_state *state, xkb_keycode_t kc)
949*2b949d04SAndroid Build Coastguard Worker {
950*2b949d04SAndroid Build Coastguard Worker xkb_level_index_t level;
951*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t layout, num_layouts;
952*2b949d04SAndroid Build Coastguard Worker const xkb_keysym_t *syms;
953*2b949d04SAndroid Build Coastguard Worker int nsyms;
954*2b949d04SAndroid Build Coastguard Worker xkb_keysym_t sym;
955*2b949d04SAndroid Build Coastguard Worker
956*2b949d04SAndroid Build Coastguard Worker layout = xkb_state_key_get_layout(state, kc);
957*2b949d04SAndroid Build Coastguard Worker num_layouts = xkb_keymap_num_layouts_for_key(state->keymap, kc);
958*2b949d04SAndroid Build Coastguard Worker level = xkb_state_key_get_level(state, kc, layout);
959*2b949d04SAndroid Build Coastguard Worker if (layout == XKB_LAYOUT_INVALID || num_layouts == 0 ||
960*2b949d04SAndroid Build Coastguard Worker level == XKB_LEVEL_INVALID)
961*2b949d04SAndroid Build Coastguard Worker return XKB_KEY_NoSymbol;
962*2b949d04SAndroid Build Coastguard Worker
963*2b949d04SAndroid Build Coastguard Worker nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
964*2b949d04SAndroid Build Coastguard Worker layout, level, &syms);
965*2b949d04SAndroid Build Coastguard Worker if (nsyms != 1)
966*2b949d04SAndroid Build Coastguard Worker return XKB_KEY_NoSymbol;
967*2b949d04SAndroid Build Coastguard Worker sym = syms[0];
968*2b949d04SAndroid Build Coastguard Worker
969*2b949d04SAndroid Build Coastguard Worker if (should_do_ctrl_transformation(state, kc) && sym > 127u) {
970*2b949d04SAndroid Build Coastguard Worker for (xkb_layout_index_t i = 0; i < num_layouts; i++) {
971*2b949d04SAndroid Build Coastguard Worker level = xkb_state_key_get_level(state, kc, i);
972*2b949d04SAndroid Build Coastguard Worker if (level == XKB_LEVEL_INVALID)
973*2b949d04SAndroid Build Coastguard Worker continue;
974*2b949d04SAndroid Build Coastguard Worker
975*2b949d04SAndroid Build Coastguard Worker nsyms = xkb_keymap_key_get_syms_by_level(state->keymap, kc,
976*2b949d04SAndroid Build Coastguard Worker i, level, &syms);
977*2b949d04SAndroid Build Coastguard Worker if (nsyms == 1 && syms[0] <= 127u) {
978*2b949d04SAndroid Build Coastguard Worker sym = syms[0];
979*2b949d04SAndroid Build Coastguard Worker break;
980*2b949d04SAndroid Build Coastguard Worker }
981*2b949d04SAndroid Build Coastguard Worker }
982*2b949d04SAndroid Build Coastguard Worker }
983*2b949d04SAndroid Build Coastguard Worker
984*2b949d04SAndroid Build Coastguard Worker if (should_do_caps_transformation(state, kc)) {
985*2b949d04SAndroid Build Coastguard Worker sym = xkb_keysym_to_upper(sym);
986*2b949d04SAndroid Build Coastguard Worker }
987*2b949d04SAndroid Build Coastguard Worker
988*2b949d04SAndroid Build Coastguard Worker return sym;
989*2b949d04SAndroid Build Coastguard Worker }
990*2b949d04SAndroid Build Coastguard Worker
991*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_key_get_utf8(struct xkb_state * state,xkb_keycode_t kc,char * buffer,size_t size)992*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_utf8(struct xkb_state *state, xkb_keycode_t kc,
993*2b949d04SAndroid Build Coastguard Worker char *buffer, size_t size)
994*2b949d04SAndroid Build Coastguard Worker {
995*2b949d04SAndroid Build Coastguard Worker xkb_keysym_t sym;
996*2b949d04SAndroid Build Coastguard Worker const xkb_keysym_t *syms;
997*2b949d04SAndroid Build Coastguard Worker int nsyms;
998*2b949d04SAndroid Build Coastguard Worker int offset;
999*2b949d04SAndroid Build Coastguard Worker char tmp[7];
1000*2b949d04SAndroid Build Coastguard Worker
1001*2b949d04SAndroid Build Coastguard Worker sym = get_one_sym_for_string(state, kc);
1002*2b949d04SAndroid Build Coastguard Worker if (sym != XKB_KEY_NoSymbol) {
1003*2b949d04SAndroid Build Coastguard Worker nsyms = 1; syms = &sym;
1004*2b949d04SAndroid Build Coastguard Worker }
1005*2b949d04SAndroid Build Coastguard Worker else {
1006*2b949d04SAndroid Build Coastguard Worker nsyms = xkb_state_key_get_syms(state, kc, &syms);
1007*2b949d04SAndroid Build Coastguard Worker }
1008*2b949d04SAndroid Build Coastguard Worker
1009*2b949d04SAndroid Build Coastguard Worker /* Make sure not to truncate in the middle of a UTF-8 sequence. */
1010*2b949d04SAndroid Build Coastguard Worker offset = 0;
1011*2b949d04SAndroid Build Coastguard Worker for (int i = 0; i < nsyms; i++) {
1012*2b949d04SAndroid Build Coastguard Worker int ret = xkb_keysym_to_utf8(syms[i], tmp, sizeof(tmp));
1013*2b949d04SAndroid Build Coastguard Worker if (ret <= 0)
1014*2b949d04SAndroid Build Coastguard Worker goto err_bad;
1015*2b949d04SAndroid Build Coastguard Worker
1016*2b949d04SAndroid Build Coastguard Worker ret--;
1017*2b949d04SAndroid Build Coastguard Worker if ((size_t) (offset + ret) <= size)
1018*2b949d04SAndroid Build Coastguard Worker memcpy(buffer + offset, tmp, ret);
1019*2b949d04SAndroid Build Coastguard Worker offset += ret;
1020*2b949d04SAndroid Build Coastguard Worker }
1021*2b949d04SAndroid Build Coastguard Worker
1022*2b949d04SAndroid Build Coastguard Worker if ((size_t) offset >= size)
1023*2b949d04SAndroid Build Coastguard Worker goto err_trunc;
1024*2b949d04SAndroid Build Coastguard Worker buffer[offset] = '\0';
1025*2b949d04SAndroid Build Coastguard Worker
1026*2b949d04SAndroid Build Coastguard Worker if (!is_valid_utf8(buffer, offset))
1027*2b949d04SAndroid Build Coastguard Worker goto err_bad;
1028*2b949d04SAndroid Build Coastguard Worker
1029*2b949d04SAndroid Build Coastguard Worker if (offset == 1 && (unsigned int) buffer[0] <= 127u &&
1030*2b949d04SAndroid Build Coastguard Worker should_do_ctrl_transformation(state, kc))
1031*2b949d04SAndroid Build Coastguard Worker buffer[0] = XkbToControl(buffer[0]);
1032*2b949d04SAndroid Build Coastguard Worker
1033*2b949d04SAndroid Build Coastguard Worker return offset;
1034*2b949d04SAndroid Build Coastguard Worker
1035*2b949d04SAndroid Build Coastguard Worker err_trunc:
1036*2b949d04SAndroid Build Coastguard Worker if (size > 0)
1037*2b949d04SAndroid Build Coastguard Worker buffer[size - 1] = '\0';
1038*2b949d04SAndroid Build Coastguard Worker return offset;
1039*2b949d04SAndroid Build Coastguard Worker
1040*2b949d04SAndroid Build Coastguard Worker err_bad:
1041*2b949d04SAndroid Build Coastguard Worker if (size > 0)
1042*2b949d04SAndroid Build Coastguard Worker buffer[0] = '\0';
1043*2b949d04SAndroid Build Coastguard Worker return 0;
1044*2b949d04SAndroid Build Coastguard Worker }
1045*2b949d04SAndroid Build Coastguard Worker
1046*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT uint32_t
xkb_state_key_get_utf32(struct xkb_state * state,xkb_keycode_t kc)1047*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_utf32(struct xkb_state *state, xkb_keycode_t kc)
1048*2b949d04SAndroid Build Coastguard Worker {
1049*2b949d04SAndroid Build Coastguard Worker xkb_keysym_t sym;
1050*2b949d04SAndroid Build Coastguard Worker uint32_t cp;
1051*2b949d04SAndroid Build Coastguard Worker
1052*2b949d04SAndroid Build Coastguard Worker sym = get_one_sym_for_string(state, kc);
1053*2b949d04SAndroid Build Coastguard Worker cp = xkb_keysym_to_utf32(sym);
1054*2b949d04SAndroid Build Coastguard Worker
1055*2b949d04SAndroid Build Coastguard Worker if (cp <= 127u && should_do_ctrl_transformation(state, kc))
1056*2b949d04SAndroid Build Coastguard Worker cp = (uint32_t) XkbToControl((char) cp);
1057*2b949d04SAndroid Build Coastguard Worker
1058*2b949d04SAndroid Build Coastguard Worker return cp;
1059*2b949d04SAndroid Build Coastguard Worker }
1060*2b949d04SAndroid Build Coastguard Worker
1061*2b949d04SAndroid Build Coastguard Worker /**
1062*2b949d04SAndroid Build Coastguard Worker * Serialises the requested modifier state into an xkb_mod_mask_t, with all
1063*2b949d04SAndroid Build Coastguard Worker * the same disclaimers as in xkb_state_update_mask.
1064*2b949d04SAndroid Build Coastguard Worker */
1065*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_mod_mask_t
xkb_state_serialize_mods(struct xkb_state * state,enum xkb_state_component type)1066*2b949d04SAndroid Build Coastguard Worker xkb_state_serialize_mods(struct xkb_state *state,
1067*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type)
1068*2b949d04SAndroid Build Coastguard Worker {
1069*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t ret = 0;
1070*2b949d04SAndroid Build Coastguard Worker
1071*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_MODS_EFFECTIVE)
1072*2b949d04SAndroid Build Coastguard Worker return state->components.mods;
1073*2b949d04SAndroid Build Coastguard Worker
1074*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_MODS_DEPRESSED)
1075*2b949d04SAndroid Build Coastguard Worker ret |= state->components.base_mods;
1076*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_MODS_LATCHED)
1077*2b949d04SAndroid Build Coastguard Worker ret |= state->components.latched_mods;
1078*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_MODS_LOCKED)
1079*2b949d04SAndroid Build Coastguard Worker ret |= state->components.locked_mods;
1080*2b949d04SAndroid Build Coastguard Worker
1081*2b949d04SAndroid Build Coastguard Worker return ret;
1082*2b949d04SAndroid Build Coastguard Worker }
1083*2b949d04SAndroid Build Coastguard Worker
1084*2b949d04SAndroid Build Coastguard Worker /**
1085*2b949d04SAndroid Build Coastguard Worker * Serialises the requested group state, with all the same disclaimers as
1086*2b949d04SAndroid Build Coastguard Worker * in xkb_state_update_mask.
1087*2b949d04SAndroid Build Coastguard Worker */
1088*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_layout_index_t
xkb_state_serialize_layout(struct xkb_state * state,enum xkb_state_component type)1089*2b949d04SAndroid Build Coastguard Worker xkb_state_serialize_layout(struct xkb_state *state,
1090*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type)
1091*2b949d04SAndroid Build Coastguard Worker {
1092*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t ret = 0;
1093*2b949d04SAndroid Build Coastguard Worker
1094*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1095*2b949d04SAndroid Build Coastguard Worker return state->components.group;
1096*2b949d04SAndroid Build Coastguard Worker
1097*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_DEPRESSED)
1098*2b949d04SAndroid Build Coastguard Worker ret += state->components.base_group;
1099*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_LATCHED)
1100*2b949d04SAndroid Build Coastguard Worker ret += state->components.latched_group;
1101*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_LOCKED)
1102*2b949d04SAndroid Build Coastguard Worker ret += state->components.locked_group;
1103*2b949d04SAndroid Build Coastguard Worker
1104*2b949d04SAndroid Build Coastguard Worker return ret;
1105*2b949d04SAndroid Build Coastguard Worker }
1106*2b949d04SAndroid Build Coastguard Worker
1107*2b949d04SAndroid Build Coastguard Worker /**
1108*2b949d04SAndroid Build Coastguard Worker * Gets a modifier mask and returns the resolved effective mask; this
1109*2b949d04SAndroid Build Coastguard Worker * is needed because some modifiers can also map to other modifiers, e.g.
1110*2b949d04SAndroid Build Coastguard Worker * the "NumLock" modifier usually also sets the "Mod2" modifier.
1111*2b949d04SAndroid Build Coastguard Worker */
1112*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t
mod_mask_get_effective(struct xkb_keymap * keymap,xkb_mod_mask_t mods)1113*2b949d04SAndroid Build Coastguard Worker mod_mask_get_effective(struct xkb_keymap *keymap, xkb_mod_mask_t mods)
1114*2b949d04SAndroid Build Coastguard Worker {
1115*2b949d04SAndroid Build Coastguard Worker const struct xkb_mod *mod;
1116*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t i;
1117*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t mask;
1118*2b949d04SAndroid Build Coastguard Worker
1119*2b949d04SAndroid Build Coastguard Worker /* The effective mask is only real mods for now. */
1120*2b949d04SAndroid Build Coastguard Worker mask = mods & MOD_REAL_MASK_ALL;
1121*2b949d04SAndroid Build Coastguard Worker
1122*2b949d04SAndroid Build Coastguard Worker xkb_mods_enumerate(i, mod, &keymap->mods)
1123*2b949d04SAndroid Build Coastguard Worker if (mods & (1u << i))
1124*2b949d04SAndroid Build Coastguard Worker mask |= mod->mapping;
1125*2b949d04SAndroid Build Coastguard Worker
1126*2b949d04SAndroid Build Coastguard Worker return mask;
1127*2b949d04SAndroid Build Coastguard Worker }
1128*2b949d04SAndroid Build Coastguard Worker
1129*2b949d04SAndroid Build Coastguard Worker /**
1130*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the given modifier is active with the specified type(s), 0 if
1131*2b949d04SAndroid Build Coastguard Worker * not, or -1 if the modifier is invalid.
1132*2b949d04SAndroid Build Coastguard Worker */
1133*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_mod_index_is_active(struct xkb_state * state,xkb_mod_index_t idx,enum xkb_state_component type)1134*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_index_is_active(struct xkb_state *state,
1135*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t idx,
1136*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type)
1137*2b949d04SAndroid Build Coastguard Worker {
1138*2b949d04SAndroid Build Coastguard Worker if (idx >= xkb_keymap_num_mods(state->keymap))
1139*2b949d04SAndroid Build Coastguard Worker return -1;
1140*2b949d04SAndroid Build Coastguard Worker
1141*2b949d04SAndroid Build Coastguard Worker return !!(xkb_state_serialize_mods(state, type) & (1u << idx));
1142*2b949d04SAndroid Build Coastguard Worker }
1143*2b949d04SAndroid Build Coastguard Worker
1144*2b949d04SAndroid Build Coastguard Worker /**
1145*2b949d04SAndroid Build Coastguard Worker * Helper function for xkb_state_mod_indices_are_active and
1146*2b949d04SAndroid Build Coastguard Worker * xkb_state_mod_names_are_active.
1147*2b949d04SAndroid Build Coastguard Worker */
1148*2b949d04SAndroid Build Coastguard Worker static bool
match_mod_masks(struct xkb_state * state,enum xkb_state_component type,enum xkb_state_match match,xkb_mod_mask_t wanted)1149*2b949d04SAndroid Build Coastguard Worker match_mod_masks(struct xkb_state *state,
1150*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type,
1151*2b949d04SAndroid Build Coastguard Worker enum xkb_state_match match,
1152*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t wanted)
1153*2b949d04SAndroid Build Coastguard Worker {
1154*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t active = xkb_state_serialize_mods(state, type);
1155*2b949d04SAndroid Build Coastguard Worker
1156*2b949d04SAndroid Build Coastguard Worker if (!(match & XKB_STATE_MATCH_NON_EXCLUSIVE) && (active & ~wanted))
1157*2b949d04SAndroid Build Coastguard Worker return false;
1158*2b949d04SAndroid Build Coastguard Worker
1159*2b949d04SAndroid Build Coastguard Worker if (match & XKB_STATE_MATCH_ANY)
1160*2b949d04SAndroid Build Coastguard Worker return active & wanted;
1161*2b949d04SAndroid Build Coastguard Worker
1162*2b949d04SAndroid Build Coastguard Worker return (active & wanted) == wanted;
1163*2b949d04SAndroid Build Coastguard Worker }
1164*2b949d04SAndroid Build Coastguard Worker
1165*2b949d04SAndroid Build Coastguard Worker /**
1166*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the modifiers are active with the specified type(s), 0 if
1167*2b949d04SAndroid Build Coastguard Worker * not, or -1 if any of the modifiers are invalid.
1168*2b949d04SAndroid Build Coastguard Worker */
1169*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_mod_indices_are_active(struct xkb_state * state,enum xkb_state_component type,enum xkb_state_match match,...)1170*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_indices_are_active(struct xkb_state *state,
1171*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type,
1172*2b949d04SAndroid Build Coastguard Worker enum xkb_state_match match,
1173*2b949d04SAndroid Build Coastguard Worker ...)
1174*2b949d04SAndroid Build Coastguard Worker {
1175*2b949d04SAndroid Build Coastguard Worker va_list ap;
1176*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t wanted = 0;
1177*2b949d04SAndroid Build Coastguard Worker int ret = 0;
1178*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t num_mods = xkb_keymap_num_mods(state->keymap);
1179*2b949d04SAndroid Build Coastguard Worker
1180*2b949d04SAndroid Build Coastguard Worker va_start(ap, match);
1181*2b949d04SAndroid Build Coastguard Worker while (1) {
1182*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t idx = va_arg(ap, xkb_mod_index_t);
1183*2b949d04SAndroid Build Coastguard Worker if (idx == XKB_MOD_INVALID)
1184*2b949d04SAndroid Build Coastguard Worker break;
1185*2b949d04SAndroid Build Coastguard Worker if (idx >= num_mods) {
1186*2b949d04SAndroid Build Coastguard Worker ret = -1;
1187*2b949d04SAndroid Build Coastguard Worker break;
1188*2b949d04SAndroid Build Coastguard Worker }
1189*2b949d04SAndroid Build Coastguard Worker wanted |= (1u << idx);
1190*2b949d04SAndroid Build Coastguard Worker }
1191*2b949d04SAndroid Build Coastguard Worker va_end(ap);
1192*2b949d04SAndroid Build Coastguard Worker
1193*2b949d04SAndroid Build Coastguard Worker if (ret == -1)
1194*2b949d04SAndroid Build Coastguard Worker return ret;
1195*2b949d04SAndroid Build Coastguard Worker
1196*2b949d04SAndroid Build Coastguard Worker return match_mod_masks(state, type, match, wanted);
1197*2b949d04SAndroid Build Coastguard Worker }
1198*2b949d04SAndroid Build Coastguard Worker
1199*2b949d04SAndroid Build Coastguard Worker /**
1200*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the given modifier is active with the specified type(s), 0 if
1201*2b949d04SAndroid Build Coastguard Worker * not, or -1 if the modifier is invalid.
1202*2b949d04SAndroid Build Coastguard Worker */
1203*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_mod_name_is_active(struct xkb_state * state,const char * name,enum xkb_state_component type)1204*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_name_is_active(struct xkb_state *state, const char *name,
1205*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type)
1206*2b949d04SAndroid Build Coastguard Worker {
1207*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t idx = xkb_keymap_mod_get_index(state->keymap, name);
1208*2b949d04SAndroid Build Coastguard Worker
1209*2b949d04SAndroid Build Coastguard Worker if (idx == XKB_MOD_INVALID)
1210*2b949d04SAndroid Build Coastguard Worker return -1;
1211*2b949d04SAndroid Build Coastguard Worker
1212*2b949d04SAndroid Build Coastguard Worker return xkb_state_mod_index_is_active(state, idx, type);
1213*2b949d04SAndroid Build Coastguard Worker }
1214*2b949d04SAndroid Build Coastguard Worker
1215*2b949d04SAndroid Build Coastguard Worker /**
1216*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the modifiers are active with the specified type(s), 0 if
1217*2b949d04SAndroid Build Coastguard Worker * not, or -1 if any of the modifiers are invalid.
1218*2b949d04SAndroid Build Coastguard Worker */
1219*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT ATTR_NULL_SENTINEL int
xkb_state_mod_names_are_active(struct xkb_state * state,enum xkb_state_component type,enum xkb_state_match match,...)1220*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_names_are_active(struct xkb_state *state,
1221*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type,
1222*2b949d04SAndroid Build Coastguard Worker enum xkb_state_match match,
1223*2b949d04SAndroid Build Coastguard Worker ...)
1224*2b949d04SAndroid Build Coastguard Worker {
1225*2b949d04SAndroid Build Coastguard Worker va_list ap;
1226*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t wanted = 0;
1227*2b949d04SAndroid Build Coastguard Worker int ret = 0;
1228*2b949d04SAndroid Build Coastguard Worker
1229*2b949d04SAndroid Build Coastguard Worker va_start(ap, match);
1230*2b949d04SAndroid Build Coastguard Worker while (1) {
1231*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t idx;
1232*2b949d04SAndroid Build Coastguard Worker const char *str = va_arg(ap, const char *);
1233*2b949d04SAndroid Build Coastguard Worker if (str == NULL)
1234*2b949d04SAndroid Build Coastguard Worker break;
1235*2b949d04SAndroid Build Coastguard Worker idx = xkb_keymap_mod_get_index(state->keymap, str);
1236*2b949d04SAndroid Build Coastguard Worker if (idx == XKB_MOD_INVALID) {
1237*2b949d04SAndroid Build Coastguard Worker ret = -1;
1238*2b949d04SAndroid Build Coastguard Worker break;
1239*2b949d04SAndroid Build Coastguard Worker }
1240*2b949d04SAndroid Build Coastguard Worker wanted |= (1u << idx);
1241*2b949d04SAndroid Build Coastguard Worker }
1242*2b949d04SAndroid Build Coastguard Worker va_end(ap);
1243*2b949d04SAndroid Build Coastguard Worker
1244*2b949d04SAndroid Build Coastguard Worker if (ret == -1)
1245*2b949d04SAndroid Build Coastguard Worker return ret;
1246*2b949d04SAndroid Build Coastguard Worker
1247*2b949d04SAndroid Build Coastguard Worker return match_mod_masks(state, type, match, wanted);
1248*2b949d04SAndroid Build Coastguard Worker }
1249*2b949d04SAndroid Build Coastguard Worker
1250*2b949d04SAndroid Build Coastguard Worker /**
1251*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the given group is active with the specified type(s), 0 if
1252*2b949d04SAndroid Build Coastguard Worker * not, or -1 if the group is invalid.
1253*2b949d04SAndroid Build Coastguard Worker */
1254*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_layout_index_is_active(struct xkb_state * state,xkb_layout_index_t idx,enum xkb_state_component type)1255*2b949d04SAndroid Build Coastguard Worker xkb_state_layout_index_is_active(struct xkb_state *state,
1256*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t idx,
1257*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type)
1258*2b949d04SAndroid Build Coastguard Worker {
1259*2b949d04SAndroid Build Coastguard Worker int ret = 0;
1260*2b949d04SAndroid Build Coastguard Worker
1261*2b949d04SAndroid Build Coastguard Worker if (idx >= state->keymap->num_groups)
1262*2b949d04SAndroid Build Coastguard Worker return -1;
1263*2b949d04SAndroid Build Coastguard Worker
1264*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_EFFECTIVE)
1265*2b949d04SAndroid Build Coastguard Worker ret |= (state->components.group == idx);
1266*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_DEPRESSED)
1267*2b949d04SAndroid Build Coastguard Worker ret |= (state->components.base_group == (int32_t) idx);
1268*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_LATCHED)
1269*2b949d04SAndroid Build Coastguard Worker ret |= (state->components.latched_group == (int32_t) idx);
1270*2b949d04SAndroid Build Coastguard Worker if (type & XKB_STATE_LAYOUT_LOCKED)
1271*2b949d04SAndroid Build Coastguard Worker ret |= (state->components.locked_group == (int32_t) idx);
1272*2b949d04SAndroid Build Coastguard Worker
1273*2b949d04SAndroid Build Coastguard Worker return ret;
1274*2b949d04SAndroid Build Coastguard Worker }
1275*2b949d04SAndroid Build Coastguard Worker
1276*2b949d04SAndroid Build Coastguard Worker /**
1277*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the given modifier is active with the specified type(s), 0 if
1278*2b949d04SAndroid Build Coastguard Worker * not, or -1 if the modifier is invalid.
1279*2b949d04SAndroid Build Coastguard Worker */
1280*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_layout_name_is_active(struct xkb_state * state,const char * name,enum xkb_state_component type)1281*2b949d04SAndroid Build Coastguard Worker xkb_state_layout_name_is_active(struct xkb_state *state, const char *name,
1282*2b949d04SAndroid Build Coastguard Worker enum xkb_state_component type)
1283*2b949d04SAndroid Build Coastguard Worker {
1284*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t idx = xkb_keymap_layout_get_index(state->keymap, name);
1285*2b949d04SAndroid Build Coastguard Worker
1286*2b949d04SAndroid Build Coastguard Worker if (idx == XKB_LAYOUT_INVALID)
1287*2b949d04SAndroid Build Coastguard Worker return -1;
1288*2b949d04SAndroid Build Coastguard Worker
1289*2b949d04SAndroid Build Coastguard Worker return xkb_state_layout_index_is_active(state, idx, type);
1290*2b949d04SAndroid Build Coastguard Worker }
1291*2b949d04SAndroid Build Coastguard Worker
1292*2b949d04SAndroid Build Coastguard Worker /**
1293*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1294*2b949d04SAndroid Build Coastguard Worker */
1295*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_led_index_is_active(struct xkb_state * state,xkb_led_index_t idx)1296*2b949d04SAndroid Build Coastguard Worker xkb_state_led_index_is_active(struct xkb_state *state, xkb_led_index_t idx)
1297*2b949d04SAndroid Build Coastguard Worker {
1298*2b949d04SAndroid Build Coastguard Worker if (idx >= state->keymap->num_leds ||
1299*2b949d04SAndroid Build Coastguard Worker state->keymap->leds[idx].name == XKB_ATOM_NONE)
1300*2b949d04SAndroid Build Coastguard Worker return -1;
1301*2b949d04SAndroid Build Coastguard Worker
1302*2b949d04SAndroid Build Coastguard Worker return !!(state->components.leds & (1u << idx));
1303*2b949d04SAndroid Build Coastguard Worker }
1304*2b949d04SAndroid Build Coastguard Worker
1305*2b949d04SAndroid Build Coastguard Worker /**
1306*2b949d04SAndroid Build Coastguard Worker * Returns 1 if the given LED is active, 0 if not, or -1 if the LED is invalid.
1307*2b949d04SAndroid Build Coastguard Worker */
1308*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_led_name_is_active(struct xkb_state * state,const char * name)1309*2b949d04SAndroid Build Coastguard Worker xkb_state_led_name_is_active(struct xkb_state *state, const char *name)
1310*2b949d04SAndroid Build Coastguard Worker {
1311*2b949d04SAndroid Build Coastguard Worker xkb_led_index_t idx = xkb_keymap_led_get_index(state->keymap, name);
1312*2b949d04SAndroid Build Coastguard Worker
1313*2b949d04SAndroid Build Coastguard Worker if (idx == XKB_LED_INVALID)
1314*2b949d04SAndroid Build Coastguard Worker return -1;
1315*2b949d04SAndroid Build Coastguard Worker
1316*2b949d04SAndroid Build Coastguard Worker return xkb_state_led_index_is_active(state, idx);
1317*2b949d04SAndroid Build Coastguard Worker }
1318*2b949d04SAndroid Build Coastguard Worker
1319*2b949d04SAndroid Build Coastguard Worker /**
1320*2b949d04SAndroid Build Coastguard Worker * See:
1321*2b949d04SAndroid Build Coastguard Worker * - XkbTranslateKeyCode(3), mod_rtrn return value, from libX11.
1322*2b949d04SAndroid Build Coastguard Worker * - MyEnhancedXkbTranslateKeyCode(), a modification of the above, from GTK+.
1323*2b949d04SAndroid Build Coastguard Worker */
1324*2b949d04SAndroid Build Coastguard Worker static xkb_mod_mask_t
key_get_consumed(struct xkb_state * state,const struct xkb_key * key,enum xkb_consumed_mode mode)1325*2b949d04SAndroid Build Coastguard Worker key_get_consumed(struct xkb_state *state, const struct xkb_key *key,
1326*2b949d04SAndroid Build Coastguard Worker enum xkb_consumed_mode mode)
1327*2b949d04SAndroid Build Coastguard Worker {
1328*2b949d04SAndroid Build Coastguard Worker const struct xkb_key_type *type;
1329*2b949d04SAndroid Build Coastguard Worker const struct xkb_key_type_entry *matching_entry;
1330*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t preserve = 0;
1331*2b949d04SAndroid Build Coastguard Worker xkb_layout_index_t group;
1332*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t consumed = 0;
1333*2b949d04SAndroid Build Coastguard Worker
1334*2b949d04SAndroid Build Coastguard Worker group = xkb_state_key_get_layout(state, key->keycode);
1335*2b949d04SAndroid Build Coastguard Worker if (group == XKB_LAYOUT_INVALID)
1336*2b949d04SAndroid Build Coastguard Worker return 0;
1337*2b949d04SAndroid Build Coastguard Worker
1338*2b949d04SAndroid Build Coastguard Worker type = key->groups[group].type;
1339*2b949d04SAndroid Build Coastguard Worker
1340*2b949d04SAndroid Build Coastguard Worker matching_entry = get_entry_for_key_state(state, key, group);
1341*2b949d04SAndroid Build Coastguard Worker if (matching_entry)
1342*2b949d04SAndroid Build Coastguard Worker preserve = matching_entry->preserve.mask;
1343*2b949d04SAndroid Build Coastguard Worker
1344*2b949d04SAndroid Build Coastguard Worker switch (mode) {
1345*2b949d04SAndroid Build Coastguard Worker case XKB_CONSUMED_MODE_XKB:
1346*2b949d04SAndroid Build Coastguard Worker consumed = type->mods.mask;
1347*2b949d04SAndroid Build Coastguard Worker break;
1348*2b949d04SAndroid Build Coastguard Worker
1349*2b949d04SAndroid Build Coastguard Worker case XKB_CONSUMED_MODE_GTK: {
1350*2b949d04SAndroid Build Coastguard Worker const struct xkb_key_type_entry *no_mods_entry;
1351*2b949d04SAndroid Build Coastguard Worker xkb_level_index_t no_mods_leveli;
1352*2b949d04SAndroid Build Coastguard Worker const struct xkb_level *no_mods_level, *level;
1353*2b949d04SAndroid Build Coastguard Worker
1354*2b949d04SAndroid Build Coastguard Worker no_mods_entry = get_entry_for_mods(type, 0);
1355*2b949d04SAndroid Build Coastguard Worker no_mods_leveli = no_mods_entry ? no_mods_entry->level : 0;
1356*2b949d04SAndroid Build Coastguard Worker no_mods_level = &key->groups[group].levels[no_mods_leveli];
1357*2b949d04SAndroid Build Coastguard Worker
1358*2b949d04SAndroid Build Coastguard Worker for (unsigned i = 0; i < type->num_entries; i++) {
1359*2b949d04SAndroid Build Coastguard Worker const struct xkb_key_type_entry *entry = &type->entries[i];
1360*2b949d04SAndroid Build Coastguard Worker if (!entry_is_active(entry))
1361*2b949d04SAndroid Build Coastguard Worker continue;
1362*2b949d04SAndroid Build Coastguard Worker
1363*2b949d04SAndroid Build Coastguard Worker level = &key->groups[group].levels[entry->level];
1364*2b949d04SAndroid Build Coastguard Worker if (XkbLevelsSameSyms(level, no_mods_level))
1365*2b949d04SAndroid Build Coastguard Worker continue;
1366*2b949d04SAndroid Build Coastguard Worker
1367*2b949d04SAndroid Build Coastguard Worker if (entry == matching_entry || one_bit_set(entry->mods.mask))
1368*2b949d04SAndroid Build Coastguard Worker consumed |= entry->mods.mask & ~entry->preserve.mask;
1369*2b949d04SAndroid Build Coastguard Worker }
1370*2b949d04SAndroid Build Coastguard Worker break;
1371*2b949d04SAndroid Build Coastguard Worker }
1372*2b949d04SAndroid Build Coastguard Worker }
1373*2b949d04SAndroid Build Coastguard Worker
1374*2b949d04SAndroid Build Coastguard Worker return consumed & ~preserve;
1375*2b949d04SAndroid Build Coastguard Worker }
1376*2b949d04SAndroid Build Coastguard Worker
1377*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_mod_index_is_consumed2(struct xkb_state * state,xkb_keycode_t kc,xkb_mod_index_t idx,enum xkb_consumed_mode mode)1378*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_index_is_consumed2(struct xkb_state *state, xkb_keycode_t kc,
1379*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t idx,
1380*2b949d04SAndroid Build Coastguard Worker enum xkb_consumed_mode mode)
1381*2b949d04SAndroid Build Coastguard Worker {
1382*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key = XkbKey(state->keymap, kc);
1383*2b949d04SAndroid Build Coastguard Worker
1384*2b949d04SAndroid Build Coastguard Worker if (!key || idx >= xkb_keymap_num_mods(state->keymap))
1385*2b949d04SAndroid Build Coastguard Worker return -1;
1386*2b949d04SAndroid Build Coastguard Worker
1387*2b949d04SAndroid Build Coastguard Worker return !!((1u << idx) & key_get_consumed(state, key, mode));
1388*2b949d04SAndroid Build Coastguard Worker }
1389*2b949d04SAndroid Build Coastguard Worker
1390*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT int
xkb_state_mod_index_is_consumed(struct xkb_state * state,xkb_keycode_t kc,xkb_mod_index_t idx)1391*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_index_is_consumed(struct xkb_state *state, xkb_keycode_t kc,
1392*2b949d04SAndroid Build Coastguard Worker xkb_mod_index_t idx)
1393*2b949d04SAndroid Build Coastguard Worker {
1394*2b949d04SAndroid Build Coastguard Worker return xkb_state_mod_index_is_consumed2(state, kc, idx,
1395*2b949d04SAndroid Build Coastguard Worker XKB_CONSUMED_MODE_XKB);
1396*2b949d04SAndroid Build Coastguard Worker }
1397*2b949d04SAndroid Build Coastguard Worker
1398*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_mod_mask_t
xkb_state_mod_mask_remove_consumed(struct xkb_state * state,xkb_keycode_t kc,xkb_mod_mask_t mask)1399*2b949d04SAndroid Build Coastguard Worker xkb_state_mod_mask_remove_consumed(struct xkb_state *state, xkb_keycode_t kc,
1400*2b949d04SAndroid Build Coastguard Worker xkb_mod_mask_t mask)
1401*2b949d04SAndroid Build Coastguard Worker {
1402*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key = XkbKey(state->keymap, kc);
1403*2b949d04SAndroid Build Coastguard Worker
1404*2b949d04SAndroid Build Coastguard Worker if (!key)
1405*2b949d04SAndroid Build Coastguard Worker return 0;
1406*2b949d04SAndroid Build Coastguard Worker
1407*2b949d04SAndroid Build Coastguard Worker return mask & ~key_get_consumed(state, key, XKB_CONSUMED_MODE_XKB);
1408*2b949d04SAndroid Build Coastguard Worker }
1409*2b949d04SAndroid Build Coastguard Worker
1410*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_mod_mask_t
xkb_state_key_get_consumed_mods2(struct xkb_state * state,xkb_keycode_t kc,enum xkb_consumed_mode mode)1411*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_consumed_mods2(struct xkb_state *state, xkb_keycode_t kc,
1412*2b949d04SAndroid Build Coastguard Worker enum xkb_consumed_mode mode)
1413*2b949d04SAndroid Build Coastguard Worker {
1414*2b949d04SAndroid Build Coastguard Worker const struct xkb_key *key;
1415*2b949d04SAndroid Build Coastguard Worker
1416*2b949d04SAndroid Build Coastguard Worker switch (mode) {
1417*2b949d04SAndroid Build Coastguard Worker case XKB_CONSUMED_MODE_XKB:
1418*2b949d04SAndroid Build Coastguard Worker case XKB_CONSUMED_MODE_GTK:
1419*2b949d04SAndroid Build Coastguard Worker break;
1420*2b949d04SAndroid Build Coastguard Worker default:
1421*2b949d04SAndroid Build Coastguard Worker log_err_func(state->keymap->ctx,
1422*2b949d04SAndroid Build Coastguard Worker "unrecognized consumed modifiers mode: %d\n", mode);
1423*2b949d04SAndroid Build Coastguard Worker return 0;
1424*2b949d04SAndroid Build Coastguard Worker }
1425*2b949d04SAndroid Build Coastguard Worker
1426*2b949d04SAndroid Build Coastguard Worker key = XkbKey(state->keymap, kc);
1427*2b949d04SAndroid Build Coastguard Worker if (!key)
1428*2b949d04SAndroid Build Coastguard Worker return 0;
1429*2b949d04SAndroid Build Coastguard Worker
1430*2b949d04SAndroid Build Coastguard Worker return key_get_consumed(state, key, mode);
1431*2b949d04SAndroid Build Coastguard Worker }
1432*2b949d04SAndroid Build Coastguard Worker
1433*2b949d04SAndroid Build Coastguard Worker XKB_EXPORT xkb_mod_mask_t
xkb_state_key_get_consumed_mods(struct xkb_state * state,xkb_keycode_t kc)1434*2b949d04SAndroid Build Coastguard Worker xkb_state_key_get_consumed_mods(struct xkb_state *state, xkb_keycode_t kc)
1435*2b949d04SAndroid Build Coastguard Worker {
1436*2b949d04SAndroid Build Coastguard Worker return xkb_state_key_get_consumed_mods2(state, kc, XKB_CONSUMED_MODE_XKB);
1437*2b949d04SAndroid Build Coastguard Worker }
1438