Last active
June 16, 2020 02:46
-
-
Save bluetech/6038239 to your computer and use it in GitHub Desktop.
xcb-xkb XkbGetMap test code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <err.h> | |
#include <stdbool.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <xcb/xcb.h> | |
#include <xcb/xkb.h> | |
#include <X11/Xlib.h> | |
#include <X11/XKBlib.h> | |
#include <xkbcommon/xkbcommon.h> | |
static void cleanup_free_fn(void *p) { free(*(void **)p); } | |
#define _cleanup_free_ __attribute__((cleanup(cleanup_free_fn))) | |
struct ctx { | |
xcb_connection_t *conn; | |
}; | |
static void | |
setup_xkb(struct ctx *ctx) | |
{ | |
{ | |
const xcb_query_extension_reply_t *reply; | |
reply = xcb_get_extension_data(ctx->conn, &xcb_xkb_id); | |
if (!reply) | |
errx(1, "no XKB in X server"); | |
} | |
{ | |
xcb_xkb_use_extension_cookie_t cookie; | |
_cleanup_free_ xcb_xkb_use_extension_reply_t *reply = NULL; | |
cookie = xcb_xkb_use_extension(ctx->conn, | |
XCB_XKB_MAJOR_VERSION, | |
XCB_XKB_MINOR_VERSION); | |
reply = xcb_xkb_use_extension_reply(ctx->conn, cookie, NULL); | |
if (!reply) | |
errx(1, "couldn't use XKB extension"); | |
if (!reply->supported) | |
errx(1, "the XKB extension is not supported in X server"); | |
} | |
} | |
static const char * | |
get_atom_name(struct ctx *ctx, xcb_atom_t atom) | |
{ | |
_cleanup_free_ xcb_get_atom_name_reply_t *reply = NULL; | |
char *name; | |
int length; | |
static char buf[1024]; /* FIXME */ | |
if (atom == 0) | |
return "<empty>"; | |
{ | |
xcb_get_atom_name_cookie_t cookie; | |
_cleanup_free_ xcb_generic_error_t *error = NULL; | |
cookie = xcb_get_atom_name(ctx->conn, atom); | |
reply = xcb_get_atom_name_reply(ctx->conn, cookie, &error); | |
if (!reply || error) { | |
/* warnx("couldn't get name of atom %d", atom); */ | |
return "<invalid>"; | |
} | |
} | |
length = xcb_get_atom_name_name_length(reply); | |
name = xcb_get_atom_name_name(reply); | |
snprintf(buf, sizeof(buf), "%.*s", length, name); | |
return buf; | |
} | |
#define ALL_COMPONENTS_MASK \ | |
(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_KEY_BEHAVIORS | \ | |
XCB_XKB_MAP_PART_VIRTUAL_MODS | \ | |
XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP) | |
static void | |
get_map(struct ctx *ctx) | |
{ | |
_cleanup_free_ xcb_xkb_get_map_reply_t *reply = NULL; | |
{ | |
xcb_xkb_get_map_cookie_t cookie; | |
_cleanup_free_ xcb_generic_error_t *error = NULL; | |
/* Send the XkbGetMap request. */ | |
cookie = xcb_xkb_get_map(ctx->conn, | |
XCB_XKB_ID_USE_CORE_KBD, | |
ALL_COMPONENTS_MASK, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0, | |
0); | |
reply = xcb_xkb_get_map_reply(ctx->conn, cookie, &error); | |
if (!reply || error) | |
errx(1, "couldn't get get_map reply: error_code %d", error->error_code); | |
if ((reply->present & ALL_COMPONENTS_MASK) != ALL_COMPONENTS_MASK) | |
errx(1, "didn't get all components"); | |
} | |
printf("minKeyCode: %d\n", reply->minKeyCode); | |
printf("maxKeyCode: %d\n", reply->maxKeyCode); | |
/* Get the map itself, with all the details. */ | |
xcb_xkb_get_map_map_t map; | |
{ | |
void *buffer; | |
buffer = xcb_xkb_get_map_map(reply); | |
xcb_xkb_get_map_map_unpack(buffer, | |
reply->nTypes, | |
reply->nKeySyms, | |
reply->nKeyActions, | |
reply->totalActions, | |
reply->totalKeyBehaviors, | |
reply->nVModMapKeys, | |
reply->totalKeyExplicit, | |
reply->totalModMapKeys, | |
reply->totalVModMapKeys, | |
reply->present, | |
&map); | |
} | |
/* Dump types. */ | |
{ | |
int length; | |
xcb_xkb_key_type_iterator_t iter; | |
printf("firstType: %d\n", reply->firstType); | |
printf("totalType: %d\n", reply->totalTypes); | |
printf("nTypes: %d\n", reply->nTypes); | |
length = xcb_xkb_get_map_map_types_rtrn_length(reply, &map); | |
iter = xcb_xkb_get_map_map_types_rtrn_iterator(reply, &map); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_key_type_t *type = iter.data; | |
printf("type %d:\n", reply->firstType + i); | |
printf("\tmods_mask: %d\n", type->mods_mask); | |
printf("\tmods_mods: %d\n", type->mods_mods); | |
printf("\tmods_vmods: %d\n", type->mods_vmods); | |
printf("\tnumLevels: %d\n", type->numLevels); | |
printf("\thasPreserve: %d\n", type->hasPreserve); | |
/* Dump type's entries. */ | |
{ | |
int length2; | |
xcb_xkb_kt_map_entry_iterator_t iter2; | |
length2 = xcb_xkb_key_type_map_length(type); | |
iter2 = xcb_xkb_key_type_map_iterator(type); | |
for (int j = 0; j < length2; j++) { | |
xcb_xkb_kt_map_entry_t *entry = iter2.data; | |
printf("\tentry %d:\n", j); | |
printf("\t\tactive: %d\n", entry->active); | |
printf("\t\tlevel: %d\n", entry->level); | |
printf("\t\tmods_mask: %d\n", entry->mods_mask); | |
printf("\t\tmods_mods: %d\n", entry->mods_mods); | |
printf("\t\tmods_vmods: %d\n", entry->mods_vmods); | |
xcb_xkb_kt_map_entry_next(&iter2); | |
} | |
} | |
/* Dump type's preserve entries. */ | |
{ | |
int length2; | |
xcb_xkb_mod_def_iterator_t iter2; | |
length2 = xcb_xkb_key_type_preserve_length(type); | |
iter2 = xcb_xkb_key_type_preserve_iterator(type); | |
for (int j = 0; j < length2; j++) { | |
xcb_xkb_mod_def_t *preserve = iter2.data; | |
printf("\tpreserve %d:\n", j); | |
printf("\t\tmask: %d\n", preserve->mask); | |
printf("\t\trealMods: %d\n", preserve->realMods); | |
printf("\t\tvmods: %d\n", preserve->vmods); | |
xcb_xkb_mod_def_next(&iter2); | |
} | |
} | |
xcb_xkb_key_type_next(&iter); | |
} | |
} | |
/* Dump key sym maps. */ | |
{ | |
int length; | |
xcb_xkb_key_sym_map_iterator_t iter; | |
printf("firstKeySym: %d\n", reply->firstKeySym); | |
printf("totalSyms: %d\n", reply->totalSyms); | |
printf("nKeySyms: %d\n", reply->nKeySyms); | |
length = xcb_xkb_get_map_map_syms_rtrn_length(reply, &map); | |
iter = xcb_xkb_get_map_map_syms_rtrn_iterator(reply, &map); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_key_sym_map_t *sym_map = iter.data; | |
printf("sym_map %d:\n", reply->firstKeySym + i); | |
/* TODO: kt_index[4] */ | |
printf("\tgroupInfo: %d\n", sym_map->groupInfo); | |
printf("\twidth: %d\n", sym_map->width); | |
printf("\tnSyms: %d\n", sym_map->nSyms); | |
/* Dump sym map's keysyms. */ | |
printf("\tkeysyms:\n"); | |
{ | |
int length2; | |
xcb_keysym_t *syms; | |
length2 = xcb_xkb_key_sym_map_syms_length(sym_map); | |
syms = xcb_xkb_key_sym_map_syms(sym_map); | |
for (int j = 0; j < length2; j++) { | |
xcb_keysym_t keysym = syms[j]; | |
char name[64]; | |
xkb_keysym_get_name(keysym, name, sizeof(name)); | |
printf("\t\t%d %s\n", keysym, name); | |
} | |
} | |
xcb_xkb_key_sym_map_next(&iter); | |
} | |
} | |
/* Dump key actions. */ | |
{ | |
printf("firstKeyAction: %d\n", reply->firstKeyAction); | |
printf("totalActions: %d\n", reply->totalActions); | |
printf("nKeyActions: %d\n", reply->nKeyActions); | |
/* Dump number of actions bound to the keys. */ | |
{ | |
int length; | |
uint8_t *iter; | |
length = xcb_xkb_get_map_map_acts_rtrn_count_length(reply, &map); | |
iter = xcb_xkb_get_map_map_acts_rtrn_count(&map); | |
for (int i = 0 ; i < length; i++) { | |
uint8_t count = *iter; | |
printf("action count %d:\n", reply->firstKeyAction + i); | |
printf("\tcount: %d\n", count); | |
iter++; | |
} | |
} | |
/* Dump the actions array. */ | |
{ | |
int length; | |
xcb_xkb_action_iterator_t iter; | |
length = xcb_xkb_get_map_map_acts_rtrn_acts_length(reply, &map); | |
iter = xcb_xkb_get_map_map_acts_rtrn_acts_iterator(reply, &map); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_action_t *action = iter.data; | |
/* TODO: action union. */ | |
printf("action %d:\n", i); | |
printf("\ttype: %d\n", action->type); | |
xcb_xkb_action_next(&iter); | |
} | |
} | |
} | |
/* Dump key behaviors. */ | |
{ | |
int length; | |
xcb_xkb_set_behavior_iterator_t iter; | |
printf("firstKeyBehavior: %d\n", reply->firstKeyBehavior); | |
printf("nKeyBehaviors: %d\n", reply->nKeyBehaviors); | |
printf("totalKeyBehaviors: %d\n", reply->totalKeyBehaviors); | |
length = xcb_xkb_get_map_map_behaviors_rtrn_length(reply, &map); | |
iter = xcb_xkb_get_map_map_behaviors_rtrn_iterator(reply, &map); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_set_behavior_t *set_behavior = iter.data; | |
xcb_xkb_behavior_t *behavior = &set_behavior->behavior; | |
printf("set_behavior %d:\n", reply->firstKeyBehavior + i); | |
printf("\tkeycode: %d\n", set_behavior->keycode); | |
/* TODO: behavior union. */ | |
printf("\tbehavior type: %d\n", behavior->type); | |
xcb_xkb_set_behavior_next(&iter); | |
} | |
} | |
/* Dump virtual mods. */ | |
{ | |
int length; | |
uint8_t *iter; | |
printf("virtualMods: %x\n", reply->virtualMods); | |
length = xcb_xkb_get_map_map_vmods_rtrn_length(reply, &map); | |
iter = xcb_xkb_get_map_map_vmods_rtrn(&map); | |
printf("length: %d\n", length); | |
for (int i = 0; i < length; i++) { | |
uint8_t vmods = *iter; | |
printf("vmods %d:\n", i); | |
printf("\tmask: %x\n", vmods); | |
iter++; | |
} | |
} | |
/* Dump key explicit masks. */ | |
{ | |
int length; | |
xcb_xkb_set_explicit_iterator_t iter; | |
printf("firstKeyExplicit: %d\n", reply->firstKeyExplicit); | |
printf("nKeyExplicit: %d\n", reply->nKeyExplicit); | |
printf("totalKeyExplicit: %d\n", reply->totalKeyExplicit); | |
length = xcb_xkb_get_map_map_explicit_rtrn_length(reply, &map); | |
iter = xcb_xkb_get_map_map_explicit_rtrn_iterator(reply, &map); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_set_explicit_t *set_explicit = iter.data; | |
printf("set_explicit %d:\n", reply->firstKeyExplicit + i); | |
printf("\tkeycode: %d\n", set_explicit->keycode); | |
printf("\texplicit: %d\n", set_explicit->explicit); | |
xcb_xkb_set_explicit_next(&iter); | |
} | |
} | |
/* Dump mod map keys. */ | |
{ | |
int length; | |
xcb_xkb_key_mod_map_iterator_t iter; | |
printf("firstModMapKey: %d\n", reply->firstModMapKey); | |
printf("nModMapKeys: %d\n", reply->nModMapKeys); | |
printf("totalModMapKeys: %d\n", reply->totalModMapKeys); | |
length = xcb_xkb_get_map_map_modmap_rtrn_length(reply, &map); | |
iter = xcb_xkb_get_map_map_modmap_rtrn_iterator(reply, &map); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_key_mod_map_t *key_mod_map = iter.data; | |
printf("key_mod_map %d:\n", reply->firstModMapKey + i); | |
printf("\tkeycode: %d\n", key_mod_map->keycode); | |
printf("\tmods: %d\n", key_mod_map->mods); | |
xcb_xkb_key_mod_map_next(&iter); | |
} | |
} | |
/* Dump key vmod map keys. */ | |
{ | |
int length; | |
xcb_xkb_key_v_mod_map_iterator_t iter; | |
printf("firstVModMapKey: %d\n", reply->firstVModMapKey); | |
printf("nVModMapKeys: %d\n", reply->nVModMapKeys); | |
printf("totalVModMapKeys: %d\n", reply->totalVModMapKeys); | |
length = xcb_xkb_get_map_map_vmodmap_rtrn_length(reply, &map); | |
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 *key_v_mod_map = iter.data; | |
printf("key_v_mod_map %d:\n", reply->firstVModMapKey + i); | |
printf("\tkeycode: %d\n", key_v_mod_map->keycode); | |
printf("\tvmods: %d\n", key_v_mod_map->vmods); | |
xcb_xkb_key_v_mod_map_next(&iter); | |
} | |
} | |
} | |
#define ALL_INDICATORS 0xffffffff | |
static void | |
get_indicator_map(struct ctx *ctx) | |
{ | |
_cleanup_free_ xcb_xkb_get_indicator_map_reply_t *reply = NULL; | |
{ | |
_cleanup_free_ xcb_generic_error_t *error = NULL; | |
xcb_xkb_get_indicator_map_cookie_t cookie; | |
cookie = xcb_xkb_get_indicator_map(ctx->conn, | |
XCB_XKB_ID_USE_CORE_KBD, | |
ALL_INDICATORS); | |
reply = xcb_xkb_get_indicator_map_reply(ctx->conn, cookie, &error); | |
if (!reply || error) | |
errx(1, "couldn't get get_indicator_map reply"); | |
} | |
printf("which: %x\n", reply->which); | |
printf("realIndicators: %x\n", reply->realIndicators); | |
printf("nIndicators: %d\n", reply->nIndicators); | |
/* Dump indicator maps. */ | |
{ | |
int length; | |
xcb_xkb_indicator_map_iterator_t iter; | |
length = xcb_xkb_get_indicator_map_maps_length(reply); | |
iter = xcb_xkb_get_indicator_map_maps_iterator(reply); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_indicator_map_t *indicator_map = iter.data; | |
printf("indicator_map %d:\n", i); | |
printf("\tflags: %d\n", indicator_map->flags); | |
printf("\twhichGroups: %d\n", indicator_map->whichGroups); | |
printf("\tgroups: %d\n", indicator_map->groups); | |
printf("\twhichMods: %d\n", indicator_map->whichMods); | |
printf("\tmods: %d\n", indicator_map->mods); | |
printf("\trealMods: %d\n", indicator_map->realMods); | |
printf("\tvmods: %d\n", indicator_map->vmods); | |
printf("\tctrls: %d\n", indicator_map->ctrls); | |
xcb_xkb_indicator_map_next(&iter); | |
} | |
} | |
} | |
#define ALL_GROUPS 0xf | |
static void | |
get_compat_map(struct ctx *ctx) | |
{ | |
_cleanup_free_ xcb_xkb_get_compat_map_reply_t *reply = NULL; | |
{ | |
_cleanup_free_ xcb_generic_error_t *error = NULL; | |
xcb_xkb_get_compat_map_cookie_t cookie; | |
cookie = xcb_xkb_get_compat_map(ctx->conn, | |
XCB_XKB_ID_USE_CORE_KBD, | |
ALL_GROUPS, | |
true, | |
0, | |
0); | |
reply = xcb_xkb_get_compat_map_reply(ctx->conn, cookie, &error); | |
if (!reply || error) | |
errx(1, "couldn't get reply for get_compat_map"); | |
} | |
printf("groupsRtrn: %#x\n", reply->groupsRtrn); | |
printf("firstSIRtrn: %d\n", reply->firstSIRtrn); | |
printf("nSIRtrn: %d\n", reply->nSIRtrn); | |
printf("nTotalSI: %d\n", reply->nTotalSI); | |
/* Dump sym interprets. */ | |
{ | |
int length; | |
xcb_xkb_sym_interpret_iterator_t iter; | |
length = xcb_xkb_get_compat_map_si_rtrn_length(reply); | |
iter = xcb_xkb_get_compat_map_si_rtrn_iterator(reply); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_sym_interpret_t *sym_interpret = iter.data; | |
printf("sym_interpret %d\n", reply->firstSIRtrn + i); | |
printf("\tsym: %d\n", sym_interpret->sym); | |
printf("\tmods: %d\n", sym_interpret->mods); | |
printf("\tmatch: %d\n", sym_interpret->match); | |
printf("\tvirtualMod: %d\n", sym_interpret->virtualMod); | |
printf("\tflags: %d\n", sym_interpret->flags); | |
printf("\taction type: %d\n", sym_interpret->action.type); | |
/* TODO: action fields */ | |
xcb_xkb_sym_interpret_next(&iter); | |
} | |
} | |
/* Dump ModMap definitons. */ | |
{ | |
int length; | |
xcb_xkb_mod_def_iterator_t iter; | |
length = xcb_xkb_get_compat_map_group_rtrn_length(reply); | |
iter = xcb_xkb_get_compat_map_group_rtrn_iterator(reply); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_mod_def_t *mod_def = iter.data; | |
printf("mod_def %d\n", i); | |
printf("\tmask: %d\n", mod_def->mask); | |
printf("\trealMods: %d\n", mod_def->realMods); | |
printf("\tvmods: %d\n", mod_def->vmods); | |
xcb_xkb_mod_def_next(&iter); | |
} | |
} | |
} | |
#define ALL_NAME_DETAILS \ | |
(XCB_XKB_NAME_DETAIL_KEYCODES | \ | |
XCB_XKB_NAME_DETAIL_GEOMETRY | \ | |
XCB_XKB_NAME_DETAIL_SYMBOLS | \ | |
XCB_XKB_NAME_DETAIL_PHYS_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_NAME_DETAIL_RG_NAMES) | |
static void | |
get_names(struct ctx *ctx) | |
{ | |
_cleanup_free_ xcb_xkb_get_names_reply_t *reply = NULL; | |
{ | |
_cleanup_free_ xcb_generic_error_t *error = NULL; | |
xcb_xkb_get_names_cookie_t cookie; | |
cookie = xcb_xkb_get_names(ctx->conn, | |
XCB_XKB_ID_USE_CORE_KBD, | |
ALL_NAME_DETAILS); | |
reply = xcb_xkb_get_names_reply(ctx->conn, cookie, &error); | |
if (!reply || error) | |
errx(1, "couldn't get reply for get_names"); | |
} | |
printf("which: %d\n", reply->which); | |
printf("minKeyCode: %d\n", reply->minKeyCode); | |
printf("maxKeyCode: %d\n", reply->maxKeyCode); | |
printf("nTypes: %d\n", reply->nTypes); | |
printf("groupNames: %d\n", reply->groupNames); | |
printf("virtualMods: %d\n", reply->virtualMods); | |
printf("firstKey: %d\n", reply->firstKey); | |
printf("nKeys: %d\n", reply->nKeys); | |
printf("indicators: %d\n", reply->indicators); | |
printf("nRadioGroups: %d\n", reply->nRadioGroups); | |
printf("nKeyAliases: %d\n", reply->nKeyAliases); | |
printf("nKTLevels: %d\n", reply->nKTLevels); | |
xcb_xkb_get_names_value_list_t list; | |
{ | |
void *buffer; | |
buffer = xcb_xkb_get_names_value_list(reply); | |
xcb_xkb_get_names_value_list_unpack(buffer, | |
reply->nTypes, | |
reply->indicators, | |
reply->virtualMods, | |
reply->groupNames, | |
reply->nKeys, | |
reply->nKeyAliases, | |
reply->nRadioGroups, | |
reply->which, | |
&list); | |
} | |
/* Dump section names. */ | |
printf("keycodesName: %s\n", get_atom_name(ctx, list.keycodesName)); | |
printf("geometryName: %s\n", get_atom_name(ctx, list.geometryName)); | |
printf("symbolsName: %s\n", get_atom_name(ctx, list.symbolsName)); | |
printf("physSymbolsName: %s\n", get_atom_name(ctx, list.physSymbolsName)); | |
printf("typesName: %s\n", get_atom_name(ctx, list.typesName)); | |
printf("compatName: %s\n", get_atom_name(ctx, list.compatName)); | |
/* Dump key type names. */ | |
{ | |
int length; | |
xcb_atom_t *iter; | |
length = xcb_xkb_get_names_value_list_type_names_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_type_names(&list); | |
for (int i = 0; i < length; i++) { | |
xcb_atom_t type_name = *iter; | |
printf("type name %d: %s\n", i, get_atom_name(ctx, type_name)); | |
iter++; | |
} | |
} | |
/* Dump how many levels each key type has. */ | |
{ | |
int length; | |
uint8_t *iter; | |
length = xcb_xkb_get_names_value_list_n_levels_per_type_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_n_levels_per_type(&list); | |
for (int i = 0; i < length; i++) { | |
uint8_t n_levels_per_type = *iter; | |
printf("n_levels_per_type %d: %d\n", i, n_levels_per_type); | |
iter++; | |
} | |
} | |
/* Dump key type level names. */ | |
{ | |
int length; | |
xcb_atom_t *iter; | |
length = xcb_xkb_get_names_value_list_kt_level_names_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_kt_level_names(&list); | |
for (int i = 0; i < length; i++) { | |
xcb_atom_t kt_level_name = *iter; | |
printf("kt_level_name %d: %s\n", i, get_atom_name(ctx, kt_level_name)); | |
iter++; | |
} | |
} | |
/* Dump indicator names. */ | |
{ | |
int length; | |
xcb_atom_t *iter; | |
length = xcb_xkb_get_names_value_list_indicator_names_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_indicator_names(&list); | |
for (int i = 0; i < length; i++) { | |
xcb_atom_t indicator_name = *iter; | |
printf("indicator_name %d: %s\n", i, get_atom_name(ctx, indicator_name)); | |
iter++; | |
} | |
} | |
/* Dump virtual modifier names. */ | |
{ | |
int length; | |
xcb_atom_t *iter; | |
length = xcb_xkb_get_names_value_list_virtual_mod_names_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_virtual_mod_names(&list); | |
for (int i = 0; i < length; i++) { | |
xcb_atom_t virtual_mod_name = *iter; | |
printf("virtual_mod_name %d: %s\n", i, get_atom_name(ctx, virtual_mod_name)); | |
iter++; | |
} | |
} | |
/* Dump group names. */ | |
{ | |
int length; | |
xcb_atom_t *iter; | |
length = xcb_xkb_get_names_value_list_groups_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_groups(&list); | |
for (int i = 0; i < length; i++) { | |
xcb_atom_t group_name = *iter; | |
printf("group_name %d: %s\n", i, get_atom_name(ctx, group_name)); | |
iter++; | |
} | |
} | |
/* Dump key names. */ | |
{ | |
int length; | |
xcb_xkb_key_name_iterator_t iter; | |
length = xcb_xkb_get_names_value_list_key_names_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_key_names_iterator(reply, &list); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_key_name_t *key_name = iter.data; | |
/* FIXME: xcb-xkb bug. */ | |
printf("key_name %d: %.4s\n", i, key_name->name); | |
xcb_xkb_key_name_next(&iter); | |
} | |
} | |
/* Dump key aliases. */ | |
{ | |
int length; | |
xcb_xkb_key_alias_iterator_t iter; | |
length = xcb_xkb_get_names_value_list_key_aliases_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_key_aliases_iterator(reply, &list); | |
for (int i = 0; i < length; i++) { | |
xcb_xkb_key_alias_t *alias = iter.data; | |
printf("key_alias %d: real %.4s; alias %.4s\n", i, alias->real, alias->alias); | |
xcb_xkb_key_alias_next(&iter); | |
} | |
} | |
/* Dump radio group names. */ | |
{ | |
int length; | |
xcb_atom_t *iter; | |
length = xcb_xkb_get_names_value_list_radio_group_names_length(reply, &list); | |
iter = xcb_xkb_get_names_value_list_radio_group_names(&list); | |
for (int i = 0; i < length; i++) { | |
xcb_atom_t radio_group_name = *iter; | |
printf("radio_group_name %d: %s\n", i, get_atom_name(ctx, radio_group_name)); | |
iter++; | |
} | |
} | |
} | |
static void | |
get_map_xlib(void) | |
{ | |
Display *dpy; | |
XkbDescPtr desc; | |
dpy = XOpenDisplay(NULL); | |
if (!dpy) | |
errx(1, "couldn't open xlib display"); | |
desc = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd); | |
if (!desc) | |
errx(1, "couldn't get xkb map from xlib"); | |
if (XkbGetIndicatorMap(dpy, XkbAllIndicatorsMask, desc) != Success || | |
XkbGetCompatMap(dpy, XkbAllCompatMask, desc) != Success || | |
/* XkbGetGeometry(dpy, desc) != Success || */ | |
XkbGetNames(dpy, XkbAllNamesMask, desc) != Success) | |
errx(1, "couldn't get xkb map component from xlib"); | |
if (desc->map->modmap) { | |
for (int i = desc->min_key_code; i <= desc->max_key_code; i++) { | |
printf("xlib modmap[%d] = %d\n", i, desc->map->modmap[i]); | |
} | |
} | |
if (desc->server->vmodmap) { | |
for (int i = desc->min_key_code; i <= desc->max_key_code; i++) { | |
printf("xlib vmodmap[%d] = %d\n", i, desc->server->vmodmap[i]); | |
} | |
} | |
if (desc->server->explicit) { | |
for (int i = desc->min_key_code; i <= desc->max_key_code; i++) { | |
printf("xlib explicit[%d] = %d\n", i, desc->server->explicit[i]); | |
} | |
} | |
XCloseDisplay(dpy); | |
} | |
int | |
main(void) | |
{ | |
struct ctx ctx; | |
ctx.conn = xcb_connect(NULL, NULL); | |
if (!ctx.conn) | |
errx(1, "couldn't connect to display"); | |
setup_xkb(&ctx); | |
get_map(&ctx); | |
get_indicator_map(&ctx); | |
get_compat_map(&ctx); | |
get_names(&ctx); | |
/* get_map_xlib(); */ | |
xcb_disconnect(ctx.conn); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment