* 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, \
+ log_err(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, \
"x11: failed to get keymap from X server: unmet condition in %s(): %s\n", \
__func__, STRINGIFY(expr)); \
goto fail; \
#define FAIL_IF_BAD_REPLY(reply, request_name) do { \
if (!reply) { \
- log_err(keymap->ctx, \
+ log_err(keymap->ctx, XKB_LOG_MESSAGE_NO_ID, \
"x11: failed to get keymap from X server: %s request failed\n", \
(request_name)); \
goto fail; \
} \
} 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)
}
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),
ALLOC_OR_FAIL(type->level_names, type->num_levels);
x11_atom_interner_adopt_atom(interner, wire_type_name, &type->name);
- x11_atom_interner_adopt_atoms(interner, kt_level_names_iter,
- type->level_names, wire_num_levels);
+ 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;
keymap->num_group_names = msb_pos(reply->groupNames);
ALLOC_OR_FAIL(keymap->group_names, keymap->num_group_names);
- x11_atom_interner_adopt_atoms(interner, iter, keymap->group_names, length);
+ for (int i = 0; i < length; i++) {
+ x11_atom_interner_adopt_atom(interner, iter[i],
+ &keymap->group_names[i]);
+ }
return true;
static bool
get_names(struct xkb_keymap *keymap, struct x11_atom_interner *interner,
- uint16_t device_id)
+ 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_connection_t *conn = interner->conn;
- 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);
+ 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,
reply->which,
&list);
- xcb_get_atom_name_cookie_t cookies[4];
- get_atom_name(conn, list.keycodesName, &cookies[0]);
- get_atom_name(conn, list.symbolsName, &cookies[1]);
- get_atom_name(conn, list.typesName, &cookies[2]);
- get_atom_name(conn, list.compatName, &cookies[3]);
-
- /* We need to ensure all replies are collected and thus no short-circuit */
- bool atom_success = true;
- atom_success &= get_atom_name_reply(conn, list.keycodesName, cookies[0],
- &keymap->keycodes_section_name);
- atom_success &= get_atom_name_reply(conn, list.symbolsName, cookies[1],
- &keymap->symbols_section_name);
- atom_success &= get_atom_name_reply(conn, list.typesName, cookies[2],
- &keymap->types_section_name);
- atom_success &= get_atom_name_reply(conn, list.compatName, cookies[3],
- &keymap->compat_section_name);
-
- if (!atom_success ||
- !get_type_names(keymap, interner, 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_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;
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_controls_cookie_t get_controls_cookie =
+ 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);
- bool had_error = false;
- had_error |= !get_map(keymap, conn, device_id);
- had_error |= !get_indicator_map(keymap, conn, indicator_map_cookie);
- had_error |= !get_compat_map(keymap, conn, compat_map_cookie);
- had_error |= !get_names(keymap, &interner, device_id);
- had_error |= !get_controls(keymap, conn, get_controls_cookie);
-
+ 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);
- had_error |= interner.had_error;
- if (had_error) {
- xkb_keymap_unref(keymap);
- return NULL;
- }
+ 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;
}