* DEALINGS IN THE SOFTWARE.
*/
+#include "config.h"
+
#include "x11-priv.h"
/*
* References for the lonesome traveler:
* Xkb protocol specification:
- * http://www.x.org/releases/current/doc/kbproto/xkbproto.html
+ * 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:
/* Constants from /usr/include/X11/extensions/XKB.h */
/* XkbNumModifiers. */
-#define NUM_REAL_MODS 8
+#define NUM_REAL_MODS 8u
/* XkbNumVirtualMods. */
-#define NUM_VMODS 16
+#define NUM_VMODS 16u
/* XkbNoModifier. */
#define NO_MODIFIER 0xff
/* XkbNumIndicators. */
-#define NUM_INDICATORS 32
+#define NUM_INDICATORS 32u
/* XkbAllIndicatorsMask. */
#define ALL_INDICATORS_MASK 0xffffffff
* 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, \
} \
} 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 enum xkb_action_controls
-translate_controls_mask(uint16_t wire)
+translate_controls_mask(uint32_t wire)
{
enum xkb_action_controls ret = 0;
if (wire & XCB_XKB_BOOL_CTRL_REPEAT_KEYS)
case XCB_XKB_SA_TYPE_MOVE_PTR:
action->type = ACTION_TYPE_PTR_MOVE;
- action->ptr.x = (wire->moveptr.xLow | (wire->moveptr.xHigh << 8));
- action->ptr.y = (wire->moveptr.yLow | (wire->moveptr.yHigh << 8));
+ 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_NO_ACCEL;
+ 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->screen.screen = wire->switchscreen.newScreen;
- if (wire->switchscreen.flags & XCB_XKB_SWITCH_SCREEN_FLAG_APPLICATION)
+ 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;
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;
}
}
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;
+ for (xkb_layout_index_t group = 0; group < key->num_groups; group++) {
+ for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) {
+ xcb_keysym_t wire_keysym = *syms_iter;
- 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;
- }
+ 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++;
+ syms_iter++;
+ }
}
}
uint8_t wire_count = *acts_count_iter;
struct xkb_key *key = &keymap->keys[reply->firstKeyAction + i];
+ FAIL_UNLESS((unsigned) syms_length == wire_sym_map->width * key->num_groups);
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 (wire_count != 0) {
+ for (xkb_layout_index_t group = 0; group < key->num_groups; group++) {
+ for (xkb_level_index_t level = 0; level < wire_sym_map->width; level++) {
+ xcb_xkb_action_t *wire_action = acts_iter.data;
- if (level < key->groups[group].type->num_levels) {
- union xkb_action *action =
- &key->groups[group].levels[level].action;
+ if (level < key->groups[group].type->num_levels) {
+ union xkb_action *action = &key->groups[group].levels[level].action;
- translate_action(action, wire_action);
- }
+ translate_action(action, wire_action);
+ }
- xcb_xkb_action_next(&acts_iter);
+ xcb_xkb_action_next(&acts_iter);
+ }
+ }
}
acts_count_iter++;
{
uint8_t *iter = xcb_xkb_get_map_map_vmods_rtrn(map);
- darray_resize0(keymap->mods,
- NUM_REAL_MODS + msb_pos(reply->virtualMods));
+ keymap->mods.num_mods =
+ NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
- for (int i = 0; i < NUM_VMODS; i++) {
- if (reply->virtualMods & (1 << i)) {
+ for (unsigned i = 0; i < NUM_VMODS; i++) {
+ if (reply->virtualMods & (1u << i)) {
uint8_t wire = *iter;
- struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i);
+ struct xkb_mod *mod = &keymap->mods.mods[NUM_REAL_MODS + i];
mod->type = MOD_VIRT;
mod->mapping = translate_mods(wire, 0, 0);
for (int i = 0; i < length; i++) {
xcb_xkb_set_explicit_t *wire = iter.data;
- struct xkb_key *key = &keymap->keys[wire->keycode];
+ 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;
for (int i = 0; i < length; i++) {
xcb_xkb_key_mod_map_t *wire = iter.data;
- struct xkb_key *key = &keymap->keys[wire->keycode];
+ 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);
for (int i = 0; i < length; i++) {
xcb_xkb_key_v_mod_map_t *wire = iter.data;
- struct xkb_key *key = &keymap->keys[wire->keycode];
+ 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);
}
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),
xcb_xkb_indicator_map_iterator_t iter =
xcb_xkb_get_indicator_map_maps_iterator(reply);
- darray_resize0(keymap->leds, msb_pos(reply->which));
+ keymap->num_leds = msb_pos(reply->which);
- for (int i = 0; i < NUM_INDICATORS; i++) {
+ 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 = &darray_item(keymap->leds, i);
+ struct xkb_led *led = &keymap->leds[i];
if (wire->whichGroups & XCB_XKB_IM_GROUPS_WHICH_USE_BASE)
led->which_groups |= XKB_STATE_LAYOUT_DEPRESSED;
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);
}
sym_interpret->level_one_only =
- !!(wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY);
+ (wire->match & XCB_XKB_SYM_INTERP_MATCH_LEVEL_ONE_ONLY);
sym_interpret->mods = wire->mods;
if (wire->virtualMod == NO_MODIFIER)
else
sym_interpret->virtual_mod = NUM_REAL_MODS + wire->virtualMod;
- sym_interpret->repeat = !!(wire->flags & 0x01);
+ sym_interpret->repeat = (wire->flags & 0x01);
translate_action(&sym_interpret->action,
(xcb_xkb_action_t *) &wire->action);
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);
}
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)
{
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;
key_type_names_iter++;
n_levels_per_type_iter++;
}
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)
{
xcb_atom_t *iter = xcb_xkb_get_names_value_list_indicator_names(list);
- FAIL_UNLESS(msb_pos(reply->indicators) <= (int) darray_size(keymap->leds));
+ FAIL_UNLESS(msb_pos(reply->indicators) <= keymap->num_leds);
- for (int i = 0; i < NUM_INDICATORS; i++) {
+ for (unsigned i = 0; i < NUM_INDICATORS; i++) {
if (reply->indicators & (1u << i)) {
xcb_atom_t wire = *iter;
- struct xkb_led *led = &darray_item(keymap->leds, i);
+ 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++;
}
}
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)
{
* tells us which vmods exist (a vmod must have a name), so we fix
* up the size here.
*/
- darray_resize0(keymap->mods, NUM_REAL_MODS + msb_pos(reply->virtualMods));
+ keymap->mods.num_mods =
+ NUM_REAL_MODS + MIN(msb_pos(reply->virtualMods), NUM_VMODS);
- for (int i = 0; i < NUM_VMODS; i++) {
- if (reply->virtualMods & (1 << i)) {
+ for (unsigned i = 0; i < NUM_VMODS; i++) {
+ if (reply->virtualMods & (1u << i)) {
xcb_atom_t wire = *iter;
- struct xkb_mod *mod = &darray_item(keymap->mods, NUM_REAL_MODS + i);
+ 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++;
}
}
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)
{
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;
}
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 required_names =
- (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);
-
- xcb_xkb_get_names_cookie_t cookie =
- xcb_xkb_get_names(conn, device_id, required_names);
+ 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");
- if ((reply->which & required_names) != required_names)
- goto fail;
+ 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);
- 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;
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);
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)));
+ keymap->keys[i].repeats = (reply->perKeyRepeat[i / 8] & (1 << (i % 8)));
free(reply);
return true;
struct xkb_keymap *keymap;
const enum xkb_keymap_format format = XKB_KEYMAP_FORMAT_TEXT_V1;
- if (flags & ~(XKB_MAP_COMPILE_PLACEHOLDER)) {
+ if (flags & ~(XKB_KEYMAP_COMPILE_NO_FLAGS)) {
log_err_func(ctx, "unrecognized flags: %#x\n", flags);
return NULL;
}
- if (device_id < 0 || device_id > 255) {
+ if (device_id < 0 || device_id > 127) {
log_err_func(ctx, "illegal device ID: %d\n", device_id);
return NULL;
}
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;
}