Skip to content

Instantly share code, notes, and snippets.

@PandorasFox
Last active December 8, 2017 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PandorasFox/a701caba8430d86c3f60d5e8f08b83c1 to your computer and use it in GitHub Desktop.
Save PandorasFox/a701caba8430d86c3f60d5e8f08b83c1 to your computer and use it in GitHub Desktop.
/*
* gcc ./tmp.c -lxcb -lxcb-xkb -lxkbcommon -lxkbcommon-x11 -g -fsanitize=address -fno-omit-frame-pointer
*/
#include <assert.h>
#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 <xkbcommon/xkbcommon.h>
#include <xkbcommon/xkbcommon-x11.h>
struct ctx {
xcb_connection_t *conn;
};
static const char *
get_atom_name(struct ctx *ctx, xcb_atom_t atom) {
xcb_get_atom_name_reply_t *reply = NULL;
char *name;
int length;
static char buf[16]; /* fixme */
if (atom == 0)
return "<empty>";
xcb_get_atom_name_cookie_t cookie;
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)
return "<invalid>";
length = xcb_get_atom_name_name_length(reply);
name = xcb_get_atom_name_name(reply);
snprintf(buf, sizeof(buf), "%.*s", length, name);
free(error);
free(reply);
return buf;
}
#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) {
uint8_t xkb_base_event;
uint8_t xkb_base_error;
if (xkb_x11_setup_xkb_extension(ctx->conn,
XKB_X11_MIN_MAJOR_XKB_VERSION,
XKB_X11_MIN_MINOR_XKB_VERSION,
0,
NULL,
NULL,
&xkb_base_event,
&xkb_base_error) != 1)
errx(EXIT_FAILURE, "Could not setup XKB extension.");
xcb_xkb_get_names_reply_t *reply = NULL;
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");
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 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++;
}
free(reply);
free(error);
}
int main(void) {
struct ctx ctx;
ctx.conn = xcb_connect(NULL, NULL);
if (!ctx.conn)
errx(1, "couldn't connect to display");
get_names(&ctx);
xcb_disconnect(ctx.conn);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment