diff --git a/changes/tools/+dump-keymap.feature.md b/changes/tools/+dump-keymap.feature.md new file mode 100644 index 00000000..948fbe6d --- /dev/null +++ b/changes/tools/+dump-keymap.feature.md @@ -0,0 +1,3 @@ +Added `xkbcli dump-keymap-wayland` and `xkbcli dump-keymap-x11` debugging tools +to dump a keymap from a Wayland compositor or a X server, similar to what +`xkbcomp -xkb $DISPLAY -` does for X servers. diff --git a/meson.build b/meson.build index 33aea6f6..37f0db23 100644 --- a/meson.build +++ b/meson.build @@ -549,7 +549,7 @@ if build_tools install: false) endif - # Tool: interactive-x11 + # Tools: interactive-x11 if get_option('enable-x11') x11_tools_dep = declare_dependency( link_with: libxkbcommon_x11, @@ -566,9 +566,18 @@ if build_tools install_dir: dir_libexec) install_man('tools/xkbcli-interactive-x11.1') configh_data.set10('HAVE_XKBCLI_INTERACTIVE_X11', true) + + executable('xkbcli-dump-keymap-x11', + 'tools/interactive-x11.c', + dependencies: x11_tools_dep, + c_args: ['-DKEYMAP_DUMP'], + install: true, + install_dir: dir_libexec) + install_man('tools/xkbcli-dump-keymap-x11.1') + configh_data.set10('HAVE_XKBCLI_DUMP_KEYMAP_X11', true) endif - # Tool: interactive-wayland + # Tools: interactive-wayland if get_option('enable-wayland') wayland_client_dep = dependency('wayland-client', version: '>=1.2.0', required: false) wayland_protocols_dep = dependency('wayland-protocols', version: '>=1.12', required: false) @@ -603,6 +612,16 @@ You can disable the Wayland xkbcli programs with -Denable-wayland=false.''') install_dir: dir_libexec) install_man('tools/xkbcli-interactive-wayland.1') configh_data.set10('HAVE_XKBCLI_INTERACTIVE_WAYLAND', true) + + executable('xkbcli-dump-keymap-wayland', + 'tools/interactive-wayland.c', + xdg_shell_sources, + dependencies: [tools_dep, wayland_client_dep], + c_args: ['-DKEYMAP_DUMP'], + install: true, + install_dir: dir_libexec) + install_man('tools/xkbcli-dump-keymap-wayland.1') + configh_data.set10('HAVE_XKBCLI_DUMP_KEYMAP_WAYLAND', true) endif # Tool: list diff --git a/tools/interactive-wayland.c b/tools/interactive-wayland.c index 17a8852b..edc1205d 100644 --- a/tools/interactive-wayland.c +++ b/tools/interactive-wayland.c @@ -86,6 +86,9 @@ struct interactive_seat { }; static bool terminate; +#ifdef KEYMAP_DUMP +static bool dump_raw_keymap; +#endif #ifdef HAVE_MKOSTEMP static int @@ -360,24 +363,45 @@ kbd_keymap(void *data, struct wl_keyboard *wl_kbd, uint32_t format, buf = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { - fprintf(stderr, "Failed to mmap keymap: %d\n", errno); + fprintf(stderr, "ERROR: Failed to mmap keymap: %d\n", errno); close(fd); return; } +#ifdef KEYMAP_DUMP + /* We do not want to be interactive, so stop at next loop */ + terminate = true; + if (dump_raw_keymap) { + /* Dump the raw keymap */ + fprintf(stdout, "%s", (char *)buf); + munmap(buf, size); + close(fd); + /* Do not go further */ + return; + } +#endif + seat->keymap = xkb_keymap_new_from_buffer(seat->inter->ctx, buf, size - 1, XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS); munmap(buf, size); close(fd); if (!seat->keymap) { - fprintf(stderr, "Failed to compile keymap!\n"); + fprintf(stderr, "ERROR: Failed to compile keymap!\n"); return; } +#ifdef KEYMAP_DUMP + /* Dump the reformatted keymap */ + char *dump = xkb_keymap_get_as_string(seat->keymap, + XKB_KEYMAP_FORMAT_TEXT_V1); + fprintf(stdout, "%s", dump); + free(dump); + return; +#endif seat->state = xkb_state_new(seat->keymap); if (!seat->state) { - fprintf(stderr, "Failed to create XKB state!\n"); + fprintf(stderr, "ERROR: Failed to create XKB state!\n"); return; } } @@ -702,10 +726,20 @@ static void usage(FILE *fp, char *progname) { fprintf(fp, - "Usage: %s [--help] [--enable-compose]\n", + "Usage: %s [--help]" +#ifndef KEYMAP_DUMP + " [--enable-compose]" +#else + " [--raw]" +#endif + "\n", progname); fprintf(fp, +#ifndef KEYMAP_DUMP " --enable-compose enable Compose\n" +#else + " --raw dump the raw keymap, without parsing it\n" +#endif " --help display this help and exit\n" ); } @@ -722,10 +756,15 @@ main(int argc, char *argv[]) bool with_compose = false; enum options { OPT_COMPOSE, + OPT_RAW, }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, +#ifndef KEYMAP_DUMP {"enable-compose", no_argument, 0, OPT_COMPOSE}, +#else + {"raw", no_argument, 0, OPT_RAW}, +#endif {0, 0, 0, 0}, }; @@ -738,9 +777,15 @@ main(int argc, char *argv[]) break; switch (opt) { +#ifndef KEYMAP_DUMP case OPT_COMPOSE: with_compose = true; break; +#else + case OPT_RAW: + dump_raw_keymap = true; + break; +#endif case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; diff --git a/tools/interactive-x11.c b/tools/interactive-x11.c index 253dc044..5a164764 100644 --- a/tools/interactive-x11.c +++ b/tools/interactive-x11.c @@ -172,6 +172,17 @@ init_kbd(struct keyboard *kbd, xcb_connection_t *conn, uint8_t first_xkb_event, ret = update_keymap(kbd); if (ret) goto err_out; + +#ifdef KEYMAP_DUMP + /* Dump the keymap */ + char *dump = xkb_keymap_get_as_string(kbd->keymap, + XKB_KEYMAP_FORMAT_TEXT_V1); + fprintf(stdout, "%s", dump); + free(dump); + terminate = true; + return 0; +#endif + if (compose_table) kbd->compose_state = xkb_compose_state_new(compose_table, XKB_COMPOSE_STATE_NO_FLAGS); @@ -198,6 +209,7 @@ deinit_kbd(struct keyboard *kbd) xkb_keymap_unref(kbd->keymap); } +#ifndef KEYMAP_DUMP static void process_xkb_event(xcb_generic_event_t *gevent, struct keyboard *kbd) { @@ -349,15 +361,22 @@ create_capture_window(xcb_connection_t *conn) return 0; } +#endif static void usage(FILE *fp, char *progname) { fprintf(fp, - "Usage: %s [--help] [--enable-compose]\n", + "Usage: %s [--help]" +#ifndef KEYMAP_DUMP + " [--enable-compose]" +#endif + "\n", progname); fprintf(fp, +#ifndef KEYMAP_DUMP " --enable-compose enable Compose\n" +#endif " --help display this help and exit\n" ); } @@ -380,7 +399,9 @@ main(int argc, char *argv[]) }; static struct option opts[] = { {"help", no_argument, 0, 'h'}, - {"enable-compose", no_argument, 0, OPT_COMPOSE}, +#ifndef KEYMAP_DUMP + {"enable-compose", no_argument, 0, OPT_COMPOSE}, +#endif {0, 0, 0, 0}, }; @@ -393,9 +414,11 @@ main(int argc, char *argv[]) break; switch (opt) { +#ifndef KEYMAP_DUMP case OPT_COMPOSE: with_compose = true; break; +#endif case 'h': usage(stdout, argv[0]); return EXIT_SUCCESS; @@ -439,7 +462,7 @@ main(int argc, char *argv[]) XKB_COMPOSE_COMPILE_NO_FLAGS); if (!compose_table) { fprintf(stderr, "Couldn't create compose from locale\n"); - goto err_compose; + goto err_core_kbd; } } else { compose_table = NULL; @@ -453,16 +476,17 @@ main(int argc, char *argv[]) } ret = init_kbd(&core_kbd, conn, first_xkb_event, core_kbd_device_id, - ctx, compose_table); + ctx, compose_table); if (ret) { fprintf(stderr, "Couldn't initialize core keyboard device\n"); goto err_ctx; } +#ifndef KEYMAP_DUMP ret = create_capture_window(conn); if (ret) { fprintf(stderr, "Couldn't create a capture window\n"); - goto err_core_kbd; + goto err_compose; } tools_disable_stdin_echo(); @@ -470,6 +494,7 @@ main(int argc, char *argv[]) tools_enable_stdin_echo(); err_compose: +#endif xkb_compose_table_unref(compose_table); err_core_kbd: deinit_kbd(&core_kbd); diff --git a/tools/xkbcli-dump-keymap-wayland.1 b/tools/xkbcli-dump-keymap-wayland.1 new file mode 100644 index 00000000..8827fc2a --- /dev/null +++ b/tools/xkbcli-dump-keymap-wayland.1 @@ -0,0 +1,35 @@ +.Dd September 20, 2024 +.Dt XKBCLI\-DUMP\-KEYMAP\-WAYLAND 1 +.Os +. +.Sh NAME +.Nm "xkbcli\-dump\-keymap\-wayland" +.Nd Debugger for XKB keyboard keymaps on Wayland +. +.Sh SYNOPSIS +.Nm +.Op Ar options +. +.Sh DESCRIPTION +.Nm +is a commandline tool to dump XKB keymaps from Wayland compositor. +. +.Pp +This requires a Wayland compositor to be running. +. +.Pp +This is a debugging tool, its behavior or output is not guaranteed to be stable. +. +.Bl -tag -width Ds +.It Fl \-help +Print help and exit +. +.It Fl \-raw +Print the raw keymap, without parsing it. +.El +. +.Sh SEE ALSO +.Xr xkbcli 1 , +.Xr xkbcli\-interactive\-wayland 1 , +.Xr xkbcli\-dump\-keymap\-x11 1 , +.Lk https://xkbcommon.org "The libxkbcommon online documentation" diff --git a/tools/xkbcli-dump-keymap-x11.1 b/tools/xkbcli-dump-keymap-x11.1 new file mode 100644 index 00000000..bbba28b8 --- /dev/null +++ b/tools/xkbcli-dump-keymap-x11.1 @@ -0,0 +1,32 @@ +.Dd September 20, 2024 +.Dt XKBCLI\-DUMP\-KEYMAP\-X11 1 +.Os +. +.Sh NAME +.Nm "xkbcli\-dump\-keymap\-x11" +.Nd Debugger for XKB keyboard keymaps on X11 +. +.Sh SYNOPSIS +.Nm +.Op Ar options +. +.Sh DESCRIPTION +.Nm +is a commandline tool to dump XKB keymaps from X servers. +. +.Pp +This requires an X server to be running. +. +.Pp +This is a debugging tool, its behavior or output is not guaranteed to be stable. +. +.Bl -tag -width Ds +.It Fl \-help +Print help and exit +.El +. +.Sh SEE ALSO +.Xr xkbcli 1 , +.Xr xkbcli\-interactive\-x11 1 , +.Xr xkbcli\-dump\-keymap\-wayland 1 , +.Lk https://xkbcommon.org "The libxkbcommon online documentation" diff --git a/tools/xkbcli-interactive-wayland.1 b/tools/xkbcli-interactive-wayland.1 index 9035d392..66dc7b24 100644 --- a/tools/xkbcli-interactive-wayland.1 +++ b/tools/xkbcli-interactive-wayland.1 @@ -4,7 +4,7 @@ . .Sh NAME .Nm "xkbcli\-interactive\-wayland" -.Nd interactive debugger for X Keyboard keymaps +.Nd interactive debugger for Wayland keyboard keymaps . .Sh SYNOPSIS .Nm diff --git a/tools/xkbcli.c b/tools/xkbcli.c index df045f55..7aa0acb0 100644 --- a/tools/xkbcli.c +++ b/tools/xkbcli.c @@ -61,6 +61,16 @@ usage(void) " Interactive debugger for XKB keymaps for evdev\n" "\n" #endif +#if HAVE_XKBCLI_DUMP_KEYMAP_WAYLAND + " dump-keymap-wayland\n" + " Dump a XKB keymap from a Wayland compositor\n" + "\n" +#endif +#if HAVE_XKBCLI_DUMP_KEYMAP_X11 + " dump-keymap-x11\n" + " Dump a XKB keymap from an X server\n" + "\n" +#endif #if HAVE_XKBCLI_COMPILE_KEYMAP " compile-keymap\n" " Compile an XKB keymap\n"