interactive-evdev: add option to print modmaps
authorPierre Le Marre <dev@wismill.eu>
Mon, 18 Sep 2023 10:17:11 +0000 (12:17 +0200)
committerWismill <dev@wismill.eu>
Mon, 18 Sep 2023 14:14:12 +0000 (16:14 +0200)
Add an option to print modmap and vmodmap of relevant keys, as well as
virtual modifiers mapping to real modifier. This is useful for debugging.
It uses private API, so we compile it separately in the fashion of
`xkbcli-compile-keymap/compile-keymap`.

meson.build
tools/interactive-evdev.c
tools/tools-common.c
tools/tools-common.h

index 7b941d0c0c884718d5ce1da6fb8fcd58abf24f87..0d6c8cee24953cb5cb58562e37a688677725125f 100644 (file)
@@ -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(
index 2f039755152faba07b95b01c1417931d5fe51a7d..8da105672ff697804164daa398409f3f7419424f 100644 (file)
@@ -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 <path to keymap file>\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;
index 3262f6150e34ed1ae9db4e9d98883a270f4c4d8f..d48f74a4bf97664a94dd5c1616228a262f8dba59 100644 (file)
@@ -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));
index 21ba8480de0a7813f24d23a9139ca4a8ef72e61a..cc7771bc4ce29a0b8cc59a712e5f24856db72a0b 100644 (file)
@@ -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,