Remove the XKB_NUM_VIRTUAL_MODIFIERS limit
[platform/upstream/libxkbcommon.git] / src / xkbcomp / keymap.c
1 /*
2  * Copyright © 2009 Dan Nicholson
3  * Copyright © 2012 Intel Corporation
4  * Copyright © 2012 Ran Benita <ran234@gmail.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  *
25  * Author: Dan Nicholson <dbn.lists@gmail.com>
26  *         Daniel Stone <daniel@fooishbar.org>
27  *         Ran Benita <ran234@gmail.com>
28  */
29
30 #include "xkbcomp-priv.h"
31
32 static void
33 ComputeEffectiveMask(struct xkb_keymap *keymap, struct xkb_mods *mods)
34 {
35     const struct xkb_vmod *vmod;
36     xkb_mod_index_t i;
37     xkb_mod_mask_t vmask = mods->mods >> XKB_NUM_CORE_MODS;
38
39     /* The effective mask is only real mods for now. */
40     mods->mask = mods->mods & 0xff;
41
42     darray_enumerate(i, vmod, keymap->vmods)
43         if (vmask & (1 << i))
44             mods->mask |= vmod->mapping;
45 }
46
47 static void
48 UpdateActionMods(struct xkb_keymap *keymap, union xkb_action *act,
49                  xkb_mod_mask_t modmap)
50 {
51     switch (act->type) {
52     case ACTION_TYPE_MOD_SET:
53     case ACTION_TYPE_MOD_LATCH:
54     case ACTION_TYPE_MOD_LOCK:
55         if (act->mods.flags & ACTION_MODS_LOOKUP_MODMAP)
56             act->mods.mods.mods = modmap;
57         ComputeEffectiveMask(keymap, &act->mods.mods);
58         break;
59     default:
60         break;
61     }
62 }
63
64 static const struct xkb_sym_interpret default_interpret = {
65     .sym = XKB_KEY_NoSymbol,
66     .repeat = true,
67     .match = MATCH_ANY_OR_NONE,
68     .mods = 0,
69     .virtual_mod = XKB_MOD_INVALID,
70     .act = { .type = ACTION_TYPE_NONE },
71 };
72
73 /**
74  * Find an interpretation which applies to this particular level, either by
75  * finding an exact match for the symbol and modifier combination, or a
76  * generic XKB_KEY_NoSymbol match.
77  */
78 static const struct xkb_sym_interpret *
79 FindInterpForKey(struct xkb_keymap *keymap, const struct xkb_key *key,
80                  xkb_layout_index_t group, xkb_level_index_t level)
81 {
82     struct xkb_sym_interpret *interp;
83     const xkb_keysym_t *syms;
84     int num_syms;
85
86     num_syms = xkb_keymap_key_get_syms_by_level(keymap, key->keycode, group,
87                                                 level, &syms);
88     if (num_syms == 0)
89         return NULL;
90
91     /*
92      * There may be multiple matchings interprets; we should always return
93      * the most specific. Here we rely on compat.c to set up the
94      * sym_interpret array from the most specific to the least specific,
95      * such that when we find a match we return immediately.
96      */
97     darray_foreach(interp, keymap->sym_interpret) {
98         xkb_mod_mask_t mods;
99         bool found;
100
101         if ((num_syms > 1 || interp->sym != syms[0]) &&
102             interp->sym != XKB_KEY_NoSymbol)
103             continue;
104
105         if (level == 0 || !(interp->match & MATCH_LEVEL_ONE_ONLY))
106             mods = key->modmap;
107         else
108             mods = 0;
109
110         switch (interp->match & MATCH_OP_MASK) {
111         case MATCH_NONE:
112             found = !(interp->mods & mods);
113             break;
114         case MATCH_ANY_OR_NONE:
115             found = (!mods || (interp->mods & mods));
116             break;
117         case MATCH_ANY:
118             found = !!(interp->mods & mods);
119             break;
120         case MATCH_ALL:
121             found = ((interp->mods & mods) == interp->mods);
122             break;
123         case MATCH_EXACTLY:
124             found = (interp->mods == mods);
125             break;
126         default:
127             found = false;
128             break;
129         }
130
131         if (found)
132             return interp;
133     }
134
135     return &default_interpret;
136 }
137
138 static bool
139 ApplyInterpsToKey(struct xkb_keymap *keymap, struct xkb_key *key)
140 {
141     xkb_mod_mask_t vmodmask = 0;
142     xkb_layout_index_t group;
143     xkb_level_index_t level;
144
145     /* If we've been told not to bind interps to this key, then don't. */
146     if (key->explicit & EXPLICIT_INTERP)
147         return true;
148
149     for (group = 0; group < key->num_groups; group++) {
150         for (level = 0; level < XkbKeyGroupWidth(key, group); level++) {
151             const struct xkb_sym_interpret *interp;
152
153             interp = FindInterpForKey(keymap, key, group, level);
154             if (!interp)
155                 continue;
156
157             /* Infer default key behaviours from the base level. */
158             if (group == 0 && level == 0)
159                 if (!(key->explicit & EXPLICIT_REPEAT) && interp->repeat)
160                     key->repeats = true;
161
162             if ((group == 0 && level == 0) ||
163                 !(interp->match & MATCH_LEVEL_ONE_ONLY)) {
164                 if (interp->virtual_mod != XKB_MOD_INVALID)
165                     vmodmask |= (1 << interp->virtual_mod);
166             }
167
168             if (interp->act.type != ACTION_TYPE_NONE)
169                 key->groups[group].levels[level].action = interp->act;
170         }
171     }
172
173     if (!(key->explicit & EXPLICIT_VMODMAP))
174         key->vmodmap = vmodmask;
175
176     return true;
177 }
178
179 /**
180  * This collects a bunch of disparate functions which was done in the server
181  * at various points that really should've been done within xkbcomp.  Turns out
182  * your actions and types are a lot more useful when any of your modifiers
183  * other than Shift actually do something ...
184  */
185 static bool
186 UpdateDerivedKeymapFields(struct xkb_keymap *keymap)
187 {
188     struct xkb_vmod *vmod;
189     xkb_led_index_t led;
190     unsigned int i, j;
191     struct xkb_key *key;
192
193     /* Find all the interprets for the key and bind them to actions,
194      * which will also update the vmodmap. */
195     xkb_foreach_key(key, keymap)
196         if (!ApplyInterpsToKey(keymap, key))
197             return false;
198
199     /* Update keymap->vmods, the virtual -> real mod mapping. */
200     xkb_foreach_key(key, keymap)
201         darray_enumerate(i, vmod, keymap->vmods)
202             if (key->vmodmap & (1 << i))
203                 vmod->mapping |= key->modmap;
204
205     /* Now update the level masks for all the types to reflect the vmods. */
206     for (i = 0; i < keymap->num_types; i++) {
207         ComputeEffectiveMask(keymap, &keymap->types[i].mods);
208
209         for (j = 0; j < keymap->types[i].num_entries; j++) {
210             ComputeEffectiveMask(keymap, &keymap->types[i].map[j].mods);
211             ComputeEffectiveMask(keymap, &keymap->types[i].map[j].preserve);
212         }
213     }
214
215     /* Update action modifiers. */
216     xkb_foreach_key(key, keymap)
217         for (i = 0; i < key->num_groups; i++)
218             for (j = 0; j < XkbKeyGroupWidth(key, i); j++)
219                 UpdateActionMods(keymap, &key->groups[i].levels[j].action,
220                                  key->modmap);
221
222     /* Update vmod -> indicator maps. */
223     for (led = 0; led < XKB_NUM_INDICATORS; led++)
224         ComputeEffectiveMask(keymap, &keymap->indicators[led].mods);
225
226     /* Find maximum number of groups out of all keys in the keymap. */
227     xkb_foreach_key(key, keymap)
228         keymap->num_groups = MAX(keymap->num_groups, key->num_groups);
229
230     return true;
231 }
232
233 typedef bool (*compile_file_fn)(XkbFile *file,
234                                 struct xkb_keymap *keymap,
235                                 enum merge_mode merge);
236
237 static const compile_file_fn compile_file_fns[LAST_KEYMAP_FILE_TYPE + 1] = {
238     [FILE_TYPE_KEYCODES] = CompileKeycodes,
239     [FILE_TYPE_TYPES] = CompileKeyTypes,
240     [FILE_TYPE_COMPAT] = CompileCompatMap,
241     [FILE_TYPE_SYMBOLS] = CompileSymbols,
242 };
243
244 bool
245 CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, enum merge_mode merge)
246 {
247     bool ok;
248     const char *main_name;
249     XkbFile *files[LAST_KEYMAP_FILE_TYPE + 1] = { NULL };
250     enum xkb_file_type type;
251     struct xkb_context *ctx = keymap->ctx;
252
253     main_name = file->name ? file->name : "(unnamed)";
254
255     /* Collect section files and check for duplicates. */
256     for (file = (XkbFile *) file->defs; file;
257          file = (XkbFile *) file->common.next) {
258         if (file->file_type < FIRST_KEYMAP_FILE_TYPE ||
259             file->file_type > LAST_KEYMAP_FILE_TYPE) {
260             log_err(ctx, "Cannot define %s in a keymap file\n",
261                     xkb_file_type_to_string(file->file_type));
262             continue;
263         }
264
265         if (files[file->file_type]) {
266             log_err(ctx,
267                     "More than one %s section in keymap file; "
268                     "All sections after the first ignored\n",
269                     xkb_file_type_to_string(file->file_type));
270             continue;
271         }
272
273         if (!file->topName) {
274             free(file->topName);
275             file->topName = strdup(main_name);
276         }
277
278         files[file->file_type] = file;
279     }
280
281     /*
282      * Check that all required section were provided.
283      * Report everything before failing.
284      */
285     ok = true;
286     for (type = FIRST_KEYMAP_FILE_TYPE;
287          type <= LAST_KEYMAP_FILE_TYPE;
288          type++) {
289         if (files[type] == NULL) {
290             log_err(ctx, "Required section %s missing from keymap\n",
291                     xkb_file_type_to_string(type));
292             ok = false;
293         }
294     }
295     if (!ok)
296         return false;
297
298     /* Compile sections. */
299     for (type = FIRST_KEYMAP_FILE_TYPE;
300          type <= LAST_KEYMAP_FILE_TYPE;
301          type++) {
302         log_dbg(ctx, "Compiling %s \"%s\"\n",
303                 xkb_file_type_to_string(type), files[type]->topName);
304
305         ok = compile_file_fns[type](files[type], keymap, merge);
306         if (!ok) {
307             log_err(ctx, "Failed to compile %s\n",
308                     xkb_file_type_to_string(type));
309             return false;
310         }
311     }
312
313     return UpdateDerivedKeymapFields(keymap);
314 }