diff options
Diffstat (limited to 'src/x11/keymap.c')
-rw-r--r-- | src/x11/keymap.c | 196 |
1 files changed, 111 insertions, 85 deletions
diff --git a/src/x11/keymap.c b/src/x11/keymap.c index f5b368f..473a89d 100644 --- a/src/x11/keymap.c +++ b/src/x11/keymap.c @@ -88,6 +88,33 @@ } \ } while (0) +static const xcb_xkb_map_part_t get_map_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); + +static const xcb_xkb_name_detail_t get_names_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 get_names_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); + static xkb_mod_mask_t translate_mods(uint8_t rmods, uint16_t vmods_low, uint16_t vmods_high) @@ -645,26 +672,15 @@ fail: } static bool -get_map(struct xkb_keymap *keymap, xcb_connection_t *conn, uint16_t device_id) +get_map(struct xkb_keymap *keymap, xcb_connection_t *conn, + xcb_xkb_get_map_cookie_t cookie) { - 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) + if ((reply->present & get_map_required_components) != get_map_required_components) goto fail; xcb_xkb_get_map_map_unpack(xcb_xkb_get_map_map(reply), @@ -749,10 +765,8 @@ get_indicators(struct xkb_keymap *keymap, xcb_connection_t *conn, 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_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); @@ -831,10 +845,8 @@ fail: 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_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); @@ -852,7 +864,7 @@ fail: } static bool -get_type_names(struct xkb_keymap *keymap, xcb_connection_t *conn, +get_type_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { @@ -880,13 +892,11 @@ get_type_names(struct xkb_keymap *keymap, xcb_connection_t *conn, 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; + x11_atom_interner_adopt_atom(interner, wire_type_name, &type->name); + for (size_t j = 0; j < wire_num_levels; j++) { + x11_atom_interner_adopt_atom(interner, kt_level_names_iter[j], + &type->level_names[j]); + } type->num_level_names = type->num_levels; kt_level_names_iter += wire_num_levels; @@ -901,7 +911,8 @@ fail: } static bool -get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn, +get_indicator_names(struct xkb_keymap *keymap, + struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { @@ -914,8 +925,7 @@ get_indicator_names(struct xkb_keymap *keymap, xcb_connection_t *conn, xcb_atom_t wire = *iter; struct xkb_led *led = &keymap->leds[i]; - if (!adopt_atom(keymap->ctx, conn, wire, &led->name)) - return false; + x11_atom_interner_adopt_atom(interner, wire, &led->name); iter++; } @@ -928,7 +938,7 @@ fail: } static bool -get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn, +get_vmod_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { @@ -947,8 +957,7 @@ get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn, 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; + x11_atom_interner_adopt_atom(interner, wire, &mod->name); iter++; } @@ -958,7 +967,7 @@ get_vmod_names(struct xkb_keymap *keymap, xcb_connection_t *conn, } static bool -get_group_names(struct xkb_keymap *keymap, xcb_connection_t *conn, +get_group_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, xcb_xkb_get_names_reply_t *reply, xcb_xkb_get_names_value_list_t *list) { @@ -968,9 +977,10 @@ get_group_names(struct xkb_keymap *keymap, xcb_connection_t *conn, 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; + for (int i = 0; i < length; i++) { + x11_atom_interner_adopt_atom(interner, iter[i], + &keymap->group_names[i]); + } return true; @@ -1051,36 +1061,17 @@ fail: } static bool -get_names(struct xkb_keymap *keymap, xcb_connection_t *conn, - uint16_t device_id) +get_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner, + xcb_xkb_get_names_cookie_t cookie) { - 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_connection_t *conn = interner->conn; 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); + FAIL_UNLESS((reply->which & get_names_required) == get_names_required); xcb_xkb_get_names_value_list_unpack(xcb_xkb_get_names_value_list(reply), reply->nTypes, @@ -1093,23 +1084,22 @@ get_names(struct xkb_keymap *keymap, xcb_connection_t *conn, 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) || + x11_atom_interner_get_escaped_atom_name(interner, list.keycodesName, + &keymap->keycodes_section_name); + x11_atom_interner_get_escaped_atom_name(interner, list.symbolsName, + &keymap->symbols_section_name); + x11_atom_interner_get_escaped_atom_name(interner, list.typesName, + &keymap->types_section_name); + x11_atom_interner_get_escaped_atom_name(interner, list.compatName, + &keymap->compat_section_name); + if (!get_type_names(keymap, interner, reply, &list) || + !get_indicator_names(keymap, interner, reply, &list) || + !get_vmod_names(keymap, interner, reply, &list) || + !get_group_names(keymap, interner, 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; @@ -1120,10 +1110,8 @@ fail: 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_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); @@ -1169,14 +1157,52 @@ xkb_x11_keymap_new_from_device(struct xkb_context *ctx, 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; - } + struct x11_atom_interner interner; + x11_atom_interner_init(&interner, ctx, conn); + + /* + * Send all requests together so only one roundtrip is needed + * to get the replies. + */ + xcb_xkb_get_map_cookie_t map_cookie = + xcb_xkb_get_map(conn, device_id, get_map_required_components, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + xcb_xkb_get_indicator_map_cookie_t indicator_map_cookie = + xcb_xkb_get_indicator_map(conn, device_id, ALL_INDICATORS_MASK); + xcb_xkb_get_compat_map_cookie_t compat_map_cookie = + xcb_xkb_get_compat_map(conn, device_id, 0, true, 0, 0); + xcb_xkb_get_names_cookie_t names_cookie = + xcb_xkb_get_names(conn, device_id, get_names_wanted); + xcb_xkb_get_controls_cookie_t controls_cookie = + xcb_xkb_get_controls(conn, device_id); + + if (!get_map(keymap, conn, map_cookie)) + goto err_map; + if (!get_indicator_map(keymap, conn, indicator_map_cookie)) + goto err_indicator_map; + if (!get_compat_map(keymap, conn, compat_map_cookie)) + goto err_compat_map; + if (!get_names(keymap, &interner, names_cookie)) + goto err_names; + if (!get_controls(keymap, conn, controls_cookie)) + goto err_controls; + x11_atom_interner_round_trip(&interner); + if (interner.had_error) + goto err_interner; return keymap; + +err_map: + xcb_discard_reply(conn, indicator_map_cookie.sequence); +err_indicator_map: + xcb_discard_reply(conn, compat_map_cookie.sequence); +err_compat_map: + xcb_discard_reply(conn, names_cookie.sequence); +err_names: + xcb_discard_reply(conn, controls_cookie.sequence); +err_controls: + x11_atom_interner_round_trip(&interner); +err_interner: + xkb_keymap_unref(keymap); + return NULL; } |