diff --git a/meson.build b/meson.build index 7b941d0..0d6c8ce 100644 --- a/meson.build +++ b/meson.build @@ -416,10 +416,13 @@ man_pages = [] # Tools build_tools = get_option('enable-tools') and cc.has_header_symbol('getopt.h', 'getopt_long', prefix: '#define _GNU_SOURCE') if build_tools - libxkbcommon_tools_internal = static_library( - 'tools-internal', + libxkbcommon_tools_internal_sources = [ 'tools/tools-common.h', 'tools/tools-common.c', + ] + libxkbcommon_tools_internal = static_library( + 'tools-internal', + libxkbcommon_tools_internal_sources, dependencies: dep_libxkbcommon, ) tools_dep = declare_dependency( @@ -467,6 +470,15 @@ if build_tools install_dir: dir_libexec) configh_data.set10('HAVE_XKBCLI_INTERACTIVE_EVDEV', true) install_man('tools/xkbcli-interactive-evdev.1') + # The same tool again, but with access to some private APIs. + executable('interactive-evdev', + 'tools/interactive-evdev.c', + libxkbcommon_sources, + libxkbcommon_tools_internal_sources, + dependencies: [tools_dep], + c_args: ['-DENABLE_PRIVATE_APIS'], + include_directories: [include_directories('src', 'include')], + install: false) endif if get_option('enable-x11') x11_tools_dep = declare_dependency( diff --git a/tools/interactive-evdev.c b/tools/interactive-evdev.c index 2f03975..8da1056 100644 --- a/tools/interactive-evdev.c +++ b/tools/interactive-evdev.c @@ -58,7 +58,12 @@ static int evdev_offset = 8; static bool report_state_changes; static bool with_compose; static enum xkb_consumed_mode consumed_mode = XKB_CONSUMED_MODE_XKB; + +#ifdef ENABLE_PRIVATE_APIS +#define DEFAULT_PRINT_FIELDS (PRINT_ALL_FIELDS & ~PRINT_MODMAPS) +#else #define DEFAULT_PRINT_FIELDS PRINT_ALL_FIELDS +#endif print_state_fields_mask_t print_fields = DEFAULT_PRINT_FIELDS; #define DEFAULT_INCLUDE_PATH_PLACEHOLDER "__defaults__" @@ -378,6 +383,9 @@ usage(FILE *fp, char *progname) fprintf(fp, " or: %s --keymap \n", progname); fprintf(fp, "For both:\n" +#ifdef ENABLE_PRIVATE_APIS + " --print-modmaps (print real & virtual key modmaps)\n" +#endif " --short (do not print layout nor Unicode keysym translation)\n" " --report-state-changes (report changes to the state)\n" " --enable-compose (enable Compose)\n" @@ -418,6 +426,9 @@ main(int argc, char *argv[]) OPT_COMPOSE, OPT_SHORT, OPT_REPORT_STATE, +#ifdef ENABLE_PRIVATE_APIS + OPT_PRINT_MODMAPS, +#endif }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, @@ -434,6 +445,9 @@ main(int argc, char *argv[]) {"short", no_argument, 0, OPT_SHORT}, {"report-state-changes", no_argument, 0, OPT_REPORT_STATE}, {"without-x11-offset", no_argument, 0, OPT_WITHOUT_X11_OFFSET}, +#ifdef ENABLE_PRIVATE_APIS + {"print-modmaps", no_argument, 0, OPT_PRINT_MODMAPS}, +#endif {0, 0, 0, 0}, }; @@ -503,6 +517,11 @@ main(int argc, char *argv[]) return EXIT_INVALID_USAGE; } break; +#ifdef ENABLE_PRIVATE_APIS + case OPT_PRINT_MODMAPS: + print_fields |= PRINT_MODMAPS; + break; +#endif case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; @@ -584,6 +603,15 @@ main(int argc, char *argv[]) goto out; } +#ifdef ENABLE_PRIVATE_APIS + if (print_fields & PRINT_MODMAPS) { + print_keys_modmaps(keymap); + putchar('\n'); + print_keymap_modmaps(keymap); + putchar('\n'); + } +#endif + act.sa_handler = sigintr_handler; sigemptyset(&act.sa_mask); act.sa_flags = 0; diff --git a/tools/tools-common.c b/tools/tools-common.c index 3262f61..d48f74a 100644 --- a/tools/tools-common.c +++ b/tools/tools-common.c @@ -61,6 +61,87 @@ print_keycode(struct xkb_keymap *keymap, const char* prefix, } } +#ifdef ENABLE_PRIVATE_APIS +#include "src/keymap.h" + +void +print_keymap_modmaps(struct xkb_keymap *keymap) { + printf("Modifiers mapping:\n"); + for (xkb_mod_index_t vmod = 0; vmod < xkb_keymap_num_mods(keymap); vmod++) { + if (keymap->mods.mods[vmod].type & MOD_REAL) + continue; + printf("- %s: ", xkb_keymap_mod_get_name(keymap, vmod)); + if (keymap->mods.mods[vmod].mapping) { + bool first = true; + for (xkb_mod_index_t mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { + if (keymap->mods.mods[vmod].mapping & (1u << mod)) { + if (first) { + first = false; + printf("%s", xkb_keymap_mod_get_name(keymap, mod)); + } else { + printf("+ %s", xkb_keymap_mod_get_name(keymap, mod)); + } + } + } + } else { + printf("(unmapped)"); + } + printf("\n"); + } +} + +#define MODMAP_PADDING 7 +#define VMODMAP_PADDING 9 +static void +print_key_modmaps(struct xkb_keymap *keymap, xkb_keycode_t keycode) { + const struct xkb_key *key = XkbKey(keymap, keycode); + if (key != NULL) { + xkb_mod_index_t mod; + + printf("modmap [ "); + if (key->modmap) { + for (mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { + if (key->modmap & (1u << mod)) { + printf("%-*s", (int) MODMAP_PADDING, + xkb_keymap_mod_get_name(keymap, mod)); + break; + } + } + } else { + printf("%*c", (int) MODMAP_PADDING, ' '); + } + + printf(" ] vmodmap [ "); + int length = 0; + const char *mod_name; + for (mod = 0; mod < xkb_keymap_num_mods(keymap); mod++) { + if (key->vmodmap & (1u << mod)) { + mod_name = xkb_keymap_mod_get_name(keymap, mod); + length += strlen(mod_name) + 1; + printf("%s ", mod_name); + } + } + if (length < VMODMAP_PADDING) { + printf("%*c", (int) VMODMAP_PADDING - length, ' '); + } + printf("] "); + } +} + +void +print_keys_modmaps(struct xkb_keymap *keymap) { + const struct xkb_key *key; + printf("Keys modmaps:\n"); + xkb_keys_foreach(key, keymap) { + if (key->modmap || key->vmodmap) { + print_keycode(keymap, "- ", key->keycode, ": "); + print_key_modmaps(keymap, key->keycode); + putchar('\n'); + } + } +} +#endif + void tools_print_keycode_state(struct xkb_state *state, struct xkb_compose_state *compose_state, @@ -103,6 +184,12 @@ tools_print_keycode_state(struct xkb_state *state, print_keycode(keymap, "keycode [ ", keycode, " ] "); +#ifdef ENABLE_PRIVATE_APIS + if (fields & PRINT_MODMAPS) { + print_key_modmaps(keymap, keycode); + } +#endif + printf("keysyms [ "); for (int i = 0; i < nsyms; i++) { xkb_keysym_get_name(syms[i], s, sizeof(s)); diff --git a/tools/tools-common.h b/tools/tools-common.h index 21ba848..cc7771b 100644 --- a/tools/tools-common.h +++ b/tools/tools-common.h @@ -38,6 +38,9 @@ /* Fields that are printed in the interactive tools. */ enum print_state_fields { +#ifdef ENABLE_PRIVATE_APIS + PRINT_MODMAPS = (1u << 1), +#endif PRINT_LAYOUT = (1u << 2), PRINT_UNICODE = (1u << 3), PRINT_ALL_FIELDS = ((PRINT_UNICODE << 1) - 1), @@ -50,6 +53,13 @@ enum print_state_fields { }; typedef uint32_t print_state_fields_mask_t; +#ifdef ENABLE_PRIVATE_APIS +void +print_keymap_modmaps(struct xkb_keymap *keymap); +void +print_keys_modmaps(struct xkb_keymap *keymap); +#endif + void tools_print_keycode_state(struct xkb_state *state, struct xkb_compose_state *compose_state,