• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2013 Ran Benita
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include "config.h"
25 
26 #include "x11-priv.h"
27 
28 /*
29  * References for the lonesome traveler:
30  * Xkb protocol specification:
31  *      https://www.x.org/releases/current/doc/kbproto/xkbproto.html
32  * The XCB xkb XML protocol file:
33  *      /user/share/xcb/xkb.xml
34  * The XCB xkb header file:
35  *      /usr/include/xcb/xkb.h
36  * The old kbproto header files:
37  *      /usr/include/X11/extensions/XKB{,proto,str}.h
38  * Xlib XKB source code:
39  *      <libX11>/src/xkb/XKBGetMap.c (and friends)
40  * X server XKB protocol handling:
41  *      <xserver>/xkb/xkb.c
42  * Man pages:
43  *      XkbGetMap(3), XkbGetCompatMap(3), etc.
44  */
45 
46 /* Constants from /usr/include/X11/extensions/XKB.h */
47 /* XkbNumModifiers. */
48 #define NUM_REAL_MODS 8u
49 /* XkbNumVirtualMods. */
50 #define NUM_VMODS 16u
51 /* XkbNoModifier. */
52 #define NO_MODIFIER 0xff
53 /* XkbNumIndicators. */
54 #define NUM_INDICATORS 32u
55 /* XkbAllIndicatorsMask. */
56 #define ALL_INDICATORS_MASK 0xffffffff
57 
58 /* Some macros. Not very nice but it'd be worse without them. */
59 
60 /*
61  * We try not to trust the server too much and be paranoid. If we get
62  * something which we definitely shouldn't, we fail.
63  */
64 #define STRINGIFY(expr) #expr
65 #define FAIL_UNLESS(expr) do {                                          \
66     if (!(expr)) {                                                      \
67         log_err(keymap->ctx,                                            \
68                 "x11: failed to get keymap from X server: unmet condition in %s(): %s\n", \
69                 __func__, STRINGIFY(expr));                             \
70         goto fail;                                                      \
71     }                                                                   \
72 } while (0)
73 
74 #define FAIL_IF_BAD_REPLY(reply, request_name) do {                     \
75     if (!reply) {                                                       \
76         log_err(keymap->ctx,                                            \
77                 "x11: failed to get keymap from X server: %s request failed\n", \
78                 (request_name));                                        \
79         goto fail;                                                      \
80     }                                                                   \
81 } while (0)
82 
83 #define ALLOC_OR_FAIL(arr, nmemb) do {                                  \
84     if ((nmemb) > 0) {                                                  \
85         (arr) = calloc((nmemb), sizeof(*(arr)));                        \
86         if (!(arr))                                                     \
87             goto fail;                                                  \
88     }                                                                   \
89 } while (0)
90 
91 
92 static xkb_mod_mask_t
translate_mods(uint8_t rmods,uint16_t vmods_low,uint16_t vmods_high)93 translate_mods(uint8_t rmods, uint16_t vmods_low, uint16_t vmods_high)
94 {
95     /* We represent mod masks in a single uint32_t value, with real mods
96      * first and vmods after (though we don't make these distinctions). */
97     return
98         ((xkb_mod_mask_t) rmods) |
99         ((xkb_mod_mask_t) vmods_low << 8) |
100         ((xkb_mod_mask_t) vmods_high << 16);
101 }
102 
103 static enum xkb_action_controls
translate_controls_mask(uint32_t wire)104 translate_controls_mask(uint32_t wire)
105 {
106     enum xkb_action_controls ret = 0;
107     if (wire & XCB_XKB_BOOL_CTRL_REPEAT_KEYS)
108         ret |= CONTROL_REPEAT;
109     if (wire & XCB_XKB_BOOL_CTRL_SLOW_KEYS)
110         ret |= CONTROL_SLOW;
111     if (wire & XCB_XKB_BOOL_CTRL_BOUNCE_KEYS)
112         ret |= CONTROL_DEBOUNCE;
113     if (wire & XCB_XKB_BOOL_CTRL_STICKY_KEYS)
114         ret |= CONTROL_STICKY;
115     if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS)
116         ret |= CONTROL_MOUSEKEYS;
117     if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS_ACCEL)
118         ret |= CONTROL_MOUSEKEYS_ACCEL;
119     if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_KEYS)
120         ret |= CONTROL_AX;
121     if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_TIMEOUT_MASK)
122         ret |= CONTROL_AX_TIMEOUT;
123     if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_FEEDBACK_MASK)
124         ret |= CONTROL_AX_FEEDBACK;
125     if (wire & XCB_XKB_BOOL_CTRL_AUDIBLE_BELL_MASK)
126         ret |= CONTROL_BELL;
127     if (wire & XCB_XKB_BOOL_CTRL_IGNORE_GROUP_LOCK_MASK)
128         ret |= CONTROL_IGNORE_GROUP_LOCK;
129     /* Some controls are not supported and don't appear here. */
130     return ret;
131 }
132 
133 static void
translate_action(union xkb_action * action,const xcb_xkb_action_t * wire)134 translate_action(union xkb_action *action, const xcb_xkb_action_t *wire)
135 {
136     switch (wire->type) {
137     case XCB_XKB_SA_TYPE_SET_MODS:
138         action->type = ACTION_TYPE_MOD_SET;
139 
140         action->mods.mods.mods = translate_mods(wire->setmods.realMods,
141                                                 wire->setmods.vmodsLow,
142                                                 wire->setmods.vmodsHigh);
143         action->mods.mods.mask = translate_mods(wire->setmods.mask, 0, 0);
144 
145         if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS)
146             action->mods.flags |= ACTION_LOCK_CLEAR;
147         if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK)
148             action->mods.flags |= ACTION_LATCH_TO_LOCK;
149         if (wire->setmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS)
150             action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP;
151 
152         break;
153     case XCB_XKB_SA_TYPE_LATCH_MODS:
154         action->type = ACTION_TYPE_MOD_LATCH;
155 
156         action->mods.mods.mods = translate_mods(wire->latchmods.realMods,
157                                                 wire->latchmods.vmodsLow,
158                                                 wire->latchmods.vmodsHigh);
159         action->mods.mods.mask = translate_mods(wire->latchmods.mask, 0, 0);
160 
161         if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS)
162             action->mods.flags |= ACTION_LOCK_CLEAR;
163         if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK)
164             action->mods.flags |= ACTION_LATCH_TO_LOCK;
165         if (wire->latchmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS)
166             action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP;
167 
168         break;
169     case XCB_XKB_SA_TYPE_LOCK_MODS:
170         action->type = ACTION_TYPE_MOD_LOCK;
171 
172         action->mods.mods.mods = translate_mods(wire->lockmods.realMods,
173                                                 wire->lockmods.vmodsLow,
174                                                 wire->lockmods.vmodsHigh);
175         action->mods.mods.mask = translate_mods(wire->lockmods.mask, 0, 0);
176 
177         if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK)
178             action->mods.flags |= ACTION_LOCK_NO_LOCK;
179         if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK)
180             action->mods.flags |= ACTION_LOCK_NO_UNLOCK;
181         if (wire->lockmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS)
182             action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP;
183 
184         break;
185     case XCB_XKB_SA_TYPE_SET_GROUP:
186         action->type = ACTION_TYPE_GROUP_SET;
187 
188         action->group.group = wire->setgroup.group;
189 
190         if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS)
191             action->group.flags |= ACTION_LOCK_CLEAR;
192         if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK)
193             action->group.flags |= ACTION_LATCH_TO_LOCK;
194         if (wire->setmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE)
195             action->group.flags |= ACTION_ABSOLUTE_SWITCH;
196 
197         break;
198     case XCB_XKB_SA_TYPE_LATCH_GROUP:
199         action->type = ACTION_TYPE_GROUP_LATCH;
200 
201         action->group.group = wire->latchgroup.group;
202 
203         if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS)
204             action->group.flags |= ACTION_LOCK_CLEAR;
205         if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK)
206             action->group.flags |= ACTION_LATCH_TO_LOCK;
207         if (wire->latchmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE)
208             action->group.flags |= ACTION_ABSOLUTE_SWITCH;
209 
210         break;
211     case XCB_XKB_SA_TYPE_LOCK_GROUP:
212         action->type = ACTION_TYPE_GROUP_LOCK;
213 
214         action->group.group = wire->lockgroup.group;
215 
216         if (wire->lockgroup.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE)
217             action->group.flags |= ACTION_ABSOLUTE_SWITCH;
218 
219         break;
220     case XCB_XKB_SA_TYPE_MOVE_PTR:
221         action->type = ACTION_TYPE_PTR_MOVE;
222 
223         action->ptr.x = (int16_t) (wire->moveptr.xLow | ((uint16_t) wire->moveptr.xHigh << 8));
224         action->ptr.y = (int16_t) (wire->moveptr.yLow | ((uint16_t) wire->moveptr.yHigh << 8));
225 
226         if (!(wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION))
227             action->ptr.flags |= ACTION_ACCEL;
228         if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_X)
229             action->ptr.flags |= ACTION_ABSOLUTE_X;
230         if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_Y)
231             action->ptr.flags |= ACTION_ABSOLUTE_Y;
232 
233         break;
234     case XCB_XKB_SA_TYPE_PTR_BTN:
235         action->type = ACTION_TYPE_PTR_BUTTON;
236 
237         action->btn.count = wire->ptrbtn.count;
238         action->btn.button = wire->ptrbtn.button;
239         action->btn.flags = 0;
240 
241         break;
242     case XCB_XKB_SA_TYPE_LOCK_PTR_BTN:
243         action->type = ACTION_TYPE_PTR_LOCK;
244 
245         action->btn.button = wire->lockptrbtn.button;
246 
247         if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK)
248             action->btn.flags |= ACTION_LOCK_NO_LOCK;
249         if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK)
250             action->btn.flags |= ACTION_LOCK_NO_UNLOCK;
251 
252         break;
253     case XCB_XKB_SA_TYPE_SET_PTR_DFLT:
254         action->type = ACTION_TYPE_PTR_DEFAULT;
255 
256         action->dflt.value = wire->setptrdflt.value;
257 
258         if (wire->setptrdflt.flags & XCB_XKB_SA_SET_PTR_DFLT_FLAG_DFLT_BTN_ABSOLUTE)
259             action->dflt.flags |= ACTION_ABSOLUTE_SWITCH;
260 
261         break;
262     case XCB_XKB_SA_TYPE_TERMINATE:
263         action->type = ACTION_TYPE_TERMINATE;
264 
265         break;
266     case XCB_XKB_SA_TYPE_SWITCH_SCREEN:
267         action->type = ACTION_TYPE_SWITCH_VT;
268 
269         action->screen.screen = wire->switchscreen.newScreen;
270 
271         if (!(wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_APPLICATION))
272             action->screen.flags |= ACTION_SAME_SCREEN;
273         if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_ABSOLUTE)
274             action->screen.flags |= ACTION_ABSOLUTE_SWITCH;
275 
276         break;
277     case XCB_XKB_SA_TYPE_SET_CONTROLS:
278         action->type = ACTION_TYPE_CTRL_SET;
279         {
280             const uint16_t mask = (wire->setcontrols.boolCtrlsLow |
281                                    (wire->setcontrols.boolCtrlsHigh << 8));
282             action->ctrls.ctrls = translate_controls_mask(mask);
283         }
284         break;
285     case XCB_XKB_SA_TYPE_LOCK_CONTROLS:
286         action->type = ACTION_TYPE_CTRL_LOCK;
287         {
288             const uint16_t mask = (wire->lockcontrols.boolCtrlsLow |
289                                    (wire->lockcontrols.boolCtrlsHigh << 8));
290             action->ctrls.ctrls = translate_controls_mask(mask);
291         }
292         break;
293 
294     case XCB_XKB_SA_TYPE_NO_ACTION:
295     /* We don't support these. */
296     case XCB_XKB_SA_TYPE_ISO_LOCK:
297     case XCB_XKB_SA_TYPE_REDIRECT_KEY:
298     case XCB_XKB_SA_TYPE_ACTION_MESSAGE:
299     case XCB_XKB_SA_TYPE_DEVICE_BTN:
300     case XCB_XKB_SA_TYPE_LOCK_DEVICE_BTN:
301     case XCB_XKB_SA_TYPE_DEVICE_VALUATOR:
302         action->type = ACTION_TYPE_NONE;
303         break;
304 
305     default:
306         if (wire->type < ACTION_TYPE_PRIVATE) {
307             action->type = ACTION_TYPE_NONE;
308             break;
309         }
310 
311         /* Treat high unknown actions as Private actions. */
312         action->priv.type = wire->noaction.type;
313         STATIC_ASSERT(sizeof(action->priv.data) == 7 &&
314                       sizeof(wire->noaction.pad0) == 7,
315                       "The private action data must be 7 bytes long!");
316         memcpy(action->priv.data, wire->noaction.pad0, 7);
317         break;
318     }
319 }
320 
321 static bool
get_types(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_map_reply_t * reply,xcb_xkb_get_map_map_t * map)322 get_types(struct xkb_keymap *keymap, xcb_connection_t *conn,
323           xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map)
324 {
325     int types_length = xcb_xkb_get_map_map_types_rtrn_length(reply, map);
326     xcb_xkb_key_type_iterator_t types_iter =
327         xcb_xkb_get_map_map_types_rtrn_iterator(reply, map);
328 
329     FAIL_UNLESS(reply->firstType == 0);
330 
331     keymap->num_types = reply->nTypes;
332     ALLOC_OR_FAIL(keymap->types, keymap->num_types);
333 
334     for (int i = 0; i < types_length; i++) {
335         xcb_xkb_key_type_t *wire_type = types_iter.data;
336         struct xkb_key_type *type = &keymap->types[i];
337 
338         FAIL_UNLESS(wire_type->numLevels > 0);
339 
340         type->mods.mods = translate_mods(wire_type->mods_mods,
341                                          wire_type->mods_vmods, 0);
342         type->mods.mask = translate_mods(wire_type->mods_mask, 0, 0);
343         type->num_levels = wire_type->numLevels;
344 
345         {
346             int entries_length = xcb_xkb_key_type_map_length(wire_type);
347             xcb_xkb_kt_map_entry_iterator_t entries_iter =
348                 xcb_xkb_key_type_map_iterator(wire_type);
349 
350             type->num_entries = wire_type->nMapEntries;
351             ALLOC_OR_FAIL(type->entries, type->num_entries);
352 
353             for (int j = 0; j < entries_length; j++) {
354                 xcb_xkb_kt_map_entry_t *wire_entry = entries_iter.data;
355                 struct xkb_key_type_entry *entry = &type->entries[j];
356 
357                 FAIL_UNLESS(wire_entry->level < type->num_levels);
358 
359                 entry->level = wire_entry->level;
360                 entry->mods.mods = translate_mods(wire_entry->mods_mods,
361                                                   wire_entry->mods_vmods, 0);
362                 entry->mods.mask = translate_mods(wire_entry->mods_mask, 0, 0);
363 
364                 xcb_xkb_kt_map_entry_next(&entries_iter);
365             }
366         }
367 
368         {
369             int preserves_length = xcb_xkb_key_type_preserve_length(wire_type);
370             xcb_xkb_mod_def_iterator_t preserves_iter =
371                 xcb_xkb_key_type_preserve_iterator(wire_type);
372 
373             FAIL_UNLESS((unsigned) preserves_length <= type->num_entries);
374 
375             for (int j = 0; j < preserves_length; j++) {
376                 xcb_xkb_mod_def_t *wire_preserve = preserves_iter.data;
377                 struct xkb_key_type_entry *entry = &type->entries[j];
378 
379                 entry->preserve.mods = translate_mods(wire_preserve->realMods,
380                                                       wire_preserve->vmods, 0);
381                 entry->preserve.mask = translate_mods(wire_preserve->mask, 0, 0);
382 
383                 xcb_xkb_mod_def_next(&preserves_iter);
384             }
385         }
386 
387         xcb_xkb_key_type_next(&types_iter);
388     }
389 
390     return true;
391 
392 fail:
393     return false;
394 }
395 
396 static bool
get_sym_maps(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_map_reply_t * reply,xcb_xkb_get_map_map_t * map)397 get_sym_maps(struct xkb_keymap *keymap, xcb_connection_t *conn,
398              xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map)
399 {
400     int sym_maps_length = xcb_xkb_get_map_map_syms_rtrn_length(reply, map);
401     xcb_xkb_key_sym_map_iterator_t sym_maps_iter =
402         xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map);
403 
404     FAIL_UNLESS(reply->minKeyCode <= reply->maxKeyCode);
405     FAIL_UNLESS(reply->firstKeySym >= reply->minKeyCode);
406     FAIL_UNLESS(reply->firstKeySym + reply->nKeySyms <= reply->maxKeyCode + 1);
407 
408     keymap->min_key_code = reply->minKeyCode;
409     keymap->max_key_code = reply->maxKeyCode;
410 
411     ALLOC_OR_FAIL(keymap->keys, keymap->max_key_code + 1);
412 
413     for (xkb_keycode_t kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++)
414         keymap->keys[kc].keycode = kc;
415 
416     for (int i = 0; i < sym_maps_length; i++) {
417         xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data;
418         struct xkb_key *key = &keymap->keys[reply->firstKeySym + i];
419 
420         key->num_groups = wire_sym_map->groupInfo & 0x0f;
421         FAIL_UNLESS(key->num_groups <= ARRAY_SIZE(wire_sym_map->kt_index));
422         ALLOC_OR_FAIL(key->groups, key->num_groups);
423 
424         for (unsigned j = 0; j < key->num_groups; j++) {
425             FAIL_UNLESS(wire_sym_map->kt_index[j] < keymap->num_types);
426             key->groups[j].type = &keymap->types[wire_sym_map->kt_index[j]];
427 
428             ALLOC_OR_FAIL(key->groups[j].levels, key->groups[j].type->num_levels);
429         }
430 
431         key->out_of_range_group_number = (wire_sym_map->groupInfo & 0x30) >> 4;
432 
433         FAIL_UNLESS(key->out_of_range_group_number <= key->num_groups);
434 
435         if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_CLAMP_INTO_RANGE)
436             key->out_of_range_group_action = RANGE_SATURATE;
437         else if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_REDIRECT_INTO_RANGE)
438             key->out_of_range_group_action = RANGE_REDIRECT;
439         else
440             key->out_of_range_group_action = RANGE_WRAP;
441 
442         {
443             int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map);
444             xcb_keysym_t *syms_iter = xcb_xkb_key_sym_map_syms(wire_sym_map);
445 
446             FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups);
447 
448             for (xkb_layout_index_t group = 0; group < key->num_groups; group++) {
449                 for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) {
450                     xcb_keysym_t wire_keysym = *syms_iter;
451 
452                     assert(key->groups[group].type != NULL);
453                     if (level < key->groups[group].type->num_levels &&
454                         wire_keysym != XKB_KEY_NoSymbol) {
455                         key->groups[group].levels[level].num_syms = 1;
456                         key->groups[group].levels[level].u.sym = wire_keysym;
457                     }
458 
459                     syms_iter++;
460                 }
461             }
462         }
463 
464         xcb_xkb_key_sym_map_next(&sym_maps_iter);
465     }
466 
467     return true;
468 
469 fail:
470     return false;
471 }
472 
473 static bool
get_actions(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_map_reply_t * reply,xcb_xkb_get_map_map_t * map)474 get_actions(struct xkb_keymap *keymap, xcb_connection_t *conn,
475             xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map)
476 {
477     int acts_count_length =
478         xcb_xkb_get_map_map_acts_rtrn_count_length(reply, map);
479     uint8_t *acts_count_iter = xcb_xkb_get_map_map_acts_rtrn_count(map);
480     xcb_xkb_action_iterator_t acts_iter =
481         xcb_xkb_get_map_map_acts_rtrn_acts_iterator(reply, map);
482     xcb_xkb_key_sym_map_iterator_t sym_maps_iter =
483         xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map);
484 
485     FAIL_UNLESS(reply->firstKeyAction == keymap->min_key_code);
486     FAIL_UNLESS(reply->firstKeyAction + reply->nKeyActions ==
487                 keymap->max_key_code + 1);
488 
489     for (int i = 0; i < acts_count_length; i++) {
490         xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data;
491         int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map);
492         uint8_t wire_count = *acts_count_iter;
493         struct xkb_key *key = &keymap->keys[reply->firstKeyAction + i];
494 
495         FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups);
496         FAIL_UNLESS(wire_count == 0 || wire_count == syms_length);
497 
498         if (wire_count != 0) {
499             for (xkb_layout_index_t group = 0; group < key->num_groups; group++) {
500                 for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) {
501                     xcb_xkb_action_t *wire_action = acts_iter.data;
502 
503                     if (level < key->groups[group].type->num_levels) {
504                         union xkb_action *action = &key->groups[group].levels[level].action;
505 
506                         translate_action(action, wire_action);
507                     }
508 
509                     xcb_xkb_action_next(&acts_iter);
510                 }
511             }
512         }
513 
514         acts_count_iter++;
515         xcb_xkb_key_sym_map_next(&sym_maps_iter);
516     }
517 
518     return true;
519 
520 fail:
521     return false;
522 }
523 
524 static bool
get_vmods(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_map_reply_t * reply,xcb_xkb_get_map_map_t * map)525 get_vmods(struct xkb_keymap *keymap, xcb_connection_t *conn,
526           xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map)
527 {
528     uint8_t *iter = xcb_xkb_get_map_map_vmods_rtrn(map);
529 
530     keymap->mods.num_mods =
531         NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
532 
533     for (unsigned i = 0; i < NUM_VMODS; i++) {
534         if (reply->virtualMods & (1u << i)) {
535             uint8_t wire = *iter;
536             struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i];
537 
538             mod->type = MOD_VIRT;
539             mod->mapping = translate_mods(wire, 0, 0);
540 
541             iter++;
542         }
543     }
544 
545     return true;
546 }
547 
548 static bool
get_explicits(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_map_reply_t * reply,xcb_xkb_get_map_map_t * map)549 get_explicits(struct xkb_keymap *keymap, xcb_connection_t *conn,
550               xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map)
551 {
552     int length = xcb_xkb_get_map_map_explicit_rtrn_length(reply, map);
553     xcb_xkb_set_explicit_iterator_t iter =
554         xcb_xkb_get_map_map_explicit_rtrn_iterator(reply, map);
555 
556     for (int i = 0; i < length; i++) {
557         xcb_xkb_set_explicit_t *wire = iter.data;
558         struct xkb_key *key;
559 
560         FAIL_UNLESS(wire->keycode >= keymap->min_key_code &&
561                     wire->keycode <= keymap->max_key_code);
562 
563         key = &keymap->keys[wire->keycode];
564 
565         if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_1) &&
566             key->num_groups > 0)
567             key->groups[0].explicit_type = true;
568         if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_2) &&
569             key->num_groups > 1)
570             key->groups[1].explicit_type = true;
571         if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_3) &&
572             key->num_groups > 2)
573             key->groups[2].explicit_type = true;
574         if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_4) &&
575             key->num_groups > 3)
576             key->groups[3].explicit_type = true;
577         if (wire->explicit & XCB_XKB_EXPLICIT_INTERPRET)
578             key->explicit |= EXPLICIT_INTERP;
579         if (wire->explicit & XCB_XKB_EXPLICIT_AUTO_REPEAT)
580             key->explicit |= EXPLICIT_REPEAT;
581         if (wire->explicit & XCB_XKB_EXPLICIT_V_MOD_MAP)
582             key->explicit |= EXPLICIT_VMODMAP;
583 
584         xcb_xkb_set_explicit_next(&iter);
585     }
586 
587     return true;
588 
589 fail:
590     return false;
591 }
592 
593 static bool
get_modmaps(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_map_reply_t * reply,xcb_xkb_get_map_map_t * map)594 get_modmaps(struct xkb_keymap *keymap, xcb_connection_t *conn,
595             xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map)
596 {
597     int length = xcb_xkb_get_map_map_modmap_rtrn_length(reply, map);
598     xcb_xkb_key_mod_map_iterator_t iter =
599         xcb_xkb_get_map_map_modmap_rtrn_iterator(reply, map);
600 
601     for (int i = 0; i < length; i++) {
602         xcb_xkb_key_mod_map_t *wire = iter.data;
603         struct xkb_key *key;
604 
605         FAIL_UNLESS(wire->keycode >= keymap->min_key_code &&
606                     wire->keycode <= keymap->max_key_code);
607 
608         key = &keymap->keys[wire->keycode];
609         key->modmap = wire->mods;
610 
611         xcb_xkb_key_mod_map_next(&iter);
612     }
613 
614     return true;
615 
616 fail:
617     return false;
618 }
619 
620 static bool
get_vmodmaps(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_map_reply_t * reply,xcb_xkb_get_map_map_t * map)621 get_vmodmaps(struct xkb_keymap *keymap, xcb_connection_t *conn,
622              xcb_xkb_get_map_reply_t *reply, xcb_xkb_get_map_map_t *map)
623 {
624     int length = xcb_xkb_get_map_map_vmodmap_rtrn_length(reply, map);
625     xcb_xkb_key_v_mod_map_iterator_t iter =
626         xcb_xkb_get_map_map_vmodmap_rtrn_iterator(reply, map);
627 
628     for (int i = 0; i < length; i++) {
629         xcb_xkb_key_v_mod_map_t *wire = iter.data;
630         struct xkb_key *key;
631 
632         FAIL_UNLESS(wire->keycode >= keymap->min_key_code &&
633                     wire->keycode <= keymap->max_key_code);
634 
635         key = &keymap->keys[wire->keycode];
636         key->vmodmap = translate_mods(0, wire->vmods, 0);
637 
638         xcb_xkb_key_v_mod_map_next(&iter);
639     }
640 
641     return true;
642 
643 fail:
644     return false;
645 }
646 
647 static bool
get_map(struct xkb_keymap * keymap,xcb_connection_t * conn,uint16_t device_id)648 get_map(struct xkb_keymap *keymap, xcb_connection_t *conn, uint16_t device_id)
649 {
650     static const xcb_xkb_map_part_t required_components =
651         (XCB_XKB_MAP_PART_KEY_TYPES |
652          XCB_XKB_MAP_PART_KEY_SYMS |
653          XCB_XKB_MAP_PART_MODIFIER_MAP |
654          XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS |
655          XCB_XKB_MAP_PART_KEY_ACTIONS |
656          XCB_XKB_MAP_PART_VIRTUAL_MODS |
657          XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP);
658 
659     xcb_xkb_get_map_cookie_t cookie =
660         xcb_xkb_get_map(conn, device_id, required_components,
661                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
662     xcb_xkb_get_map_reply_t *reply = xcb_xkb_get_map_reply(conn, cookie, NULL);
663     xcb_xkb_get_map_map_t map;
664 
665     FAIL_IF_BAD_REPLY(reply, "XkbGetMap");
666 
667     if ((reply->present & required_components) != required_components)
668         goto fail;
669 
670     xcb_xkb_get_map_map_unpack(xcb_xkb_get_map_map(reply),
671                                reply->nTypes,
672                                reply->nKeySyms,
673                                reply->nKeyActions,
674                                reply->totalActions,
675                                reply->totalKeyBehaviors,
676                                reply->virtualMods,
677                                reply->totalKeyExplicit,
678                                reply->totalModMapKeys,
679                                reply->totalVModMapKeys,
680                                reply->present,
681                                &map);
682 
683     if (!get_types(keymap, conn, reply, &map) ||
684         !get_sym_maps(keymap, conn, reply, &map) ||
685         !get_actions(keymap, conn, reply, &map) ||
686         !get_vmods(keymap, conn, reply, &map) ||
687         !get_explicits(keymap, conn, reply, &map) ||
688         !get_modmaps(keymap, conn, reply, &map) ||
689         !get_vmodmaps(keymap, conn, reply, &map))
690         goto fail;
691 
692     free(reply);
693     return true;
694 
695 fail:
696     free(reply);
697     return false;
698 }
699 
700 static bool
get_indicators(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_indicator_map_reply_t * reply)701 get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn,
702                xcb_xkb_get_indicator_map_reply_t *reply)
703 {
704     xcb_xkb_indicator_map_iterator_t iter =
705         xcb_xkb_get_indicator_map_maps_iterator(reply);
706 
707     keymap->num_leds = msb_pos(reply->which);
708 
709     for (unsigned i = 0; i < NUM_INDICATORS; i++) {
710         if (reply->which & (1u << i)) {
711             xcb_xkb_indicator_map_t *wire = iter.data;
712             struct xkb_led *led = &keymap->leds[i];
713 
714             if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_BASE)
715                 led->which_groups |= XKB_STATE_LAYOUT_DEPRESSED;
716             if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LATCHED)
717                 led->which_groups |= XKB_STATE_LAYOUT_LATCHED;
718             if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LOCKED)
719                 led->which_groups |= XKB_STATE_LAYOUT_LOCKED;
720             if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_EFFECTIVE)
721                 led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE;
722             if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_COMPAT)
723                 led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE;
724 
725             led->groups = wire->groups;
726 
727             if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_BASE)
728                 led->which_mods |= XKB_STATE_MODS_DEPRESSED;
729             if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LATCHED)
730                 led->which_mods |= XKB_STATE_MODS_LATCHED;
731             if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LOCKED)
732                 led->which_mods |= XKB_STATE_MODS_LOCKED;
733             if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_EFFECTIVE)
734                 led->which_mods |= XKB_STATE_MODS_EFFECTIVE;
735             if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_COMPAT)
736                 led->which_mods |= XKB_STATE_MODS_EFFECTIVE;
737 
738             led->mods.mods = translate_mods(wire->realMods, wire->vmods, 0);
739             led->mods.mask = translate_mods(wire->mods, 0, 0);
740 
741             led->ctrls = translate_controls_mask(wire->ctrls);
742 
743             xcb_xkb_indicator_map_next(&iter);
744         }
745     }
746 
747     return true;
748 }
749 
750 static bool
get_indicator_map(struct xkb_keymap * keymap,xcb_connection_t * conn,uint16_t device_id)751 get_indicator_map(struct xkb_keymap *keymap, xcb_connection_t *conn,
752                   uint16_t device_id)
753 {
754     xcb_xkb_get_indicator_map_cookie_t cookie =
755         xcb_xkb_get_indicator_map(conn, device_id, ALL_INDICATORS_MASK);
756     xcb_xkb_get_indicator_map_reply_t *reply =
757         xcb_xkb_get_indicator_map_reply(conn, cookie, NULL);
758 
759     FAIL_IF_BAD_REPLY(reply, "XkbGetIndicatorMap");
760 
761     if (!get_indicators(keymap, conn, reply))
762         goto fail;
763 
764     free(reply);
765     return true;
766 
767 fail:
768     free(reply);
769     return false;
770 }
771 
772 static bool
get_sym_interprets(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_compat_map_reply_t * reply)773 get_sym_interprets(struct xkb_keymap *keymap, xcb_connection_t *conn,
774                    xcb_xkb_get_compat_map_reply_t *reply)
775 {
776     int length = xcb_xkb_get_compat_map_si_rtrn_length(reply);
777     xcb_xkb_sym_interpret_iterator_t iter =
778         xcb_xkb_get_compat_map_si_rtrn_iterator(reply);
779 
780     FAIL_UNLESS(reply->firstSIRtrn == 0);
781     FAIL_UNLESS(reply->nSIRtrn == reply->nTotalSI);
782 
783     keymap->num_sym_interprets = reply->nSIRtrn;
784     ALLOC_OR_FAIL(keymap->sym_interprets, keymap->num_sym_interprets);
785 
786     for (int i = 0; i < length; i++) {
787         xcb_xkb_sym_interpret_t *wire = iter.data;
788         struct xkb_sym_interpret *sym_interpret = &keymap->sym_interprets[i];
789 
790         sym_interpret->sym = wire->sym;
791 
792         switch (wire->match & XCB_XKB_SYM_INTERP_MATCH_OP_MASK) {
793         case XCB_XKB_SYM_INTERPRET_MATCH_NONE_OF:
794             sym_interpret->match = MATCH_NONE;
795             break;
796         case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF_OR_NONE:
797             sym_interpret->match = MATCH_ANY_OR_NONE;
798             break;
799         case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF:
800             sym_interpret->match = MATCH_ANY;
801             break;
802         case XCB_XKB_SYM_INTERPRET_MATCH_ALL_OF:
803             sym_interpret->match = MATCH_ALL;
804             break;
805         case XCB_XKB_SYM_INTERPRET_MATCH_EXACTLY:
806             sym_interpret->match = MATCH_EXACTLY;
807             break;
808         }
809 
810         sym_interpret->level_one_only =
811             (wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY);
812         sym_interpret->mods = wire->mods;
813 
814         if (wire->virtualMod == NO_MODIFIER)
815             sym_interpret->virtual_mod = XKB_MOD_INVALID;
816         else
817             sym_interpret->virtual_mod = NUM_REAL_MODS + wire->virtualMod;
818 
819         sym_interpret->repeat = (wire->flags & 0x01);
820         translate_action(&sym_interpret->action,
821                          (xcb_xkb_action_t *) &wire->action);
822 
823         xcb_xkb_sym_interpret_next(&iter);
824     }
825 
826     return true;
827 
828 fail:
829     return false;
830 }
831 
832 static bool
get_compat_map(struct xkb_keymap * keymap,xcb_connection_t * conn,uint16_t device_id)833 get_compat_map(struct xkb_keymap *keymap, xcb_connection_t *conn,
834                uint16_t device_id)
835 {
836     xcb_xkb_get_compat_map_cookie_t cookie =
837         xcb_xkb_get_compat_map(conn, device_id, 0, true, 0, 0);
838     xcb_xkb_get_compat_map_reply_t *reply =
839         xcb_xkb_get_compat_map_reply(conn, cookie, NULL);
840 
841     FAIL_IF_BAD_REPLY(reply, "XkbGetCompatMap");
842 
843     if (!get_sym_interprets(keymap, conn, reply))
844         goto fail;
845 
846     free(reply);
847     return true;
848 
849 fail:
850     free(reply);
851     return false;
852 }
853 
854 static bool
get_type_names(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_names_reply_t * reply,xcb_xkb_get_names_value_list_t * list)855 get_type_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
856                xcb_xkb_get_names_reply_t *reply,
857                xcb_xkb_get_names_value_list_t *list)
858 {
859     int key_type_names_length =
860         xcb_xkb_get_names_value_list_type_names_length(reply, list);
861     xcb_atom_t *key_type_names_iter =
862         xcb_xkb_get_names_value_list_type_names(list);
863     int n_levels_per_type_length =
864         xcb_xkb_get_names_value_list_n_levels_per_type_length(reply, list);
865     uint8_t *n_levels_per_type_iter =
866         xcb_xkb_get_names_value_list_n_levels_per_type(list);
867     xcb_atom_t *kt_level_names_iter =
868         xcb_xkb_get_names_value_list_kt_level_names(list);
869 
870     FAIL_UNLESS(reply->nTypes == keymap->num_types);
871     FAIL_UNLESS(key_type_names_length == n_levels_per_type_length);
872 
873     for (int i = 0; i < key_type_names_length; i++) {
874         xcb_atom_t wire_type_name = *key_type_names_iter;
875         uint8_t wire_num_levels = *n_levels_per_type_iter;
876         struct xkb_key_type *type = &keymap->types[i];
877 
878         /* Levels must have names. */
879         FAIL_UNLESS(type->num_levels == wire_num_levels);
880 
881         ALLOC_OR_FAIL(type->level_names, type->num_levels);
882 
883         if (!adopt_atom(keymap->ctx, conn, wire_type_name, &type->name))
884             goto fail;
885 
886         if (!adopt_atoms(keymap->ctx, conn,
887                          kt_level_names_iter, type->level_names,
888                          wire_num_levels))
889             goto fail;
890 
891         type->num_level_names = type->num_levels;
892         kt_level_names_iter += wire_num_levels;
893         key_type_names_iter++;
894         n_levels_per_type_iter++;
895     }
896 
897     return true;
898 
899 fail:
900     return false;
901 }
902 
903 static bool
get_indicator_names(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_names_reply_t * reply,xcb_xkb_get_names_value_list_t * list)904 get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
905                     xcb_xkb_get_names_reply_t *reply,
906                     xcb_xkb_get_names_value_list_t *list)
907 {
908     xcb_atom_t *iter = xcb_xkb_get_names_value_list_indicator_names(list);
909 
910     FAIL_UNLESS(msb_pos(reply->indicators) <= keymap->num_leds);
911 
912     for (unsigned i = 0; i < NUM_INDICATORS; i++) {
913         if (reply->indicators & (1u << i)) {
914             xcb_atom_t wire = *iter;
915             struct xkb_led *led = &keymap->leds[i];
916 
917             if (!adopt_atom(keymap->ctx, conn, wire, &led->name))
918                 return false;
919 
920             iter++;
921         }
922     }
923 
924     return true;
925 
926 fail:
927     return false;
928 }
929 
930 static bool
get_vmod_names(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_names_reply_t * reply,xcb_xkb_get_names_value_list_t * list)931 get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
932                xcb_xkb_get_names_reply_t *reply,
933                xcb_xkb_get_names_value_list_t *list)
934 {
935     xcb_atom_t *iter = xcb_xkb_get_names_value_list_virtual_mod_names(list);
936 
937     /*
938      * GetMap's reply->virtualMods is always 0xffff. This one really
939      * tells us which vmods exist (a vmod must have a name), so we fix
940      * up the size here.
941      */
942     keymap->mods.num_mods =
943         NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
944 
945     for (unsigned i = 0; i < NUM_VMODS; i++) {
946         if (reply->virtualMods & (1u << i)) {
947             xcb_atom_t wire = *iter;
948             struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i];
949 
950             if (!adopt_atom(keymap->ctx, conn, wire, &mod->name))
951                 return false;
952 
953             iter++;
954         }
955     }
956 
957     return true;
958 }
959 
960 static bool
get_group_names(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_names_reply_t * reply,xcb_xkb_get_names_value_list_t * list)961 get_group_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
962                 xcb_xkb_get_names_reply_t *reply,
963                 xcb_xkb_get_names_value_list_t *list)
964 {
965     int length = xcb_xkb_get_names_value_list_groups_length(reply, list);
966     xcb_atom_t *iter = xcb_xkb_get_names_value_list_groups(list);
967 
968     keymap->num_group_names = msb_pos(reply->groupNames);
969     ALLOC_OR_FAIL(keymap->group_names, keymap->num_group_names);
970 
971     if (!adopt_atoms(keymap->ctx, conn,
972                      iter, keymap->group_names, length))
973         goto fail;
974 
975     return true;
976 
977 fail:
978     return false;
979 }
980 
981 static bool
get_key_names(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_names_reply_t * reply,xcb_xkb_get_names_value_list_t * list)982 get_key_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
983               xcb_xkb_get_names_reply_t *reply,
984               xcb_xkb_get_names_value_list_t *list)
985 {
986     int length = xcb_xkb_get_names_value_list_key_names_length(reply, list);
987     xcb_xkb_key_name_iterator_t iter =
988         xcb_xkb_get_names_value_list_key_names_iterator(reply, list);
989 
990     FAIL_UNLESS(reply->minKeyCode == keymap->min_key_code);
991     FAIL_UNLESS(reply->maxKeyCode == keymap->max_key_code);
992     FAIL_UNLESS(reply->firstKey == keymap->min_key_code);
993     FAIL_UNLESS(reply->firstKey + reply->nKeys - 1U == keymap->max_key_code);
994 
995     for (int i = 0; i < length; i++) {
996         xcb_xkb_key_name_t *wire = iter.data;
997         xkb_atom_t *key_name = &keymap->keys[reply->firstKey + i].name;
998 
999         if (wire->name[0] == '\0') {
1000             *key_name = XKB_ATOM_NONE;
1001         }
1002         else {
1003             *key_name = xkb_atom_intern(keymap->ctx, wire->name,
1004                                         strnlen(wire->name,
1005                                                 XCB_XKB_CONST_KEY_NAME_LENGTH));
1006             if (!*key_name)
1007                 return false;
1008         }
1009 
1010         xcb_xkb_key_name_next(&iter);
1011     }
1012 
1013     return true;
1014 
1015 fail:
1016     return false;
1017 }
1018 
1019 static bool
get_aliases(struct xkb_keymap * keymap,xcb_connection_t * conn,xcb_xkb_get_names_reply_t * reply,xcb_xkb_get_names_value_list_t * list)1020 get_aliases(struct xkb_keymap *keymap, xcb_connection_t *conn,
1021             xcb_xkb_get_names_reply_t *reply,
1022             xcb_xkb_get_names_value_list_t *list)
1023 {
1024     int length = xcb_xkb_get_names_value_list_key_aliases_length(reply, list);
1025     xcb_xkb_key_alias_iterator_t iter =
1026         xcb_xkb_get_names_value_list_key_aliases_iterator(reply, list);
1027 
1028     keymap->num_key_aliases = reply->nKeyAliases;
1029     ALLOC_OR_FAIL(keymap->key_aliases, keymap->num_key_aliases);
1030 
1031     for (int i = 0; i < length; i++) {
1032         xcb_xkb_key_alias_t *wire = iter.data;
1033         struct xkb_key_alias *alias = &keymap->key_aliases[i];
1034 
1035         alias->real =
1036             xkb_atom_intern(keymap->ctx, wire->real,
1037                             strnlen(wire->real, XCB_XKB_CONST_KEY_NAME_LENGTH));
1038         alias->alias =
1039             xkb_atom_intern(keymap->ctx, wire->alias,
1040                             strnlen(wire->alias, XCB_XKB_CONST_KEY_NAME_LENGTH));
1041         if (!alias->real || !alias->alias)
1042             goto fail;
1043 
1044         xcb_xkb_key_alias_next(&iter);
1045     }
1046 
1047     return true;
1048 
1049 fail:
1050     return false;
1051 }
1052 
1053 static bool
get_names(struct xkb_keymap * keymap,xcb_connection_t * conn,uint16_t device_id)1054 get_names(struct xkb_keymap *keymap, xcb_connection_t *conn,
1055           uint16_t device_id)
1056 {
1057     static const xcb_xkb_name_detail_t wanted =
1058         (XCB_XKB_NAME_DETAIL_KEYCODES |
1059          XCB_XKB_NAME_DETAIL_SYMBOLS |
1060          XCB_XKB_NAME_DETAIL_TYPES |
1061          XCB_XKB_NAME_DETAIL_COMPAT |
1062          XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES |
1063          XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES |
1064          XCB_XKB_NAME_DETAIL_INDICATOR_NAMES |
1065          XCB_XKB_NAME_DETAIL_KEY_NAMES |
1066          XCB_XKB_NAME_DETAIL_KEY_ALIASES |
1067          XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES |
1068          XCB_XKB_NAME_DETAIL_GROUP_NAMES);
1069     static const xcb_xkb_name_detail_t required =
1070         (XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES |
1071          XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES |
1072          XCB_XKB_NAME_DETAIL_KEY_NAMES |
1073          XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES);
1074 
1075     xcb_xkb_get_names_cookie_t cookie =
1076         xcb_xkb_get_names(conn, device_id, wanted);
1077     xcb_xkb_get_names_reply_t *reply =
1078         xcb_xkb_get_names_reply(conn, cookie, NULL);
1079     xcb_xkb_get_names_value_list_t list;
1080 
1081     FAIL_IF_BAD_REPLY(reply, "XkbGetNames");
1082 
1083     FAIL_UNLESS((reply->which & required) == required);
1084 
1085     xcb_xkb_get_names_value_list_unpack(xcb_xkb_get_names_value_list(reply),
1086                                         reply->nTypes,
1087                                         reply->indicators,
1088                                         reply->virtualMods,
1089                                         reply->groupNames,
1090                                         reply->nKeys,
1091                                         reply->nKeyAliases,
1092                                         reply->nRadioGroups,
1093                                         reply->which,
1094                                         &list);
1095 
1096     if (!get_atom_name(conn, list.keycodesName, &keymap->keycodes_section_name) ||
1097         !get_atom_name(conn, list.symbolsName, &keymap->symbols_section_name) ||
1098         !get_atom_name(conn, list.typesName, &keymap->types_section_name) ||
1099         !get_atom_name(conn, list.compatName, &keymap->compat_section_name) ||
1100         !get_type_names(keymap, conn, reply, &list) ||
1101         !get_indicator_names(keymap, conn, reply, &list) ||
1102         !get_vmod_names(keymap, conn, reply, &list) ||
1103         !get_group_names(keymap, conn, reply, &list) ||
1104         !get_key_names(keymap, conn, reply, &list) ||
1105         !get_aliases(keymap, conn, reply, &list))
1106         goto fail;
1107 
1108     XkbEscapeMapName(keymap->keycodes_section_name);
1109     XkbEscapeMapName(keymap->symbols_section_name);
1110     XkbEscapeMapName(keymap->types_section_name);
1111     XkbEscapeMapName(keymap->compat_section_name);
1112 
1113     free(reply);
1114     return true;
1115 
1116 fail:
1117     free(reply);
1118     return false;
1119 }
1120 
1121 static bool
get_controls(struct xkb_keymap * keymap,xcb_connection_t * conn,uint16_t device_id)1122 get_controls(struct xkb_keymap *keymap, xcb_connection_t *conn,
1123              uint16_t device_id)
1124 {
1125     xcb_xkb_get_controls_cookie_t cookie =
1126         xcb_xkb_get_controls(conn, device_id);
1127     xcb_xkb_get_controls_reply_t *reply =
1128         xcb_xkb_get_controls_reply(conn, cookie, NULL);
1129 
1130     FAIL_IF_BAD_REPLY(reply, "XkbGetControls");
1131     FAIL_UNLESS(reply->numGroups > 0 && reply->numGroups <= 4);
1132 
1133     keymap->enabled_ctrls = translate_controls_mask(reply->enabledControls);
1134     keymap->num_groups = reply->numGroups;
1135 
1136     FAIL_UNLESS(keymap->max_key_code < XCB_XKB_CONST_PER_KEY_BIT_ARRAY_SIZE * 8);
1137 
1138     for (xkb_keycode_t i = keymap->min_key_code; i <= keymap->max_key_code; i++)
1139         keymap->keys[i].repeats = (reply->perKeyRepeat[i / 8] & (1 << (i % 8)));
1140 
1141     free(reply);
1142     return true;
1143 
1144 fail:
1145     free(reply);
1146     return false;
1147 }
1148 
1149 XKB_EXPORT struct xkb_keymap *
xkb_x11_keymap_new_from_device(struct xkb_context * ctx,xcb_connection_t * conn,int32_t device_id,enum xkb_keymap_compile_flags flags)1150 xkb_x11_keymap_new_from_device(struct xkb_context *ctx,
1151                                xcb_connection_t *conn,
1152                                int32_t device_id,
1153                                enum xkb_keymap_compile_flags flags)
1154 {
1155     struct xkb_keymap *keymap;
1156     const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
1157 
1158     if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
1159         log_err_func(ctx, "unrecognized flags: %#x\n", flags);
1160         return NULL;
1161     }
1162 
1163     if (device_id < 0 || device_id > 127) {
1164         log_err_func(ctx, "illegal device ID: %d\n", device_id);
1165         return NULL;
1166     }
1167 
1168     keymap = xkb_keymap_new(ctx, format, flags);
1169     if (!keymap)
1170         return NULL;
1171 
1172     if (!get_map(keymap, conn, device_id) ||
1173         !get_indicator_map(keymap, conn, device_id) ||
1174         !get_compat_map(keymap, conn, device_id) ||
1175         !get_names(keymap, conn, device_id) ||
1176         !get_controls(keymap, conn, device_id)) {
1177         xkb_keymap_unref(keymap);
1178         return NULL;
1179     }
1180 
1181     return keymap;
1182 }
1183