#include #include #include #include #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) /* Offset between evdev keycodes (where KEY_ESCAPE is 1), and the evdev XKB * keycode set (where ESC is 9). */ #define EVDEV_OFFSET 8 int main(int argc, char **argv) { struct xkb_context *ctx; ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!ctx) errx(EXIT_FAILURE, "xkb_context_new failed"); struct xkb_rule_names names = { .rules = "evdev", .model = "pc105", .layout = "us,ru", .variant = NULL, .options = "grp:lctrl_toggle" }; struct xkb_keymap *keymap; keymap = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS); if (!keymap) errx(EXIT_FAILURE, "xkb_keymap_new_from_names failed"); xkb_mod_index_t num_mods = xkb_keymap_num_mods(keymap); for (xkb_keycode_t keycode = 1; keycode < 255; keycode++) { xkb_keycode_t evdev_keycode = keycode + EVDEV_OFFSET; xkb_layout_index_t num_layouts = xkb_keymap_num_layouts_for_key(keymap, evdev_keycode); printf("keycode %3d =", keycode); for (xkb_layout_index_t layout = 0; layout < num_layouts; layout++) { xkb_level_index_t num_levels = xkb_keymap_num_levels_for_key(keymap, evdev_keycode, layout); printf(" | {%s}", xkb_keymap_layout_get_name(keymap, layout)); for (xkb_level_index_t level = 0; level < num_levels; level++) { xkb_mod_mask_t masks[100]; size_t num_masks; const xkb_keysym_t *syms; int num_syms; memset(masks, 0, sizeof(masks)); num_masks = xkb_keymap_key_get_mods_for_level(keymap, evdev_keycode, layout, level, masks, ARRAY_SIZE(masks)); num_syms = xkb_keymap_key_get_syms_by_level(keymap, evdev_keycode, layout, level, &syms); for (int i = 0; i < num_syms; i++) { xkb_keysym_t sym = syms[i]; for (size_t m = 0; m < num_masks; m++) { xkb_mod_mask_t mask = masks[m]; char s[255]; int ret; ret = xkb_keysym_get_name(sym, s, sizeof(s)); if (ret < 0 || (size_t) ret >= sizeof(s)) errx(EXIT_FAILURE, "Failed to get name of keysym"); xkb_mod_index_t num_mods = xkb_keymap_num_mods(keymap); printf(" ("); if (!mask) printf("Plain"); int delim = 0; for (xkb_mod_index_t mod = 0; mod < num_mods; mod++) { if ((mask & (1 << mod)) == 0) continue; printf("%s%s", (delim ? " " : ""), xkb_keymap_mod_get_name(keymap, mod)); delim = 1; } printf(") %s,", s); } } } } printf("\n"); } return EXIT_SUCCESS; }