diff options
Diffstat (limited to 'src/3rdparty/xkbcommon/src/x11/x11-keymap.c')
-rw-r--r-- | src/3rdparty/xkbcommon/src/x11/x11-keymap.c | 1177 |
1 files changed, 0 insertions, 1177 deletions
diff --git a/src/3rdparty/xkbcommon/src/x11/x11-keymap.c b/src/3rdparty/xkbcommon/src/x11/x11-keymap.c deleted file mode 100644 index 701b614b2f..0000000000 --- a/src/3rdparty/xkbcommon/src/x11/x11-keymap.c +++ /dev/null @@ -1,1177 +0,0 @@ -/* - * Copyright © 2013 Ran Benita - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "x11-priv.h" - -/* - * References for the lonesome traveler: - * Xkb protocol specification: - * https://www.x.org/releases/current/doc/kbproto/xkbproto.html - * The XCB xkb XML protocol file: - * /user/share/xcb/xkb.xml - * The XCB xkb header file: - * /usr/include/xcb/xkb.h - * The old kbproto header files: - * /usr/include/X11/extensions/XKB{,proto,str}.h - * Xlib XKB source code: - * <libX11>/src/xkb/XKBGetMap.c (and friends) - * X server XKB protocol handling: - * <xserver>/xkb/xkb.c - * Man pages: - * XkbGetMap(3), XkbGetCompatMap(3), etc. - */ - -/* Constants from /usr/include/X11/extensions/XKB.h */ -/* XkbNumModifiers. */ -#define NUM_REAL_MODS 8u -/* XkbNumVirtualMods. */ -#define NUM_VMODS 16u -/* XkbNoModifier. */ -#define NO_MODIFIER 0xff -/* XkbNumIndicators. */ -#define NUM_INDICATORS 32u -/* XkbAllIndicatorsMask. */ -#define ALL_INDICATORS_MASK 0xffffffff - -/* Some macros. Not very nice but it'd be worse without them. */ - -/* - * We try not to trust the server too much and be paranoid. If we get - * something which we definitely shouldn't, we fail. - */ -#define STRINGIFY(expr) #expr -#define FAIL_UNLESS(expr) do { \ - if (!(expr)) { \ - log_err(keymap->ctx, \ - "x11: failed to get keymap from X server: unmet condition in %s(): %s\n", \ - __func__, STRINGIFY(expr)); \ - goto fail; \ - } \ -} while (0) - -#define FAIL_IF_BAD_REPLY(reply, request_name) do { \ - if (!reply) { \ - log_err(keymap->ctx, \ - "x11: failed to get keymap from X server: %s request failed\n", \ - (request_name)); \ - goto fail; \ - } \ -} while (0) - -#define ALLOC_OR_FAIL(arr, nmemb) do { \ - if ((nmemb) > 0) { \ - (arr) = calloc((nmemb), sizeof(*(arr))); \ - if (!(arr)) \ - goto fail; \ - } \ -} while (0) - - -static xkb_mod_mask_t -translate_mods(uint8_t rmods, uint16_t vmods_low, uint16_t vmods_high) -{ - /* We represent mod masks in a single uint32_t value, with real mods - * first and vmods after (though we don't make these distinctions). */ - return - ((xkb_mod_mask_t) rmods) | - ((xkb_mod_mask_t) vmods_low << 8) | - ((xkb_mod_mask_t) vmods_high << 16); -} - -static enum xkb_action_controls -translate_controls_mask(uint32_t wire) -{ - enum xkb_action_controls ret = 0; - if (wire & XCB_XKB_BOOL_CTRL_REPEAT_KEYS) - ret |= CONTROL_REPEAT; - if (wire & XCB_XKB_BOOL_CTRL_SLOW_KEYS) - ret |= CONTROL_SLOW; - if (wire & XCB_XKB_BOOL_CTRL_BOUNCE_KEYS) - ret |= CONTROL_DEBOUNCE; - if (wire & XCB_XKB_BOOL_CTRL_STICKY_KEYS) - ret |= CONTROL_STICKY; - if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS) - ret |= CONTROL_MOUSEKEYS; - if (wire & XCB_XKB_BOOL_CTRL_MOUSE_KEYS_ACCEL) - ret |= CONTROL_MOUSEKEYS_ACCEL; - if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_KEYS) - ret |= CONTROL_AX; - if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_TIMEOUT_MASK) - ret |= CONTROL_AX_TIMEOUT; - if (wire & XCB_XKB_BOOL_CTRL_ACCESS_X_FEEDBACK_MASK) - ret |= CONTROL_AX_FEEDBACK; - if (wire & XCB_XKB_BOOL_CTRL_AUDIBLE_BELL_MASK) - ret |= CONTROL_BELL; - if (wire & XCB_XKB_BOOL_CTRL_IGNORE_GROUP_LOCK_MASK) - ret |= CONTROL_IGNORE_GROUP_LOCK; - /* Some controls are not supported and don't appear here. */ - return ret; -} - -static void -translate_action(union xkb_action *action, const xcb_xkb_action_t *wire) -{ - switch (wire->type) { - case XCB_XKB_SA_TYPE_SET_MODS: - action->type = ACTION_TYPE_MOD_SET; - - action->mods.mods.mods = translate_mods(wire->setmods.realMods, - wire->setmods.vmodsLow, - wire->setmods.vmodsHigh); - action->mods.mods.mask = translate_mods(wire->setmods.mask, 0, 0); - - if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS) - action->mods.flags |= ACTION_LOCK_CLEAR; - if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) - action->mods.flags |= ACTION_LATCH_TO_LOCK; - if (wire->setmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) - action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; - - break; - case XCB_XKB_SA_TYPE_LATCH_MODS: - action->type = ACTION_TYPE_MOD_LATCH; - - action->mods.mods.mods = translate_mods(wire->latchmods.realMods, - wire->latchmods.vmodsLow, - wire->latchmods.vmodsHigh); - action->mods.mods.mask = translate_mods(wire->latchmods.mask, 0, 0); - - if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS) - action->mods.flags |= ACTION_LOCK_CLEAR; - if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) - action->mods.flags |= ACTION_LATCH_TO_LOCK; - if (wire->latchmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) - action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; - - break; - case XCB_XKB_SA_TYPE_LOCK_MODS: - action->type = ACTION_TYPE_MOD_LOCK; - - action->mods.mods.mods = translate_mods(wire->lockmods.realMods, - wire->lockmods.vmodsLow, - wire->lockmods.vmodsHigh); - action->mods.mods.mask = translate_mods(wire->lockmods.mask, 0, 0); - - if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK) - action->mods.flags |= ACTION_LOCK_NO_LOCK; - if (wire->lockmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK) - action->mods.flags |= ACTION_LOCK_NO_UNLOCK; - if (wire->lockmods.flags & XCB_XKB_SA_USE_MOD_MAP_MODS) - action->mods.flags |= ACTION_MODS_LOOKUP_MODMAP; - - break; - case XCB_XKB_SA_TYPE_SET_GROUP: - action->type = ACTION_TYPE_GROUP_SET; - - action->group.group = wire->setgroup.group; - - if (wire->setmods.flags & XCB_XKB_SA_CLEAR_LOCKS) - action->group.flags |= ACTION_LOCK_CLEAR; - if (wire->setmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) - action->group.flags |= ACTION_LATCH_TO_LOCK; - if (wire->setmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) - action->group.flags |= ACTION_ABSOLUTE_SWITCH; - - break; - case XCB_XKB_SA_TYPE_LATCH_GROUP: - action->type = ACTION_TYPE_GROUP_LATCH; - - action->group.group = wire->latchgroup.group; - - if (wire->latchmods.flags & XCB_XKB_SA_CLEAR_LOCKS) - action->group.flags |= ACTION_LOCK_CLEAR; - if (wire->latchmods.flags & XCB_XKB_SA_LATCH_TO_LOCK) - action->group.flags |= ACTION_LATCH_TO_LOCK; - if (wire->latchmods.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) - action->group.flags |= ACTION_ABSOLUTE_SWITCH; - - break; - case XCB_XKB_SA_TYPE_LOCK_GROUP: - action->type = ACTION_TYPE_GROUP_LOCK; - - action->group.group = wire->lockgroup.group; - - if (wire->lockgroup.flags & XCB_XKB_SA_ISO_LOCK_FLAG_GROUP_ABSOLUTE) - action->group.flags |= ACTION_ABSOLUTE_SWITCH; - - break; - case XCB_XKB_SA_TYPE_MOVE_PTR: - action->type = ACTION_TYPE_PTR_MOVE; - - action->ptr.x = (int16_t) (wire->moveptr.xLow | ((uint16_t) wire->moveptr.xHigh << 8)); - action->ptr.y = (int16_t) (wire->moveptr.yLow | ((uint16_t) wire->moveptr.yHigh << 8)); - - if (!(wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_NO_ACCELERATION)) - action->ptr.flags |= ACTION_ACCEL; - if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_X) - action->ptr.flags |= ACTION_ABSOLUTE_X; - if (wire->moveptr.flags & XCB_XKB_SA_MOVE_PTR_FLAG_MOVE_ABSOLUTE_Y) - action->ptr.flags |= ACTION_ABSOLUTE_Y; - - break; - case XCB_XKB_SA_TYPE_PTR_BTN: - action->type = ACTION_TYPE_PTR_BUTTON; - - action->btn.count = wire->ptrbtn.count; - action->btn.button = wire->ptrbtn.button; - action->btn.flags = 0; - - break; - case XCB_XKB_SA_TYPE_LOCK_PTR_BTN: - action->type = ACTION_TYPE_PTR_LOCK; - - action->btn.button = wire->lockptrbtn.button; - - if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_LOCK) - action->btn.flags |= ACTION_LOCK_NO_LOCK; - if (wire->lockptrbtn.flags & XCB_XKB_SA_ISO_LOCK_FLAG_NO_UNLOCK) - action->btn.flags |= ACTION_LOCK_NO_UNLOCK; - - break; - case XCB_XKB_SA_TYPE_SET_PTR_DFLT: - action->type = ACTION_TYPE_PTR_DEFAULT; - - action->dflt.value = wire->setptrdflt.value; - - if (wire->setptrdflt.flags & XCB_XKB_SA_SET_PTR_DFLT_FLAG_DFLT_BTN_ABSOLUTE) - action->dflt.flags |= ACTION_ABSOLUTE_SWITCH; - - break; - case XCB_XKB_SA_TYPE_TERMINATE: - action->type = ACTION_TYPE_TERMINATE; - - break; - case XCB_XKB_SA_TYPE_SWITCH_SCREEN: - action->type = ACTION_TYPE_SWITCH_VT; - - action->screen.screen = wire->switchscreen.newScreen; - - if (!(wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_APPLICATION)) - action->screen.flags |= ACTION_SAME_SCREEN; - if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_ABSOLUTE) - action->screen.flags |= ACTION_ABSOLUTE_SWITCH; - - break; - case XCB_XKB_SA_TYPE_SET_CONTROLS: - action->type = ACTION_TYPE_CTRL_SET; - { - const uint16_t mask = (wire->setcontrols.boolCtrlsLow | - (wire->setcontrols.boolCtrlsHigh << 8)); - action->ctrls.ctrls = translate_controls_mask(mask); - } - break; - case XCB_XKB_SA_TYPE_LOCK_CONTROLS: - action->type = ACTION_TYPE_CTRL_LOCK; - { - const uint16_t mask = (wire->lockcontrols.boolCtrlsLow | - (wire->lockcontrols.boolCtrlsHigh << 8)); - action->ctrls.ctrls = translate_controls_mask(mask); - } - break; - - case XCB_XKB_SA_TYPE_NO_ACTION: - /* We don't support these. */ - case XCB_XKB_SA_TYPE_ISO_LOCK: - case XCB_XKB_SA_TYPE_REDIRECT_KEY: - case XCB_XKB_SA_TYPE_ACTION_MESSAGE: - case XCB_XKB_SA_TYPE_DEVICE_BTN: - case XCB_XKB_SA_TYPE_LOCK_DEVICE_BTN: - case XCB_XKB_SA_TYPE_DEVICE_VALUATOR: - action->type = ACTION_TYPE_NONE; - break; - - default: - if (wire->type < ACTION_TYPE_PRIVATE) { - action->type = ACTION_TYPE_NONE; - break; - } - - /* Treat high unknown actions as Private actions. */ - action->priv.type = wire->noaction.type; - STATIC_ASSERT(sizeof(action->priv.data) == 7 && - sizeof(wire->noaction.pad0) == 7, - "The private action data must be 7 bytes long!"); - memcpy(action->priv.data, wire->noaction.pad0, 7); - break; - } -} - -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) -{ - int types_length = xcb_xkb_get_map_map_types_rtrn_length(reply, map); - xcb_xkb_key_type_iterator_t types_iter = - xcb_xkb_get_map_map_types_rtrn_iterator(reply, map); - - FAIL_UNLESS(reply->firstType == 0); - - keymap->num_types = reply->nTypes; - ALLOC_OR_FAIL(keymap->types, keymap->num_types); - - for (int i = 0; i < types_length; i++) { - xcb_xkb_key_type_t *wire_type = types_iter.data; - struct xkb_key_type *type = &keymap->types[i]; - - FAIL_UNLESS(wire_type->numLevels > 0); - - type->mods.mods = translate_mods(wire_type->mods_mods, - wire_type->mods_vmods, 0); - type->mods.mask = translate_mods(wire_type->mods_mask, 0, 0); - type->num_levels = wire_type->numLevels; - - { - int entries_length = xcb_xkb_key_type_map_length(wire_type); - xcb_xkb_kt_map_entry_iterator_t entries_iter = - xcb_xkb_key_type_map_iterator(wire_type); - - type->num_entries = wire_type->nMapEntries; - ALLOC_OR_FAIL(type->entries, type->num_entries); - - for (int j = 0; j < entries_length; j++) { - xcb_xkb_kt_map_entry_t *wire_entry = entries_iter.data; - struct xkb_key_type_entry *entry = &type->entries[j]; - - FAIL_UNLESS(wire_entry->level < type->num_levels); - - entry->level = wire_entry->level; - entry->mods.mods = translate_mods(wire_entry->mods_mods, - wire_entry->mods_vmods, 0); - entry->mods.mask = translate_mods(wire_entry->mods_mask, 0, 0); - - xcb_xkb_kt_map_entry_next(&entries_iter); - } - } - - { - int preserves_length = xcb_xkb_key_type_preserve_length(wire_type); - xcb_xkb_mod_def_iterator_t preserves_iter = - xcb_xkb_key_type_preserve_iterator(wire_type); - - FAIL_UNLESS((unsigned) preserves_length <= type->num_entries); - - for (int j = 0; j < preserves_length; j++) { - xcb_xkb_mod_def_t *wire_preserve = preserves_iter.data; - struct xkb_key_type_entry *entry = &type->entries[j]; - - entry->preserve.mods = translate_mods(wire_preserve->realMods, - wire_preserve->vmods, 0); - entry->preserve.mask = translate_mods(wire_preserve->mask, 0, 0); - - xcb_xkb_mod_def_next(&preserves_iter); - } - } - - xcb_xkb_key_type_next(&types_iter); - } - - return true; - -fail: - return false; -} - -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) -{ - int sym_maps_length = xcb_xkb_get_map_map_syms_rtrn_length(reply, map); - xcb_xkb_key_sym_map_iterator_t sym_maps_iter = - xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map); - - FAIL_UNLESS(reply->minKeyCode <= reply->maxKeyCode); - FAIL_UNLESS(reply->firstKeySym >= reply->minKeyCode); - FAIL_UNLESS(reply->firstKeySym + reply->nKeySyms <= reply->maxKeyCode + 1); - - keymap->min_key_code = reply->minKeyCode; - keymap->max_key_code = reply->maxKeyCode; - - ALLOC_OR_FAIL(keymap->keys, keymap->max_key_code + 1); - - for (xkb_keycode_t kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++) - keymap->keys[kc].keycode = kc; - - for (int i = 0; i < sym_maps_length; i++) { - xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data; - struct xkb_key *key = &keymap->keys[reply->firstKeySym + i]; - - key->num_groups = wire_sym_map->groupInfo & 0x0f; - FAIL_UNLESS(key->num_groups <= ARRAY_SIZE(wire_sym_map->kt_index)); - ALLOC_OR_FAIL(key->groups, key->num_groups); - - for (unsigned j = 0; j < key->num_groups; j++) { - FAIL_UNLESS(wire_sym_map->kt_index[j] < keymap->num_types); - key->groups[j].type = &keymap->types[wire_sym_map->kt_index[j]]; - - ALLOC_OR_FAIL(key->groups[j].levels, key->groups[j].type->num_levels); - } - - key->out_of_range_group_number = (wire_sym_map->groupInfo & 0x30) >> 4; - - FAIL_UNLESS(key->out_of_range_group_number <= key->num_groups); - - if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_CLAMP_INTO_RANGE) - key->out_of_range_group_action = RANGE_SATURATE; - else if (wire_sym_map->groupInfo & XCB_XKB_GROUPS_WRAP_REDIRECT_INTO_RANGE) - key->out_of_range_group_action = RANGE_REDIRECT; - else - key->out_of_range_group_action = RANGE_WRAP; - - { - int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map); - xcb_keysym_t *syms_iter = xcb_xkb_key_sym_map_syms(wire_sym_map); - - FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups); - - for (int j = 0; j < syms_length; j++) { - xcb_keysym_t wire_keysym = *syms_iter; - const xkb_layout_index_t group = j / wire_sym_map->width; - const xkb_level_index_t level = j % wire_sym_map->width; - - assert(key->groups[group].type != NULL); - if (level < key->groups[group].type->num_levels && - wire_keysym != XKB_KEY_NoSymbol) { - key->groups[group].levels[level].num_syms = 1; - key->groups[group].levels[level].u.sym = wire_keysym; - } - - syms_iter++; - } - } - - xcb_xkb_key_sym_map_next(&sym_maps_iter); - } - - return true; - -fail: - return false; -} - -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) -{ - int acts_count_length = - xcb_xkb_get_map_map_acts_rtrn_count_length(reply, map); - uint8_t *acts_count_iter = xcb_xkb_get_map_map_acts_rtrn_count(map); - xcb_xkb_action_iterator_t acts_iter = - xcb_xkb_get_map_map_acts_rtrn_acts_iterator(reply, map); - xcb_xkb_key_sym_map_iterator_t sym_maps_iter = - xcb_xkb_get_map_map_syms_rtrn_iterator(reply, map); - - FAIL_UNLESS(reply->firstKeyAction == keymap->min_key_code); - FAIL_UNLESS(reply->firstKeyAction + reply->nKeyActions == - keymap->max_key_code + 1); - - for (int i = 0; i < acts_count_length; i++) { - xcb_xkb_key_sym_map_t *wire_sym_map = sym_maps_iter.data; - int syms_length = xcb_xkb_key_sym_map_syms_length(wire_sym_map); - uint8_t wire_count = *acts_count_iter; - struct xkb_key *key = &keymap->keys[reply->firstKeyAction + i]; - - FAIL_UNLESS(wire_count == 0 || wire_count == syms_length); - - for (int j = 0; j < wire_count; j++) { - xcb_xkb_action_t *wire_action = acts_iter.data; - const xkb_layout_index_t group = j / wire_sym_map->width; - const xkb_level_index_t level = j % wire_sym_map->width; - - if (level < key->groups[group].type->num_levels) { - union xkb_action *action = - &key->groups[group].levels[level].action; - - translate_action(action, wire_action); - } - - xcb_xkb_action_next(&acts_iter); - } - - acts_count_iter++; - xcb_xkb_key_sym_map_next(&sym_maps_iter); - } - - return true; - -fail: - return false; -} - -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) -{ - uint8_t *iter = xcb_xkb_get_map_map_vmods_rtrn(map); - - keymap->mods.num_mods = - NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS); - - for (unsigned i = 0; i < NUM_VMODS; i++) { - if (reply->virtualMods & (1u << i)) { - uint8_t wire = *iter; - struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i]; - - mod->type = MOD_VIRT; - mod->mapping = translate_mods(wire, 0, 0); - - iter++; - } - } - - return true; -} - -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) -{ - int length = xcb_xkb_get_map_map_explicit_rtrn_length(reply, map); - xcb_xkb_set_explicit_iterator_t iter = - xcb_xkb_get_map_map_explicit_rtrn_iterator(reply, map); - - for (int i = 0; i < length; i++) { - xcb_xkb_set_explicit_t *wire = iter.data; - struct xkb_key *key; - - FAIL_UNLESS(wire->keycode >= keymap->min_key_code && - wire->keycode <= keymap->max_key_code); - - key = &keymap->keys[wire->keycode]; - - if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_1) && - key->num_groups > 0) - key->groups[0].explicit_type = true; - if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_2) && - key->num_groups > 1) - key->groups[1].explicit_type = true; - if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_3) && - key->num_groups > 2) - key->groups[2].explicit_type = true; - if ((wire->explicit & XCB_XKB_EXPLICIT_KEY_TYPE_4) && - key->num_groups > 3) - key->groups[3].explicit_type = true; - if (wire->explicit & XCB_XKB_EXPLICIT_INTERPRET) - key->explicit |= EXPLICIT_INTERP; - if (wire->explicit & XCB_XKB_EXPLICIT_AUTO_REPEAT) - key->explicit |= EXPLICIT_REPEAT; - if (wire->explicit & XCB_XKB_EXPLICIT_V_MOD_MAP) - key->explicit |= EXPLICIT_VMODMAP; - - xcb_xkb_set_explicit_next(&iter); - } - - return true; - -fail: - return false; -} - -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) -{ - int length = xcb_xkb_get_map_map_modmap_rtrn_length(reply, map); - xcb_xkb_key_mod_map_iterator_t iter = - xcb_xkb_get_map_map_modmap_rtrn_iterator(reply, map); - - for (int i = 0; i < length; i++) { - xcb_xkb_key_mod_map_t *wire = iter.data; - struct xkb_key *key; - - FAIL_UNLESS(wire->keycode >= keymap->min_key_code && - wire->keycode <= keymap->max_key_code); - - key = &keymap->keys[wire->keycode]; - key->modmap = wire->mods; - - xcb_xkb_key_mod_map_next(&iter); - } - - return true; - -fail: - return false; -} - -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) -{ - int length = xcb_xkb_get_map_map_vmodmap_rtrn_length(reply, map); - xcb_xkb_key_v_mod_map_iterator_t iter = - xcb_xkb_get_map_map_vmodmap_rtrn_iterator(reply, map); - - for (int i = 0; i < length; i++) { - xcb_xkb_key_v_mod_map_t *wire = iter.data; - struct xkb_key *key; - - FAIL_UNLESS(wire->keycode >= keymap->min_key_code && - wire->keycode <= keymap->max_key_code); - - key = &keymap->keys[wire->keycode]; - key->vmodmap = translate_mods(0, wire->vmods, 0); - - xcb_xkb_key_v_mod_map_next(&iter); - } - - return true; - -fail: - return false; -} - -static bool -get_map(struct xkb_keymap *keymap, xcb_connection_t *conn, uint16_t device_id) -{ - static const xcb_xkb_map_part_t required_components = - (XCB_XKB_MAP_PART_KEY_TYPES | - XCB_XKB_MAP_PART_KEY_SYMS | - XCB_XKB_MAP_PART_MODIFIER_MAP | - XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS | - XCB_XKB_MAP_PART_KEY_ACTIONS | - XCB_XKB_MAP_PART_VIRTUAL_MODS | - XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP); - - xcb_xkb_get_map_cookie_t cookie = - xcb_xkb_get_map(conn, device_id, required_components, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - xcb_xkb_get_map_reply_t *reply = xcb_xkb_get_map_reply(conn, cookie, NULL); - xcb_xkb_get_map_map_t map; - - FAIL_IF_BAD_REPLY(reply, "XkbGetMap"); - - if ((reply->present & required_components) != required_components) - goto fail; - - xcb_xkb_get_map_map_unpack(xcb_xkb_get_map_map(reply), - reply->nTypes, - reply->nKeySyms, - reply->nKeyActions, - reply->totalActions, - reply->totalKeyBehaviors, - reply->virtualMods, - reply->totalKeyExplicit, - reply->totalModMapKeys, - reply->totalVModMapKeys, - reply->present, - &map); - - if (!get_types(keymap, conn, reply, &map) || - !get_sym_maps(keymap, conn, reply, &map) || - !get_actions(keymap, conn, reply, &map) || - !get_vmods(keymap, conn, reply, &map) || - !get_explicits(keymap, conn, reply, &map) || - !get_modmaps(keymap, conn, reply, &map) || - !get_vmodmaps(keymap, conn, reply, &map)) - goto fail; - - free(reply); - return true; - -fail: - free(reply); - return false; -} - -static bool -get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn, - xcb_xkb_get_indicator_map_reply_t *reply) -{ - xcb_xkb_indicator_map_iterator_t iter = - xcb_xkb_get_indicator_map_maps_iterator(reply); - - keymap->num_leds = msb_pos(reply->which); - - for (unsigned i = 0; i < NUM_INDICATORS; i++) { - if (reply->which & (1u << i)) { - xcb_xkb_indicator_map_t *wire = iter.data; - struct xkb_led *led = &keymap->leds[i]; - - if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_BASE) - led->which_groups |= XKB_STATE_LAYOUT_DEPRESSED; - if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LATCHED) - led->which_groups |= XKB_STATE_LAYOUT_LATCHED; - if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_LOCKED) - led->which_groups |= XKB_STATE_LAYOUT_LOCKED; - if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_EFFECTIVE) - led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE; - if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_COMPAT) - led->which_groups |= XKB_STATE_LAYOUT_EFFECTIVE; - - led->groups = wire->groups; - - if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_BASE) - led->which_mods |= XKB_STATE_MODS_DEPRESSED; - if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LATCHED) - led->which_mods |= XKB_STATE_MODS_LATCHED; - if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_LOCKED) - led->which_mods |= XKB_STATE_MODS_LOCKED; - if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_EFFECTIVE) - led->which_mods |= XKB_STATE_MODS_EFFECTIVE; - if (wire->whichMods & XCB_XKB_IM_MODS_WHICH_USE_COMPAT) - led->which_mods |= XKB_STATE_MODS_EFFECTIVE; - - led->mods.mods = translate_mods(wire->realMods, wire->vmods, 0); - led->mods.mask = translate_mods(wire->mods, 0, 0); - - led->ctrls = translate_controls_mask(wire->ctrls); - - xcb_xkb_indicator_map_next(&iter); - } - } - - return true; -} - -static bool -get_indicator_map(struct xkb_keymap *keymap, xcb_connection_t *conn, - uint16_t device_id) -{ - xcb_xkb_get_indicator_map_cookie_t cookie = - xcb_xkb_get_indicator_map(conn, device_id, ALL_INDICATORS_MASK); - xcb_xkb_get_indicator_map_reply_t *reply = - xcb_xkb_get_indicator_map_reply(conn, cookie, NULL); - - FAIL_IF_BAD_REPLY(reply, "XkbGetIndicatorMap"); - - if (!get_indicators(keymap, conn, reply)) - goto fail; - - free(reply); - return true; - -fail: - free(reply); - return false; -} - -static bool -get_sym_interprets(struct xkb_keymap *keymap, xcb_connection_t *conn, - xcb_xkb_get_compat_map_reply_t *reply) -{ - int length = xcb_xkb_get_compat_map_si_rtrn_length(reply); - xcb_xkb_sym_interpret_iterator_t iter = - xcb_xkb_get_compat_map_si_rtrn_iterator(reply); - - FAIL_UNLESS(reply->firstSIRtrn == 0); - FAIL_UNLESS(reply->nSIRtrn == reply->nTotalSI); - - keymap->num_sym_interprets = reply->nSIRtrn; - ALLOC_OR_FAIL(keymap->sym_interprets, keymap->num_sym_interprets); - - for (int i = 0; i < length; i++) { - xcb_xkb_sym_interpret_t *wire = iter.data; - struct xkb_sym_interpret *sym_interpret = &keymap->sym_interprets[i]; - - sym_interpret->sym = wire->sym; - - switch (wire->match & XCB_XKB_SYM_INTERP_MATCH_OP_MASK) { - case XCB_XKB_SYM_INTERPRET_MATCH_NONE_OF: - sym_interpret->match = MATCH_NONE; - break; - case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF_OR_NONE: - sym_interpret->match = MATCH_ANY_OR_NONE; - break; - case XCB_XKB_SYM_INTERPRET_MATCH_ANY_OF: - sym_interpret->match = MATCH_ANY; - break; - case XCB_XKB_SYM_INTERPRET_MATCH_ALL_OF: - sym_interpret->match = MATCH_ALL; - break; - case XCB_XKB_SYM_INTERPRET_MATCH_EXACTLY: - sym_interpret->match = MATCH_EXACTLY; - break; - } - - sym_interpret->level_one_only = - (wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY); - sym_interpret->mods = wire->mods; - - if (wire->virtualMod == NO_MODIFIER) - sym_interpret->virtual_mod = XKB_MOD_INVALID; - else - sym_interpret->virtual_mod = NUM_REAL_MODS + wire->virtualMod; - - sym_interpret->repeat = (wire->flags & 0x01); - translate_action(&sym_interpret->action, - (xcb_xkb_action_t *) &wire->action); - - xcb_xkb_sym_interpret_next(&iter); - } - - return true; - -fail: - return false; -} - -static bool -get_compat_map(struct xkb_keymap *keymap, xcb_connection_t *conn, - uint16_t device_id) -{ - xcb_xkb_get_compat_map_cookie_t cookie = - xcb_xkb_get_compat_map(conn, device_id, 0, true, 0, 0); - xcb_xkb_get_compat_map_reply_t *reply = - xcb_xkb_get_compat_map_reply(conn, cookie, NULL); - - FAIL_IF_BAD_REPLY(reply, "XkbGetCompatMap"); - - if (!get_sym_interprets(keymap, conn, reply)) - goto fail; - - free(reply); - return true; - -fail: - free(reply); - return false; -} - -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) -{ - int key_type_names_length = - xcb_xkb_get_names_value_list_type_names_length(reply, list); - xcb_atom_t *key_type_names_iter = - xcb_xkb_get_names_value_list_type_names(list); - int n_levels_per_type_length = - xcb_xkb_get_names_value_list_n_levels_per_type_length(reply, list); - uint8_t *n_levels_per_type_iter = - xcb_xkb_get_names_value_list_n_levels_per_type(list); - xcb_atom_t *kt_level_names_iter = - xcb_xkb_get_names_value_list_kt_level_names(list); - - FAIL_UNLESS(reply->nTypes == keymap->num_types); - FAIL_UNLESS(key_type_names_length == n_levels_per_type_length); - - for (int i = 0; i < key_type_names_length; i++) { - xcb_atom_t wire_type_name = *key_type_names_iter; - uint8_t wire_num_levels = *n_levels_per_type_iter; - struct xkb_key_type *type = &keymap->types[i]; - - /* Levels must have names. */ - FAIL_UNLESS(type->num_levels == wire_num_levels); - - ALLOC_OR_FAIL(type->level_names, type->num_levels); - - if (!adopt_atom(keymap->ctx, conn, wire_type_name, &type->name)) - goto fail; - - if (!adopt_atoms(keymap->ctx, conn, - kt_level_names_iter, type->level_names, - wire_num_levels)) - goto fail; - - kt_level_names_iter += wire_num_levels; - key_type_names_iter++; - n_levels_per_type_iter++; - } - - return true; - -fail: - return false; -} - -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) -{ - xcb_atom_t *iter = xcb_xkb_get_names_value_list_indicator_names(list); - - FAIL_UNLESS(msb_pos(reply->indicators) <= keymap->num_leds); - - for (unsigned i = 0; i < NUM_INDICATORS; i++) { - if (reply->indicators & (1u << i)) { - xcb_atom_t wire = *iter; - struct xkb_led *led = &keymap->leds[i]; - - if (!adopt_atom(keymap->ctx, conn, wire, &led->name)) - return false; - - iter++; - } - } - - return true; - -fail: - return false; -} - -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) -{ - xcb_atom_t *iter = xcb_xkb_get_names_value_list_virtual_mod_names(list); - - /* - * GetMap's reply->virtualMods is always 0xffff. This one really - * tells us which vmods exist (a vmod must have a name), so we fix - * up the size here. - */ - keymap->mods.num_mods = - NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS); - - for (unsigned i = 0; i < NUM_VMODS; i++) { - if (reply->virtualMods & (1u << i)) { - xcb_atom_t wire = *iter; - struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i]; - - if (!adopt_atom(keymap->ctx, conn, wire, &mod->name)) - return false; - - iter++; - } - } - - return true; -} - -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) -{ - int length = xcb_xkb_get_names_value_list_groups_length(reply, list); - xcb_atom_t *iter = xcb_xkb_get_names_value_list_groups(list); - - keymap->num_group_names = msb_pos(reply->groupNames); - ALLOC_OR_FAIL(keymap->group_names, keymap->num_group_names); - - if (!adopt_atoms(keymap->ctx, conn, - iter, keymap->group_names, length)) - goto fail; - - return true; - -fail: - return false; -} - -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) -{ - int length = xcb_xkb_get_names_value_list_key_names_length(reply, list); - xcb_xkb_key_name_iterator_t iter = - xcb_xkb_get_names_value_list_key_names_iterator(reply, list); - - FAIL_UNLESS(reply->minKeyCode == keymap->min_key_code); - FAIL_UNLESS(reply->maxKeyCode == keymap->max_key_code); - FAIL_UNLESS(reply->firstKey == keymap->min_key_code); - FAIL_UNLESS(reply->firstKey + reply->nKeys - 1U == keymap->max_key_code); - - for (int i = 0; i < length; i++) { - xcb_xkb_key_name_t *wire = iter.data; - xkb_atom_t *key_name = &keymap->keys[reply->firstKey + i].name; - - if (wire->name[0] == '\0') { - *key_name = XKB_ATOM_NONE; - } - else { - *key_name = xkb_atom_intern(keymap->ctx, wire->name, - strnlen(wire->name, - XCB_XKB_CONST_KEY_NAME_LENGTH)); - if (!*key_name) - return false; - } - - xcb_xkb_key_name_next(&iter); - } - - return true; - -fail: - return false; -} - -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) -{ - int length = xcb_xkb_get_names_value_list_key_aliases_length(reply, list); - xcb_xkb_key_alias_iterator_t iter = - xcb_xkb_get_names_value_list_key_aliases_iterator(reply, list); - - keymap->num_key_aliases = reply->nKeyAliases; - ALLOC_OR_FAIL(keymap->key_aliases, keymap->num_key_aliases); - - for (int i = 0; i < length; i++) { - xcb_xkb_key_alias_t *wire = iter.data; - struct xkb_key_alias *alias = &keymap->key_aliases[i]; - - alias->real = - xkb_atom_intern(keymap->ctx, wire->real, - strnlen(wire->real, XCB_XKB_CONST_KEY_NAME_LENGTH)); - alias->alias = - xkb_atom_intern(keymap->ctx, wire->alias, - strnlen(wire->alias, XCB_XKB_CONST_KEY_NAME_LENGTH)); - if (!alias->real || !alias->alias) - goto fail; - - xcb_xkb_key_alias_next(&iter); - } - - return true; - -fail: - return false; -} - -static bool -get_names(struct xkb_keymap *keymap, xcb_connection_t *conn, - uint16_t device_id) -{ - static const xcb_xkb_name_detail_t wanted = - (XCB_XKB_NAME_DETAIL_KEYCODES | - XCB_XKB_NAME_DETAIL_SYMBOLS | - XCB_XKB_NAME_DETAIL_TYPES | - XCB_XKB_NAME_DETAIL_COMPAT | - XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | - XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | - XCB_XKB_NAME_DETAIL_INDICATOR_NAMES | - XCB_XKB_NAME_DETAIL_KEY_NAMES | - XCB_XKB_NAME_DETAIL_KEY_ALIASES | - XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES | - XCB_XKB_NAME_DETAIL_GROUP_NAMES); - static const xcb_xkb_name_detail_t required = - (XCB_XKB_NAME_DETAIL_KEY_TYPE_NAMES | - XCB_XKB_NAME_DETAIL_KT_LEVEL_NAMES | - XCB_XKB_NAME_DETAIL_KEY_NAMES | - XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES); - - xcb_xkb_get_names_cookie_t cookie = - xcb_xkb_get_names(conn, device_id, wanted); - xcb_xkb_get_names_reply_t *reply = - xcb_xkb_get_names_reply(conn, cookie, NULL); - xcb_xkb_get_names_value_list_t list; - - FAIL_IF_BAD_REPLY(reply, "XkbGetNames"); - - FAIL_UNLESS((reply->which & required) == required); - - xcb_xkb_get_names_value_list_unpack(xcb_xkb_get_names_value_list(reply), - reply->nTypes, - reply->indicators, - reply->virtualMods, - reply->groupNames, - reply->nKeys, - reply->nKeyAliases, - reply->nRadioGroups, - reply->which, - &list); - - if (!get_atom_name(conn, list.keycodesName, &keymap->keycodes_section_name) || - !get_atom_name(conn, list.symbolsName, &keymap->symbols_section_name) || - !get_atom_name(conn, list.typesName, &keymap->types_section_name) || - !get_atom_name(conn, list.compatName, &keymap->compat_section_name) || - !get_type_names(keymap, conn, reply, &list) || - !get_indicator_names(keymap, conn, reply, &list) || - !get_vmod_names(keymap, conn, reply, &list) || - !get_group_names(keymap, conn, reply, &list) || - !get_key_names(keymap, conn, reply, &list) || - !get_aliases(keymap, conn, reply, &list)) - goto fail; - - XkbEscapeMapName(keymap->keycodes_section_name); - XkbEscapeMapName(keymap->symbols_section_name); - XkbEscapeMapName(keymap->types_section_name); - XkbEscapeMapName(keymap->compat_section_name); - - free(reply); - return true; - -fail: - free(reply); - return false; -} - -static bool -get_controls(struct xkb_keymap *keymap, xcb_connection_t *conn, - uint16_t device_id) -{ - xcb_xkb_get_controls_cookie_t cookie = - xcb_xkb_get_controls(conn, device_id); - xcb_xkb_get_controls_reply_t *reply = - xcb_xkb_get_controls_reply(conn, cookie, NULL); - - FAIL_IF_BAD_REPLY(reply, "XkbGetControls"); - FAIL_UNLESS(reply->numGroups > 0 && reply->numGroups <= 4); - - keymap->enabled_ctrls = translate_controls_mask(reply->enabledControls); - keymap->num_groups = reply->numGroups; - - FAIL_UNLESS(keymap->max_key_code < XCB_XKB_CONST_PER_KEY_BIT_ARRAY_SIZE * 8); - - for (xkb_keycode_t i = keymap->min_key_code; i <= keymap->max_key_code; i++) - keymap->keys[i].repeats = (reply->perKeyRepeat[i / 8] & (1 << (i % 8))); - - free(reply); - return true; - -fail: - free(reply); - return false; -} - -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) -{ - struct xkb_keymap *keymap; - const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1; - - if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) { - log_err_func(ctx, "unrecognized flags: %#x\n", flags); - return NULL; - } - - if (device_id < 0 || device_id > 127) { - log_err_func(ctx, "illegal device ID: %d\n", device_id); - return NULL; - } - - keymap = xkb_keymap_new(ctx, format, flags); - if (!keymap) - return NULL; - - if (!get_map(keymap, conn, device_id) || - !get_indicator_map(keymap, conn, device_id) || - !get_compat_map(keymap, conn, device_id) || - !get_names(keymap, conn, device_id) || - !get_controls(keymap, conn, device_id)) { - xkb_keymap_unref(keymap); - return NULL; - } - - return keymap; -} |