From ce4723b6de5ea7153fbd6ba3439765ffa7066505 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Fri, 7 Apr 2023 23:43:45 -0300 Subject: [PATCH 01/13] Jenkins: Add Qt Wayland support to AppImage --- .ci/AppImageBuilder.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.ci/AppImageBuilder.yml b/.ci/AppImageBuilder.yml index 22967e2f4..39997a7a8 100644 --- a/.ci/AppImageBuilder.yml +++ b/.ci/AppImageBuilder.yml @@ -68,6 +68,7 @@ AppDir: - libxcb-shm0 # if QT:BOOL=ON - libxcb-xfixes0 # if QT:BOOL=ON - libxkbcommon-x11-0 # if QT:BOOL=ON + - qtwayland5 # if QT:BOOL=ON - zlib1g files: exclude: From 078e8cca0cdd4be2d52b67dcc0463962869cccb9 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 00:29:40 -0300 Subject: [PATCH 02/13] Add more AppImage build stuff to gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 0a21bf105..acb28baf7 100644 --- a/.gitignore +++ b/.gitignore @@ -34,6 +34,8 @@ Makefile *.tar.* *.AppImage /appimage-builder-cache +/appimage-build +/AppImageBuilder-generated.yml # Visual Studio Code /.vs From bbbe0ec88d4dff35843f7acdaeab253151241deb Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 00:31:25 -0300 Subject: [PATCH 03/13] qt: Add xkbcommon keyboard support for Wayland --- src/qt/CMakeLists.txt | 3 + src/qt/qt_mainwindow.cpp | 14 +- src/qt/xkbcommon_keyboard.cpp | 9 +- src/qt/xkbcommon_keyboard.hpp | 1 + src/qt/xkbcommon_wl_keyboard.cpp | 236 ++++++++++++++++++++++++++++++ src/qt/xkbcommon_wl_keyboard.hpp | 17 +++ src/qt/xkbcommon_x11_keyboard.cpp | 1 + 7 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 src/qt/xkbcommon_wl_keyboard.cpp create mode 100644 src/qt/xkbcommon_wl_keyboard.hpp diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index 0cce392a9..dd3bc6f79 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -402,6 +402,9 @@ if (UNIX AND NOT APPLE AND NOT HAIKU) ecm_add_wayland_client_protocol(WL_SOURCE_VAR PROTOCOL ${CMAKE_SOURCE_DIR}/wl_protocols/pointer-constraints-unstable-v1.xml BASENAME pointer-constraints-unstable-v1) target_include_directories(ui PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${Qt${QT_MAJOR}Gui_PRIVATE_INCLUDE_DIRS}) target_sources(ui PRIVATE ${WL_SOURCE_VAR} wl_mouse.cpp) + if (XKBCOMMON_FOUND) + target_sources(ui PRIVATE xkbcommon_wl_keyboard.cpp) + endif() target_compile_definitions(ui PRIVATE WAYLAND) endif() endif() diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index de7bceafb..40f01c2f6 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -101,6 +101,9 @@ extern int qt_nvr_save(void); # ifdef XKBCOMMON_X11 # include "xkbcommon_x11_keyboard.hpp" # endif +# ifdef WAYLAND +# include "xkbcommon_wl_keyboard.hpp" +# endif # endif # include # include @@ -652,9 +655,18 @@ MainWindow::MainWindow(QWidget *parent) ui->actionCursor_Puck->setChecked(true); } -#ifdef XKBCOMMON_X11 +#ifdef XKBCOMMON +# ifdef XKBCOMMON_X11 if (QApplication::platformName().contains("xcb")) xkbcommon_x11_init(); + else +# endif +# ifdef WAYLAND + if (QApplication::platformName().contains("wayland")) + xkbcommon_wl_init(); + else +# endif + {} #endif } diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp index 1b4998b1f..87bc02aa5 100644 --- a/src/qt/xkbcommon_keyboard.cpp +++ b/src/qt/xkbcommon_keyboard.cpp @@ -228,7 +228,14 @@ struct xkb_keymap *xkbcommon_keymap = nullptr; void xkbcommon_init(struct xkb_keymap *keymap) { - xkbcommon_keymap = keymap; + if (keymap) + xkbcommon_keymap = keymap; +} + +void +xkbcommon_close() +{ + xkbcommon_keymap = NULL; } uint16_t diff --git a/src/qt/xkbcommon_keyboard.hpp b/src/qt/xkbcommon_keyboard.hpp index afcba41bb..c3b28eeec 100644 --- a/src/qt/xkbcommon_keyboard.hpp +++ b/src/qt/xkbcommon_keyboard.hpp @@ -16,4 +16,5 @@ */ extern void *xkbcommon_keymap; void xkbcommon_init(struct xkb_keymap *keymap); +void xkbcommon_close(); uint16_t xkbcommon_translate(uint32_t keycode); diff --git a/src/qt/xkbcommon_wl_keyboard.cpp b/src/qt/xkbcommon_wl_keyboard.cpp new file mode 100644 index 000000000..2dda6368a --- /dev/null +++ b/src/qt/xkbcommon_wl_keyboard.cpp @@ -0,0 +1,236 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * xkbcommon Wayland keyboard input module. + * + * Heavily inspired by libxkbcommon interactive-wayland.c + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +extern "C" { +#include +#include +#include +#include <86box/86box.h> +}; +#include "xkbcommon_keyboard.hpp" +#include +#include + +#include +#include +#include + +typedef struct { + struct wl_seat *wl_seat; + struct wl_keyboard *wl_kbd; + uint32_t version; + + struct xkb_keymap *keymap; + + struct wl_list link; +} seat_t; + +static bool wl_init_ok = false; +static struct wl_list seats; +static struct xkb_context *ctx; + +static void +xkbcommon_wl_set_keymap() +{ + /* Grab keymap from the first seat with one. */ + seat_t *seat, *tmp; + wl_list_for_each_safe(seat, tmp, &seats, link) { + if (seat->keymap) { + xkbcommon_init(seat->keymap); + return; + } + } + xkbcommon_close(); +} + +static void +kbd_keymap(void *data, struct wl_keyboard *wl_kbd, uint32_t format, + int fd, uint32_t size) +{ + seat_t *seat = (seat_t *) data; + + char *buf = (char *) mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (!buf) { + qWarning() << "XKB Keyboard: Failed to mmap keymap with error" << errno; + return; + } + + seat->keymap = xkb_keymap_new_from_buffer(ctx, buf, size - 1, + XKB_KEYMAP_FORMAT_TEXT_V1, + XKB_KEYMAP_COMPILE_NO_FLAGS); + munmap(buf, size); + close(fd); + if (!seat->keymap) { + qWarning() << "XKB Keyboard: Keymap compilation failed"; + return; + } + + xkbcommon_wl_set_keymap(); +} + +static void +kbd_enter(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, + struct wl_surface *surf, struct wl_array *keys) +{ +} + +static void +kbd_leave(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, + struct wl_surface *surf) +{ +} + +static void +kbd_key(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, uint32_t time, + uint32_t key, uint32_t state) +{ +} + +static void +kbd_modifiers(void *data, struct wl_keyboard *wl_kbd, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, + uint32_t mods_locked, uint32_t group) +{ +} + +static void +kbd_repeat_info(void *data, struct wl_keyboard *wl_kbd, int32_t rate, + int32_t delay) +{ +} + +static const struct wl_keyboard_listener kbd_listener = { + kbd_keymap, + kbd_enter, + kbd_leave, + kbd_key, + kbd_modifiers, + kbd_repeat_info +}; + +static void +seat_capabilities(void *data, struct wl_seat *wl_seat, uint32_t caps) +{ + seat_t *seat = (seat_t *) data; + + if (!seat->wl_kbd && (caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + seat->wl_kbd = wl_seat_get_keyboard(seat->wl_seat); + wl_keyboard_add_listener(seat->wl_kbd, &kbd_listener, seat); + } else if (seat->wl_kbd && !(caps & WL_SEAT_CAPABILITY_KEYBOARD)) { + if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_keyboard_release(seat->wl_kbd); + else + wl_keyboard_destroy(seat->wl_kbd); + + static struct xkb_keymap *keymap = seat->keymap; + seat->keymap = NULL; + xkbcommon_wl_set_keymap(); + xkb_keymap_unref(keymap); + + seat->wl_kbd = NULL; + } +} + +static void +seat_name(void *data, struct wl_seat *wl_seat, const char *name) +{ +} + +static const struct wl_seat_listener seat_listener = { + seat_capabilities, + seat_name +}; + +static void +display_handle_global(void *data, struct wl_registry *wl_registry, uint32_t id, + const char *interface, uint32_t version) +{ + if (!strcmp(interface, "wl_seat")) { + seat_t *seat = (seat_t *) malloc(sizeof(seat_t)); + memset(seat, 0, sizeof(seat_t)); + + seat->wl_seat = (wl_seat *) wl_registry_bind(wl_registry, id, &wl_seat_interface, MIN(version, 5)); + wl_seat_add_listener(seat->wl_seat, &seat_listener, seat); + wl_list_insert(&seats, &seat->link); + } +} + +static void +display_global_remove(void *data, struct wl_registry *wl_registry, uint32_t id) +{ + xkbcommon_close(); + + seat_t *seat, *tmp; + wl_list_for_each_safe(seat, tmp, &seats, link) { + if (seat->wl_kbd) { + if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_keyboard_release(seat->wl_kbd); + else + wl_keyboard_destroy(seat->wl_kbd); + + xkb_keymap_unref(seat->keymap); + } + + if (seat->version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_seat_release(seat->wl_seat); + else + wl_seat_destroy(seat->wl_seat); + + wl_list_remove(&seat->link); + free(seat); + } +} + +static const struct wl_registry_listener registry_listener = { + display_handle_global, + display_global_remove +}; + +void +xkbcommon_wl_init() +{ + if (wl_init_ok) + return; + + wl_list_init(&seats); + + ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (!ctx) { + qWarning() << "XKB Keyboard: XKB context creation failed"; + return; + } + + wl_display *display = (wl_display *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("wl_display"); + if (display) { + auto registry = wl_display_get_registry(display); + if (registry) { + wl_registry_add_listener(registry, ®istry_listener, nullptr); + wl_display_roundtrip(display); + wl_display_roundtrip(display); + } else { + goto err_ctx; + } + } else { + goto err_ctx; + } + wl_init_ok = true; + return; + +err_ctx: + xkb_context_unref(ctx); +} diff --git a/src/qt/xkbcommon_wl_keyboard.hpp b/src/qt/xkbcommon_wl_keyboard.hpp new file mode 100644 index 000000000..a70cb9e9b --- /dev/null +++ b/src/qt/xkbcommon_wl_keyboard.hpp @@ -0,0 +1,17 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for xkbcommon Wayland keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +void xkbcommon_wl_init(); diff --git a/src/qt/xkbcommon_x11_keyboard.cpp b/src/qt/xkbcommon_x11_keyboard.cpp index b9c16cc9b..8cba2c4d1 100644 --- a/src/qt/xkbcommon_x11_keyboard.cpp +++ b/src/qt/xkbcommon_x11_keyboard.cpp @@ -77,6 +77,7 @@ xkbcommon_x11_init() } xkbcommon_init(keymap); + goto err_conn; err_ctx: xkb_context_unref(ctx); From 4dd6b168557235630cd6ad3f89b748939edc8362 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 00:38:24 -0300 Subject: [PATCH 04/13] qt: Add another xkb Num. alias --- src/qt/xkbcommon_keyboard.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp index 87bc02aa5..f5a7ca0eb 100644 --- a/src/qt/xkbcommon_keyboard.cpp +++ b/src/qt/xkbcommon_keyboard.cpp @@ -128,6 +128,7 @@ std::unordered_map xkb_keycodes{ {"AE13", 0x7d}, /* \| */ {"KPPT", 0x7e}, /* Brazilian Num. */ {"I06", 0x7e}, /* alias of KPPT on keycodes/xfree86 (i.e. X11 forwarding) */ + {"I129", 0x7e}, /* another alias: KPCOMMA */ /* Korean keys. */ {"HJCV", 0xf1}, /* hancha toggle */ From 08158571c0fa19f420b14fb70c60e6d4431cde64 Mon Sep 17 00:00:00 2001 From: richardg867 Date: Sat, 8 Apr 2023 01:02:45 -0300 Subject: [PATCH 05/13] Jenkins: Remove forgotten debug line --- .ci/build.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/.ci/build.sh b/.ci/build.sh index 67320c2e2..1d50e304c 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -948,7 +948,6 @@ else -S "$prefix" -B "$prefix_build" || exit 99 cmake --build "$prefix_build" -j$(nproc) || exit 99 cmake --install "$prefix_build" || exit 99 - cp -p "$cwd_root/archive_tmp/usr/bin/fluidsynth" fluidsynth # Build SDL2 for joystick and FAudio support, with most components # disabled to remove the dependencies on PulseAudio and libdrm. From 080859f184a6ddba8c4b41d106ea0be1de6df8f7 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 01:03:21 -0300 Subject: [PATCH 06/13] qt: Fix xkb Pause key handling --- src/qt/qt_mainwindow.cpp | 4 ++++ src/qt/xkbcommon_keyboard.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 40f01c2f6..a8957b476 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1552,6 +1552,10 @@ x11_keycode_to_keysym(uint32_t keycode) } } #endif + /* Special case for Ctrl+Pause. */ + if ((finalkeycode == 0x145) && (keyboard_recv(0x1d) || keyboard_recv(0x11d))) + finalkeycode = 0x146; + if (rctrl_is_lalt && finalkeycode == 0x11D) finalkeycode = 0x38; return finalkeycode; diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp index f5a7ca0eb..15833cd9b 100644 --- a/src/qt/xkbcommon_keyboard.cpp +++ b/src/qt/xkbcommon_keyboard.cpp @@ -141,8 +141,8 @@ std::unordered_map xkb_keycodes{ {"SYRQ", 0x137}, {"FK13", 0x137}, /* F13 as SysRq */ {"RALT", 0x138}, - {"PAUS", 0x146}, /* special case */ - {"FK15", 0x146}, /* F15 as Pause */ + {"PAUS", 0x145}, + {"FK15", 0x145}, /* F15 as Pause */ {"HOME", 0x147}, {"UP", 0x148}, {"PGUP", 0x149}, From 201503e6d24a91a9e7a6351fbcdbaafc43914cac Mon Sep 17 00:00:00 2001 From: richardg867 Date: Sat, 8 Apr 2023 01:19:05 -0300 Subject: [PATCH 07/13] Jenkins: Fix pkgconfig path missing a dependency for xkbcommon-x11 --- .ci/build.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ci/build.sh b/.ci/build.sh index 1d50e304c..a61cdc7f9 100755 --- a/.ci/build.sh +++ b/.ci/build.sh @@ -629,7 +629,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(ENV{PKG_CONFIG_PATH} "") -set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/$libdir/pkgconfig:/usr/share/$libdir/pkgconfig") +set(ENV{PKG_CONFIG_LIBDIR} "/usr/lib/$libdir/pkgconfig:/usr/share/$libdir/pkgconfig:/usr/share/pkgconfig") include("$(realpath "$toolchain_file")") EOF From aea869b997a8303c0a56e53655e18193a71a6d8a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 02:19:26 -0300 Subject: [PATCH 08/13] qt: Add missing XKB mapping for KPPLUSMINUS --- src/qt/xkbcommon_keyboard.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp index 15833cd9b..490f95c82 100644 --- a/src/qt/xkbcommon_keyboard.cpp +++ b/src/qt/xkbcommon_keyboard.cpp @@ -164,8 +164,8 @@ std::unordered_map xkb_keycodes{ {"KPEQ", 0x59}, /* Num= */ {"FRNT", 0x101}, /* # Logitech Task Select */ {"I224", 0x105}, /* CHAT# => Messenger/Files */ - {"I190", 0x107}, /* REDO */ - {"UNDO", 0x108}, + {"I190", 0x107}, /* REDO# */ + {"UNDO", 0x108}, /* # */ {"PAST", 0x10a}, /* # Paste */ {"I185", 0x10b}, /* SCROLLUP# => normal speed */ {"I173", 0x110}, /* PREVIOUSSONG */ @@ -174,8 +174,8 @@ std::unordered_map xkb_keycodes{ {"I157", 0x114}, /* PROG2# => Excel */ {"I210", 0x115}, /* PROG3# => Calendar */ {"I182", 0x116}, /* EXIT# => Log Off */ - {"CUT", 0x117}, - {"COPY", 0x118}, + {"CUT", 0x117}, /* # */ + {"COPY", 0x118}, /* # */ {"I171", 0x119}, /* NEXTSONG */ {"I162", 0x11e}, /* CYCLEWINDOWS => Application Right (no left counterpart) */ {"MUTE", 0x120}, @@ -202,6 +202,7 @@ std::unordered_map xkb_keycodes{ {"I159", 0x144}, /* MSDOS# */ {"I120", 0x14c}, /* MACRO */ {"I187", 0x14c}, /* KPLEFTPAREN# */ + {"I126", 0x14e}, /* KPPLUSMINUS */ {"I243", 0x155}, /* DOCUMENTS# => Logitech */ {"I242", 0x157}, /* SAVE# */ {"I218", 0x158}, /* PRINT# */ From 6e1f3de04414a47ad23330bef7b19f97d0c387d2 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 14:32:05 -0300 Subject: [PATCH 09/13] qt: Get XCB connection for xkbcommon keyboard from Qt itself --- src/qt/xkbcommon_wl_keyboard.cpp | 2 +- src/qt/xkbcommon_x11_keyboard.cpp | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/qt/xkbcommon_wl_keyboard.cpp b/src/qt/xkbcommon_wl_keyboard.cpp index 2dda6368a..c6736f2d4 100644 --- a/src/qt/xkbcommon_wl_keyboard.cpp +++ b/src/qt/xkbcommon_wl_keyboard.cpp @@ -55,7 +55,7 @@ xkbcommon_wl_set_keymap() return; } } - xkbcommon_close(); + xkbcommon_close(); /* none found */ } static void diff --git a/src/qt/xkbcommon_x11_keyboard.cpp b/src/qt/xkbcommon_x11_keyboard.cpp index 8cba2c4d1..8e0167518 100644 --- a/src/qt/xkbcommon_x11_keyboard.cpp +++ b/src/qt/xkbcommon_x11_keyboard.cpp @@ -33,7 +33,9 @@ extern "C" { }; #include "xkbcommon_keyboard.hpp" +#include #include +#include void xkbcommon_x11_init() @@ -43,9 +45,9 @@ xkbcommon_x11_init() int32_t core_kbd_device_id; struct xkb_keymap *keymap; - conn = xcb_connect(NULL, NULL); - if (!conn || xcb_connection_has_error(conn)) { - qWarning() << "XKB Keyboard: X server connection failed with error" << (conn ? xcb_connection_has_error(conn) : -1); + conn = (xcb_connection_t *) QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("connection"); + if (!conn) { + qWarning() << "XKB Keyboard: X server connection failed"; return; } @@ -55,13 +57,13 @@ xkbcommon_x11_init() NULL, NULL, NULL, NULL); if (!ret) { qWarning() << "XKB Keyboard: XKB extension setup failed"; - goto err_conn; + return; } ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!ctx) { qWarning() << "XKB Keyboard: XKB context creation failed"; - goto err_conn; + return; } core_kbd_device_id = xkb_x11_get_core_keyboard_device_id(conn); @@ -77,10 +79,8 @@ xkbcommon_x11_init() } xkbcommon_init(keymap); - goto err_conn; + return; err_ctx: xkb_context_unref(ctx); -err_conn: - xcb_disconnect(conn); } From 1fb13b605e7b27f70a83ab576f96106b7110500a Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 15:39:42 -0300 Subject: [PATCH 10/13] qt: Add more XKB mappings, mostly multimedia on extended evdev codes (apparently not usable in X but will be useful later) --- src/qt/xkbcommon_keyboard.cpp | 58 ++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp index 490f95c82..e0560117b 100644 --- a/src/qt/xkbcommon_keyboard.cpp +++ b/src/qt/xkbcommon_keyboard.cpp @@ -53,6 +53,7 @@ std::unordered_map xkb_keycodes{ {"AD11", 0x1a}, {"AD12", 0x1b}, {"RTRN", 0x1c}, + {"LNFD", 0x1c}, /* linefeed => Enter */ {"LCTL", 0x1d}, {"AC01", 0x1e}, @@ -99,7 +100,7 @@ std::unordered_map xkb_keycodes{ {"NMLK", 0x45}, {"SCLK", 0x46}, - {"FK14", 0x46}, /* F14 as Scroll Lock */ + {"FK14", 0x46}, /* F14 => Scroll Lock */ {"KP7", 0x47}, {"KP8", 0x48}, {"KP9", 0x49}, @@ -119,6 +120,7 @@ std::unordered_map xkb_keycodes{ {"FK12", 0x58}, /* Japanese keys. */ + {"HZTG", 0x29}, /* hankaku-zenkaku toggle => ~ */ {"HKTG", 0x70}, /* hiragana-katakana toggle... */ {"HIRA", 0x70}, /* ...and individual keys */ {"KATA", 0x70}, @@ -128,7 +130,7 @@ std::unordered_map xkb_keycodes{ {"AE13", 0x7d}, /* \| */ {"KPPT", 0x7e}, /* Brazilian Num. */ {"I06", 0x7e}, /* alias of KPPT on keycodes/xfree86 (i.e. X11 forwarding) */ - {"I129", 0x7e}, /* another alias: KPCOMMA */ + {"I129", 0x7e}, /* another alias: evdev KPCOMMA */ /* Korean keys. */ {"HJCV", 0xf1}, /* hancha toggle */ @@ -139,10 +141,11 @@ std::unordered_map xkb_keycodes{ {"KPDV", 0x135}, {"PRSC", 0x137}, {"SYRQ", 0x137}, - {"FK13", 0x137}, /* F13 as SysRq */ + {"FK13", 0x137}, /* F13 => SysRq */ {"RALT", 0x138}, {"PAUS", 0x145}, - {"FK15", 0x145}, /* F15 as Pause */ + {"BRK", 0x145}, + {"FK15", 0x145}, /* F15 => Pause */ {"HOME", 0x147}, {"UP", 0x148}, {"PGUP", 0x149}, @@ -155,25 +158,36 @@ std::unordered_map xkb_keycodes{ {"DELE", 0x153}, {"LWIN", 0x15b}, + {"LMTA", 0x15b}, {"RWIN", 0x15c}, - {"COMP", 0x15d}, + {"RMTA", 0x15c}, + {"MENU", 0x15d}, + {"COMP", 0x15d}, /* Compose as Menu */ /* Multimedia keys, using Linux evdev-specific keycodes where required. Guideline is to try and follow the Microsoft standard, then fill in some OEM-specific keys for redundancy sake. Keys marked with # are not translated into evdev codes by the standard atkbd driver. */ {"KPEQ", 0x59}, /* Num= */ + {"I426", 0x6a}, /* ZOOMIN# => Logitech */ + {"I428", 0x6b}, /* ZOOMRESET# => Logitech */ + {"I231", 0x6d}, /* CANCEL# => Logitech */ {"FRNT", 0x101}, /* # Logitech Task Select */ + {"I156", 0x102}, /* PROG1# => Samsung */ + {"I157", 0x103}, /* PROG2# => Samsung */ + {"I427", 0x104}, /* ZOOMOUT# => Logitech */ + {"I152", 0x105}, /* FILE# => Messenger/Files */ {"I224", 0x105}, /* CHAT# => Messenger/Files */ + {"I438", 0x105}, /* MESSENGER# */ {"I190", 0x107}, /* REDO# */ {"UNDO", 0x108}, /* # */ {"PAST", 0x10a}, /* # Paste */ {"I185", 0x10b}, /* SCROLLUP# => normal speed */ {"I173", 0x110}, /* PREVIOUSSONG */ {"FIND", 0x112}, /* # Logitech */ - {"I156", 0x113}, /* PROG1# => Word */ - {"I157", 0x114}, /* PROG2# => Excel */ - {"I210", 0x115}, /* PROG3# => Calendar */ - {"I182", 0x116}, /* EXIT# => Log Off */ + {"I429", 0x113}, /* WORDPROCESSOR# => Word */ + {"I431", 0x114}, /* SPREADSHEET# => Excel */ + {"I405", 0x115}, /* CALENDAR# */ + {"I441", 0x116}, /* LOGOFF# */ {"CUT", 0x117}, /* # */ {"COPY", 0x118}, /* # */ {"I171", 0x119}, /* NEXTSONG */ @@ -181,7 +195,7 @@ std::unordered_map xkb_keycodes{ {"MUTE", 0x120}, {"I148", 0x121}, /* CALC */ {"I172", 0x122}, /* PLAYPAUSE */ - {"I158", 0x123}, /* WWW# => Compaq online start */ + {"I440", 0x123}, /* SPELLCHECK# */ {"I174", 0x124}, /* STOPCD */ {"I147", 0x126}, /* MENU# => Shortcut/Menu/Help for a few OEMs */ {"VOL-", 0x12e}, @@ -189,9 +203,12 @@ std::unordered_map xkb_keycodes{ {"I169", 0x12f}, /* EJECTCD# => Logitech */ {"I170", 0x12f}, /* EJECTCLOSECD# => Logitech */ {"VOL+", 0x130}, + {"I158", 0x132}, /* WWW# */ {"I180", 0x132}, /* HOMEPAGE */ + {"I642", 0x137}, /* SELECTIVE_SCREENSHOT# => SysRq */ {"HELP", 0x13b}, /* # */ - {"I221", 0x13c}, /* SOUND# => My Music */ + {"I221", 0x13c}, /* SOUND# => My Music/Office Home */ + {"I368", 0x13c}, /* VENDOR# => My Music/Office Home */ {"I212", 0x13d}, /* DASHBOARD# => Task Pane */ {"I189", 0x13e}, /* NEW# */ {"OPEN", 0x13f}, /* # */ @@ -213,6 +230,7 @@ std::unordered_map xkb_keycodes{ {"I220", 0x164}, /* CAMERA# => My Pictures */ {"I225", 0x165}, /* SEARCH */ {"I164", 0x166}, /* BOOKMARKS => Favorites */ + {"I372", 0x166}, /* FAVORITES# */ {"I181", 0x167}, /* REFRESH */ {"STOP", 0x168}, {"I167", 0x169}, /* FORWARD */ @@ -222,7 +240,7 @@ std::unordered_map xkb_keycodes{ {"I223", 0x16c}, /* EMAIL# */ {"I234", 0x16d}, /* MEDIA */ {"I175", 0x178}, /* RECORD# => Logitech */ - {"I160", 0x17a}, /* COFFEE# */ + {"I160", 0x17a}, /* COFFEE/SCREENLOCK# */ {"I186", 0x18b}, /* SCROLLDOWN# => normal speed */ }; struct xkb_keymap *xkbcommon_keymap = nullptr; @@ -244,23 +262,21 @@ uint16_t xkbcommon_translate(uint32_t keycode) { const char *key_name = xkb_keymap_key_get_name(xkbcommon_keymap, keycode); - if (!key_name) { - qWarning() << "XKB Keyboard: Unknown keycode" << Qt::hex << keycode; - return 0; - } - std::string key_name_s(key_name); - uint16_t ret = xkb_keycodes[key_name_s]; + /* If XKB doesn't know the key name for this keycode, assume an unnamed Ixxx key. + This is useful for older XKB versions with an incomplete evdev keycode map. */ + auto key_name_s = key_name ? std::string(key_name) : QString("I%1").arg(keycode).toStdString(); + auto ret = xkb_keycodes[key_name_s]; - /* Observed with multimedia keys on a Windows X11 client. */ + /* Observed with multimedia keys on Windows VcXsrv. */ if (!ret && (key_name_s.length() == 3) && (key_name_s[0] == 'I') && IS_HEX_DIGIT(key_name_s[1]) && IS_HEX_DIGIT(key_name_s[2])) ret = 0x100 | stoi(key_name_s.substr(1), nullptr, 16); if (!ret) - qWarning() << "XKB Keyboard: Unknown key" << Qt::hex << keycode << "/" << QString::fromStdString(key_name_s); + qWarning() << "XKB Keyboard: Unknown key" << Qt::hex << keycode << QString::fromStdString(key_name_s); #if 0 else - qInfo() << "XKB Keyboard: Key" << Qt::hex << keycode << "/" << QString::fromStdString(key_name_s) << "scancode" << Qt::hex << ret; + qInfo() << "XKB Keyboard: Key" << Qt::hex << keycode << QString::fromStdString(key_name_s) << "scancode" << Qt::hex << ret; #endif return ret; From a80e9501b831c1d275e6db6ce35895c69a0e86b8 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 17:58:55 -0300 Subject: [PATCH 11/13] qt: Add evdev keycode mapper --- src/qt/CMakeLists.txt | 2 +- src/qt/evdev_keyboard.cpp | 134 ++++++++++++++++++++++++++++++++++ src/qt/evdev_keyboard.hpp | 20 +++++ src/qt/qt_mainwindow.cpp | 53 ++++---------- src/qt/xkbcommon_keyboard.cpp | 95 +++++------------------- 5 files changed, 190 insertions(+), 114 deletions(-) create mode 100644 src/qt/evdev_keyboard.cpp create mode 100644 src/qt/evdev_keyboard.hpp diff --git a/src/qt/CMakeLists.txt b/src/qt/CMakeLists.txt index dd3bc6f79..614da7a00 100644 --- a/src/qt/CMakeLists.txt +++ b/src/qt/CMakeLists.txt @@ -365,7 +365,7 @@ endif() if (UNIX AND NOT APPLE AND NOT HAIKU) find_package(X11 REQUIRED) target_link_libraries(ui PRIVATE X11::X11 X11::Xi) - target_sources(ui PRIVATE xinput2_mouse.cpp) + target_sources(ui PRIVATE evdev_keyboard.cpp xinput2_mouse.cpp) find_package(PkgConfig REQUIRED) pkg_check_modules(LIBEVDEV IMPORTED_TARGET libevdev) if (LIBEVDEV_FOUND) diff --git a/src/qt/evdev_keyboard.cpp b/src/qt/evdev_keyboard.cpp new file mode 100644 index 000000000..4eba75e26 --- /dev/null +++ b/src/qt/evdev_keyboard.cpp @@ -0,0 +1,134 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * evdev keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +#include +#include + +static std::unordered_map evdev_keycodes{ + {99, 0x54}, /* SYSRQ */ + {86, 0x56}, /* 102ND */ + {87, 0x57}, /* F11 */ + {88, 0x58}, /* F12 */ + {117, 0x59}, /* KPEQUAL */ + {95, 0x5c}, /* KPJPCOMMA */ + {183, 0x5d}, /* F13 */ + {184, 0x5e}, /* F14 */ + {185, 0x5f}, /* F15 */ + {93, 0x70}, /* KATAKANAHIRAGANA */ + {89, 0x73}, /* RO */ + {85, 0x76}, /* ZENKAKUHANKAKU */ + {91, 0x77}, /* HIRAGANA */ + {90, 0x78}, /* KATAKANA */ + {92, 0x79}, /* HENKAN */ + {94, 0x7b}, /* MUHENKAN */ + {124, 0x7d}, /* YEN */ + {121, 0x7e}, /* KPCOMMA */ + + /* Multimedia keys. Guideline is to try and follow the Microsoft standard, then + fill in remaining scancodes with OEM-specific keys for redundancy sake. Keys + marked with # are not translated into evdev codes by the standard atkbd driver. */ + {117, 0x59}, /* Num= */ + {418, 0x6a}, /* ZOOMIN# => Logitech */ + {420, 0x6b}, /* ZOOMRESET# => Logitech */ + {223, 0x6d}, /* CANCEL# => Logitech */ + {132, 0x101}, /* # Logitech Task Select */ + {148, 0x102}, /* PROG1# => Samsung */ + {149, 0x103}, /* PROG2# => Samsung */ + {419, 0x104}, /* ZOOMOUT# => Logitech */ + {144, 0x105}, /* FILE# => Messenger/Files */ + {216, 0x105}, /* CHAT# => Messenger/Files */ + {430, 0x105}, /* MESSENGER# */ + {182, 0x107}, /* REDO# */ + {131, 0x108}, /* UNDO# */ + {135, 0x10a}, /* PASTE# */ + {177, 0x10b}, /* SCROLLUP# => normal speed */ + {165, 0x110}, /* PREVIOUSSONG */ + {136, 0x112}, /* FIND# => Logitech */ + {421, 0x113}, /* WORDPROCESSOR# => Word */ + {423, 0x114}, /* SPREADSHEET# => Excel */ + {397, 0x115}, /* CALENDAR# */ + {433, 0x116}, /* LOGOFF# */ + {137, 0x117}, /* CUT# */ + {133, 0x118}, /* COPY# */ + {163, 0x119}, /* NEXTSONG */ + {154, 0x11e}, /* CYCLEWINDOWS => Application Right (no left counterpart) */ + {113, 0x120}, /* MUTE */ + {140, 0x121}, /* CALC */ + {164, 0x122}, /* PLAYPAUSE */ + {432, 0x123}, /* SPELLCHECK# */ + {166, 0x124}, /* STOPCD */ + {139, 0x126}, /* MENU# => Shortcut/Menu/Help for a few OEMs */ + {114, 0x12e}, /* VOL- */ + {160, 0x12f}, /* CLOSECD# => Logitech Eject */ + {161, 0x12f}, /* EJECTCD# => Logitech */ + {162, 0x12f}, /* EJECTCLOSECD# => Logitech */ + {115, 0x130}, /* VOL+ */ + {150, 0x132}, /* WWW# */ + {172, 0x132}, /* HOMEPAGE */ + {634, 0x137}, /* SELECTIVE_SCREENSHOT# => SysRq */ + {138, 0x13b}, /* HELP# */ + {213, 0x13c}, /* SOUND# => My Music/Office Home */ + {360, 0x13c}, /* VENDOR# => My Music/Office Home */ + {204, 0x13d}, /* DASHBOARD# => Task Pane */ + {181, 0x13e}, /* NEW# */ + {134, 0x13f}, /* OPEN# */ + {206, 0x140}, /* CLOSE# */ + {232, 0x141}, /* REPLY# */ + {233, 0x142}, /* FORWARDMAIL# */ + {231, 0x143}, /* SEND# */ + {151, 0x144}, /* MSDOS# */ + {112, 0x14c}, /* MACRO */ + {179, 0x14c}, /* KPLEFTPAREN# */ + {118, 0x14e}, /* KPPLUSMINUS */ + {235, 0x155}, /* DOCUMENTS# => Logitech */ + {234, 0x157}, /* SAVE# */ + {210, 0x158}, /* PRINT# */ + {116, 0x15e}, /* POWER */ + {142, 0x15f}, /* SLEEP */ + {143, 0x163}, /* WAKEUP */ + {180, 0x164}, /* KPRIGHTPAREN# */ + {212, 0x164}, /* CAMERA# => My Pictures */ + {217, 0x165}, /* SEARCH */ + {156, 0x166}, /* BOOKMARKS => Favorites */ + {364, 0x166}, /* FAVORITES# */ + {173, 0x167}, /* REFRESH */ + {128, 0x168}, /* STOP */ + {159, 0x169}, /* FORWARD */ + {158, 0x16a}, /* BACK */ + {157, 0x16b}, /* COMPUTER */ + {155, 0x16c}, /* MAIL */ + {215, 0x16c}, /* EMAIL# */ + {226, 0x16d}, /* MEDIA */ + {167, 0x178}, /* RECORD# => Logitech */ + {152, 0x17a}, /* COFFEE/SCREENLOCK# */ + {178, 0x18b}, /* SCROLLDOWN# => normal speed */ +}; + +uint16_t +evdev_translate(uint32_t keycode) +{ + /* "for 1-83 (0x01-0x53) scancode equals keycode" */ + auto ret = (keycode <= 0x53) ? keycode : evdev_keycodes[keycode]; + + if (!ret) + qWarning() << "Evdev Keyboard: Unknown key" << keycode; +#if 0 + else + qInfo() << "Evdev Keyboard: Key" << keycode << "scancode" << Qt::hex << ret; +#endif + + return ret; +} diff --git a/src/qt/evdev_keyboard.hpp b/src/qt/evdev_keyboard.hpp new file mode 100644 index 000000000..5efe5958d --- /dev/null +++ b/src/qt/evdev_keyboard.hpp @@ -0,0 +1,20 @@ +/* + * 86Box A hypervisor and IBM PC system emulator that specializes in + * running old operating systems and software designed for IBM + * PC systems and compatibles from 1981 through fairly recent + * system designs based on the PCI bus. + * + * This file is part of the 86Box distribution. + * + * Definitions for evdev keyboard input module. + * + * + * + * Authors: RichardG, + * + * Copyright 2023 RichardG. + */ +#ifndef EVDEV_KEYBOARD_HPP +#define EVDEV_KEYBOARD_HPP +uint16_t evdev_translate(uint32_t keycode); +#endif diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index a8957b476..8e8208dcc 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -96,6 +96,9 @@ extern int qt_nvr_save(void); #include "qt_util.hpp" #if defined __unix__ && !defined __HAIKU__ +# ifndef Q_OS_MACOS +# include "evdev_keyboard.hpp" +# endif # ifdef XKBCOMMON # include "xkbcommon_keyboard.hpp" # ifdef XKBCOMMON_X11 @@ -1378,27 +1381,6 @@ std::array darwin_to_xt { }; #endif -#if defined(__unix__) && !defined(__HAIKU__) -static std::unordered_map evdev_to_xt = { - {96, 0x11C}, - { 97, 0x11D}, - { 98, 0x135}, - { 99, 0x71 }, - { 100, 0x138}, - { 101, 0x1C }, - { 102, 0x147}, - { 103, 0x148}, - { 104, 0x149}, - { 105, 0x14B}, - { 106, 0x14D}, - { 107, 0x14F}, - { 108, 0x150}, - { 109, 0x151}, - { 110, 0x152}, - { 111, 0x153} -}; -#endif - #ifdef __HAIKU__ static std::unordered_map be_to_xt = { {0x01, 0x01 }, @@ -1528,28 +1510,25 @@ x11_keycode_to_keysym(uint32_t keycode) if (xkbcommon_keymap) { finalkeycode = xkbcommon_translate(keycode); } else +# endif +# ifdef EVDEV_KEYBOARD_HPP + if (QApplication::platformName().contains("eglfs")) { + finalkeycode = evdev_translate(keycode); + } else # endif { static Display *x11display = nullptr; - if (QApplication::platformName().contains("eglfs")) { - keycode -= 8; - if (keycode <= 88) - finalkeycode = keycode; - else - finalkeycode = evdev_to_xt[keycode]; - } else { - if (QApplication::platformName().contains("wayland")) { + if (QApplication::platformName().contains("wayland")) { + selected_keycode = x11_to_xt_2; + } else if (!x11display) { + x11display = XOpenDisplay(nullptr); + if (XKeysymToKeycode(x11display, XK_Home) == 110) { selected_keycode = x11_to_xt_2; - } else if (!x11display) { - x11display = XOpenDisplay(nullptr); - if (XKeysymToKeycode(x11display, XK_Home) == 110) { - selected_keycode = x11_to_xt_2; - } else if (XKeysymToKeycode(x11display, XK_Home) == 69) { - selected_keycode = x11_to_xt_vnc; - } + } else if (XKeysymToKeycode(x11display, XK_Home) == 69) { + selected_keycode = x11_to_xt_vnc; } - finalkeycode = selected_keycode[keycode]; } + finalkeycode = selected_keycode[keycode]; } #endif /* Special case for Ctrl+Pause. */ diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp index e0560117b..953008453 100644 --- a/src/qt/xkbcommon_keyboard.cpp +++ b/src/qt/xkbcommon_keyboard.cpp @@ -20,10 +20,12 @@ extern "C" { #include #include +#include "evdev_keyboard.hpp" -#define IS_HEX_DIGIT(c) ((((c) >= '0') && ((c) <= '9')) || (((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && ((c) <= 'f'))) +#define IS_DEC_DIGIT(c) (((c) >= '0') && ((c) <= '9')) +#define IS_HEX_DIGIT(c) (IS_DEC_DIGIT(c) || (((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && ((c) <= 'f'))) -std::unordered_map xkb_keycodes{ +static std::unordered_map xkb_keycodes{ {"ESC", 0x01}, {"AE01", 0x02}, {"AE02", 0x03}, @@ -100,7 +102,6 @@ std::unordered_map xkb_keycodes{ {"NMLK", 0x45}, {"SCLK", 0x46}, - {"FK14", 0x46}, /* F14 => Scroll Lock */ {"KP7", 0x47}, {"KP8", 0x48}, {"KP9", 0x49}, @@ -118,19 +119,22 @@ std::unordered_map xkb_keycodes{ {"LSGT", 0x56}, {"FK11", 0x57}, {"FK12", 0x58}, + {"FK13", 0x5d}, + {"FK14", 0x5e}, + {"FK15", 0x5f}, /* Japanese keys. */ - {"HZTG", 0x29}, /* hankaku-zenkaku toggle => ~ */ - {"HKTG", 0x70}, /* hiragana-katakana toggle... */ - {"HIRA", 0x70}, /* ...and individual keys */ - {"KATA", 0x70}, + {"JPCM", 0x5c}, /* evdev KPJPCOMMA */ + {"HKTG", 0x70}, /* hiragana-katakana toggle */ {"AB11", 0x73}, /* \_ and Brazilian /? */ + {"HZTG", 0x76}, /* hankaku-zenkaku toggle */ + {"HIRA", 0x77}, + {"KATA", 0x78}, {"HENK", 0x79}, {"MUHE", 0x7b}, {"AE13", 0x7d}, /* \| */ {"KPPT", 0x7e}, /* Brazilian Num. */ {"I06", 0x7e}, /* alias of KPPT on keycodes/xfree86 (i.e. X11 forwarding) */ - {"I129", 0x7e}, /* another alias: evdev KPCOMMA */ /* Korean keys. */ {"HJCV", 0xf1}, /* hancha toggle */ @@ -141,11 +145,9 @@ std::unordered_map xkb_keycodes{ {"KPDV", 0x135}, {"PRSC", 0x137}, {"SYRQ", 0x137}, - {"FK13", 0x137}, /* F13 => SysRq */ {"RALT", 0x138}, {"PAUS", 0x145}, {"BRK", 0x145}, - {"FK15", 0x145}, /* F15 => Pause */ {"HOME", 0x147}, {"UP", 0x148}, {"PGUP", 0x149}, @@ -164,84 +166,21 @@ std::unordered_map xkb_keycodes{ {"MENU", 0x15d}, {"COMP", 0x15d}, /* Compose as Menu */ - /* Multimedia keys, using Linux evdev-specific keycodes where required. Guideline is to try - and follow the Microsoft standard, then fill in some OEM-specific keys for redundancy sake. - Keys marked with # are not translated into evdev codes by the standard atkbd driver. */ + /* Multimedia keys. Same notes as evdev_keyboard apply here. */ {"KPEQ", 0x59}, /* Num= */ - {"I426", 0x6a}, /* ZOOMIN# => Logitech */ - {"I428", 0x6b}, /* ZOOMRESET# => Logitech */ - {"I231", 0x6d}, /* CANCEL# => Logitech */ {"FRNT", 0x101}, /* # Logitech Task Select */ - {"I156", 0x102}, /* PROG1# => Samsung */ - {"I157", 0x103}, /* PROG2# => Samsung */ - {"I427", 0x104}, /* ZOOMOUT# => Logitech */ - {"I152", 0x105}, /* FILE# => Messenger/Files */ - {"I224", 0x105}, /* CHAT# => Messenger/Files */ - {"I438", 0x105}, /* MESSENGER# */ - {"I190", 0x107}, /* REDO# */ {"UNDO", 0x108}, /* # */ {"PAST", 0x10a}, /* # Paste */ - {"I185", 0x10b}, /* SCROLLUP# => normal speed */ - {"I173", 0x110}, /* PREVIOUSSONG */ {"FIND", 0x112}, /* # Logitech */ - {"I429", 0x113}, /* WORDPROCESSOR# => Word */ - {"I431", 0x114}, /* SPREADSHEET# => Excel */ - {"I405", 0x115}, /* CALENDAR# */ - {"I441", 0x116}, /* LOGOFF# */ {"CUT", 0x117}, /* # */ {"COPY", 0x118}, /* # */ - {"I171", 0x119}, /* NEXTSONG */ - {"I162", 0x11e}, /* CYCLEWINDOWS => Application Right (no left counterpart) */ {"MUTE", 0x120}, - {"I148", 0x121}, /* CALC */ - {"I172", 0x122}, /* PLAYPAUSE */ - {"I440", 0x123}, /* SPELLCHECK# */ - {"I174", 0x124}, /* STOPCD */ - {"I147", 0x126}, /* MENU# => Shortcut/Menu/Help for a few OEMs */ {"VOL-", 0x12e}, - {"I168", 0x12f}, /* CLOSECD# => Logitech Eject */ - {"I169", 0x12f}, /* EJECTCD# => Logitech */ - {"I170", 0x12f}, /* EJECTCLOSECD# => Logitech */ {"VOL+", 0x130}, - {"I158", 0x132}, /* WWW# */ - {"I180", 0x132}, /* HOMEPAGE */ - {"I642", 0x137}, /* SELECTIVE_SCREENSHOT# => SysRq */ - {"HELP", 0x13b}, /* # */ - {"I221", 0x13c}, /* SOUND# => My Music/Office Home */ - {"I368", 0x13c}, /* VENDOR# => My Music/Office Home */ - {"I212", 0x13d}, /* DASHBOARD# => Task Pane */ - {"I189", 0x13e}, /* NEW# */ - {"OPEN", 0x13f}, /* # */ - {"I214", 0x140}, /* CLOSE# */ - {"I240", 0x141}, /* REPLY# */ - {"I241", 0x142}, /* FORWARDMAIL# */ - {"I239", 0x143}, /* SEND# */ - {"I159", 0x144}, /* MSDOS# */ - {"I120", 0x14c}, /* MACRO */ - {"I187", 0x14c}, /* KPLEFTPAREN# */ - {"I126", 0x14e}, /* KPPLUSMINUS */ - {"I243", 0x155}, /* DOCUMENTS# => Logitech */ - {"I242", 0x157}, /* SAVE# */ - {"I218", 0x158}, /* PRINT# */ + {"HELP", 0x13b}, + {"OPEN", 0x13f}, {"POWR", 0x15e}, - {"I150", 0x15f}, /* SLEEP */ - {"I151", 0x163}, /* WAKEUP */ - {"I188", 0x164}, /* KPRIGHTPAREN# */ - {"I220", 0x164}, /* CAMERA# => My Pictures */ - {"I225", 0x165}, /* SEARCH */ - {"I164", 0x166}, /* BOOKMARKS => Favorites */ - {"I372", 0x166}, /* FAVORITES# */ - {"I181", 0x167}, /* REFRESH */ {"STOP", 0x168}, - {"I167", 0x169}, /* FORWARD */ - {"I166", 0x16a}, /* BACK */ - {"I165", 0x16b}, /* COMPUTER */ - {"I163", 0x16c}, /* MAIL */ - {"I223", 0x16c}, /* EMAIL# */ - {"I234", 0x16d}, /* MEDIA */ - {"I175", 0x178}, /* RECORD# => Logitech */ - {"I160", 0x17a}, /* COFFEE/SCREENLOCK# */ - {"I186", 0x18b}, /* SCROLLDOWN# => normal speed */ }; struct xkb_keymap *xkbcommon_keymap = nullptr; @@ -272,6 +211,10 @@ xkbcommon_translate(uint32_t keycode) if (!ret && (key_name_s.length() == 3) && (key_name_s[0] == 'I') && IS_HEX_DIGIT(key_name_s[1]) && IS_HEX_DIGIT(key_name_s[2])) ret = 0x100 | stoi(key_name_s.substr(1), nullptr, 16); + /* Translate unnamed evdev-specific keycodes. */ + if (!ret && (key_name_s.length() >= 2) && (key_name_s[0] == 'I') && IS_DEC_DIGIT(key_name_s[1])) + ret = evdev_translate(stoi(key_name_s.substr(1)) - 8); + if (!ret) qWarning() << "XKB Keyboard: Unknown key" << Qt::hex << keycode << QString::fromStdString(key_name_s); #if 0 From ae9202327980060f938a8e63e1fbb90ab6469e6e Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 18:45:10 -0300 Subject: [PATCH 12/13] qt: Add missing evdev mappings and fix offset in native evdev mode --- src/qt/evdev_keyboard.cpp | 32 ++++++++++++++++++++++++++++++-- src/qt/qt_mainwindow.cpp | 2 +- src/qt/xkbcommon_keyboard.cpp | 2 +- 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/qt/evdev_keyboard.cpp b/src/qt/evdev_keyboard.cpp index 4eba75e26..3e66dc1ed 100644 --- a/src/qt/evdev_keyboard.cpp +++ b/src/qt/evdev_keyboard.cpp @@ -17,16 +17,18 @@ #include #include -static std::unordered_map evdev_keycodes{ +static std::unordered_map evdev_keycodes = { {99, 0x54}, /* SYSRQ */ {86, 0x56}, /* 102ND */ {87, 0x57}, /* F11 */ {88, 0x58}, /* F12 */ {117, 0x59}, /* KPEQUAL */ - {95, 0x5c}, /* KPJPCOMMA */ {183, 0x5d}, /* F13 */ {184, 0x5e}, /* F14 */ {185, 0x5f}, /* F15 */ + + /* Japanese keys. */ + {95, 0x5c}, /* KPJPCOMMA */ {93, 0x70}, /* KATAKANAHIRAGANA */ {89, 0x73}, /* RO */ {85, 0x76}, /* ZENKAKUHANKAKU */ @@ -37,6 +39,32 @@ static std::unordered_map evdev_keycodes{ {124, 0x7d}, /* YEN */ {121, 0x7e}, /* KPCOMMA */ + /* Korean keys. */ + {123, 0xf1}, /* HANJA */ + {122, 0xf2}, /* HANGUL */ + + {96, 0x11c}, /* KPENTER */ + {97, 0x11d}, /* RIGHTCTRL */ + {98, 0x135}, /* KPSLASH */ + {99, 0x137}, /* SYSRQ */ + {100, 0x138}, /* RIGHTALT */ + {119, 0x145}, /* PAUSE */ + {411, 0x145}, /* BREAK */ + {102, 0x147}, /* HOME */ + {103, 0x148}, /* UP */ + {104, 0x149}, /* PAGEUP */ + {105, 0x14b}, /* LEFT */ + {106, 0x14d}, /* RIGHT */ + {107, 0x14f}, /* END */ + {108, 0x150}, /* DOWN */ + {109, 0x151}, /* PAGEDOWN */ + {110, 0x152}, /* INSERT */ + {111, 0x153}, /* DELETE */ + + {125, 0x15b}, /* LEFTMETA */ + {126, 0x15c}, /* RIGHTMETA */ + {127, 0x15d}, /* COMPOSE => Menu */ + /* Multimedia keys. Guideline is to try and follow the Microsoft standard, then fill in remaining scancodes with OEM-specific keys for redundancy sake. Keys marked with # are not translated into evdev codes by the standard atkbd driver. */ diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index 8e8208dcc..a52ee7245 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -1513,7 +1513,7 @@ x11_keycode_to_keysym(uint32_t keycode) # endif # ifdef EVDEV_KEYBOARD_HPP if (QApplication::platformName().contains("eglfs")) { - finalkeycode = evdev_translate(keycode); + finalkeycode = evdev_translate(keycode - 8); } else # endif { diff --git a/src/qt/xkbcommon_keyboard.cpp b/src/qt/xkbcommon_keyboard.cpp index 953008453..1546b6faa 100644 --- a/src/qt/xkbcommon_keyboard.cpp +++ b/src/qt/xkbcommon_keyboard.cpp @@ -25,7 +25,7 @@ extern "C" { #define IS_DEC_DIGIT(c) (((c) >= '0') && ((c) <= '9')) #define IS_HEX_DIGIT(c) (IS_DEC_DIGIT(c) || (((c) >= 'A') && ((c) <= 'F')) || (((c) >= 'a') && ((c) <= 'f'))) -static std::unordered_map xkb_keycodes{ +static std::unordered_map xkb_keycodes = { {"ESC", 0x01}, {"AE01", 0x02}, {"AE02", 0x03}, From 4002b71da6d96c7664bfcf8a407bcfafd0a915d4 Mon Sep 17 00:00:00 2001 From: RichardG867 Date: Sat, 8 Apr 2023 18:58:26 -0300 Subject: [PATCH 13/13] qt: Remove legacy X11 input translators --- src/qt/qt_mainwindow.cpp | 371 +-------------------------------------- 1 file changed, 5 insertions(+), 366 deletions(-) diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index a52ee7245..95b881e64 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -905,349 +905,6 @@ MainWindow::on_actionSettings_triggered() plat_pause(currentPause); } -#if defined(__unix__) && !defined(__HAIKU__) -std::array x11_to_xt_base { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0x01, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0A, - 0x0B, - 0x0C, - 0x0D, - 0x0E, - 0x0F, - 0x10, - 0x11, - 0x12, - 0x13, - 0x14, - 0x15, - 0x16, - 0x17, - 0x18, - 0x19, - 0x1A, - 0x1B, - 0x1C, - 0x1D, - 0x1E, - 0x1F, - 0x20, - 0x21, - 0x22, - 0x23, - 0x24, - 0x25, - 0x26, - 0x27, - 0x28, - 0x29, - 0x2A, - 0x2B, - 0x2C, - 0x2D, - 0x2E, - 0x2F, - 0x30, - 0x31, - 0x32, - 0x33, - 0x34, - 0x35, - 0x36, - 0x37, - 0x38, - 0x39, - 0x3A, - 0x3B, - 0x3C, - 0x3D, - 0x3E, - 0x3F, - 0x40, - 0x41, - 0x42, - 0x43, - 0x44, - 0x45, - 0x46, - 0x47, - 0x48, - 0x49, - 0x4A, - 0x4B, - 0x4C, - 0x4D, - 0x4E, - 0x4F, - 0x50, - 0x51, - 0x52, - 0x53, - 0x54, - 0x55, - 0x56, - 0x57, - 0x58, - 0x147, - 0x148, - 0x149, - 0, - 0x14B, - 0, - 0x14D, - 0x14F, - 0x150, - 0x151, - 0x152, - 0x153, - 0x11C, - 0x11D, - 0, // Pause/Break key. - 0x137, - 0x135, - 0x138, - 0, // Ditto as above comment. - 0x15B, - 0x15C, - 0x15D, -}; - -std::array x11_to_xt_2 { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0x01, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0A, - 0x0B, - 0x0C, - 0x0D, - 0x0E, - 0x0F, - 0x10, - 0x11, - 0x12, - 0x13, - 0x14, - 0x15, - 0x16, - 0x17, - 0x18, - 0x19, - 0x1A, - 0x1B, - 0x1C, - 0x1D, - 0x1E, - 0x1F, - 0x20, - 0x21, - 0x22, - 0x23, - 0x24, - 0x25, - 0x26, - 0x27, - 0x28, - 0x29, - 0x2A, - 0x2B, - 0x2C, - 0x2D, - 0x2E, - 0x2F, - 0x30, - 0x31, - 0x32, - 0x33, - 0x34, - 0x35, - 0x36, - 0x37, - 0x38, - 0x39, - 0x3A, - 0x3B, - 0x3C, - 0x3D, - 0x3E, - 0x3F, - 0x40, - 0x41, - 0x42, - 0x43, - 0x44, - 0x45, - 0x46, - 0x47, - 0x48, - 0x49, - 0x4A, - 0x4B, - 0x4C, - 0x4D, - 0x4E, - 0x4F, - 0x50, - 0x51, - 0x52, - 0x53, - 0x138, - 0x55, - 0x56, - 0x57, - 0x58, - 0x56, - 0x70, - 0x7B, - 0x7D, - 0x2B, - 0x7E, - 0, - 0x11C, - 0x11D, - 0x135, - 0x137, - 0x138, - 0, - 0x147, - 0x148, - 0x149, - 0x14B, - 0x14D, - 0x14F, - 0x150, - 0x151, - 0x152, - 0x153, - 0, - 0, /* Mute */ - 0, /* Volume Down */ - 0, /* Volume Up */ - 0, /* Power Off */ - 0, - 0, - 0, - 0, - 0, - 0x70, - 0x7B, - 0x73, - 0x15B, - 0x15C, - 0x15D -}; - -std::array x11_to_xt_vnc { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0x1D, - 0x11D, - 0x2A, - 0x36, - 0, - 0, - 0x38, - 0x138, - 0x39, - 0x0B, - 0x02, - 0x03, - 0x04, - 0x05, - 0x06, - 0x07, - 0x08, - 0x09, - 0x0A, - 0x0C, - 0x0D, - 0x1A, - 0x1B, - 0x27, - 0x28, - 0x29, - 0x33, - 0x34, - 0x35, - 0x2B, - 0x1E, - 0x30, - 0x2E, - 0x20, - 0x12, - 0x21, - 0x22, - 0x23, - 0x17, - 0x24, - 0x25, - 0x26, - 0x32, - 0x31, - 0x18, - 0x19, - 0x10, - 0x13, - 0x1F, - 0x14, - 0x16, - 0x2F, - 0x11, - 0x2D, - 0x15, - 0x2C, - 0x0E, - 0x1C, - 0x0F, - 0x01, - 0x153, - 0x147, - 0x14F, - 0x149, - 0x151, - 0x148, - 0x150, - 0x14B, - 0x14D, -}; -#endif - #ifdef Q_OS_MACOS std::array darwin_to_xt { 0x1E, @@ -1491,14 +1148,10 @@ static std::unordered_map be_to_xt = { }; #endif -#if defined(__unix__) && !defined(__HAIKU__) -static std::array &selected_keycode = x11_to_xt_base; -#endif - uint16_t x11_keycode_to_keysym(uint32_t keycode) { - uint16_t finalkeycode = 0; + uint16_t finalkeycode; #if defined(Q_OS_WINDOWS) finalkeycode = (keycode & 0xFFFF); #elif defined(Q_OS_MACOS) @@ -1507,29 +1160,15 @@ x11_keycode_to_keysym(uint32_t keycode) finalkeycode = be_to_xt[keycode]; #else # ifdef XKBCOMMON - if (xkbcommon_keymap) { + if (xkbcommon_keymap) finalkeycode = xkbcommon_translate(keycode); - } else + else # endif # ifdef EVDEV_KEYBOARD_HPP - if (QApplication::platformName().contains("eglfs")) { finalkeycode = evdev_translate(keycode - 8); - } else +# else + finalkeycode = 0; # endif - { - static Display *x11display = nullptr; - if (QApplication::platformName().contains("wayland")) { - selected_keycode = x11_to_xt_2; - } else if (!x11display) { - x11display = XOpenDisplay(nullptr); - if (XKeysymToKeycode(x11display, XK_Home) == 110) { - selected_keycode = x11_to_xt_2; - } else if (XKeysymToKeycode(x11display, XK_Home) == 69) { - selected_keycode = x11_to_xt_vnc; - } - } - finalkeycode = selected_keycode[keycode]; - } #endif /* Special case for Ctrl+Pause. */ if ((finalkeycode == 0x145) && (keyboard_recv(0x1d) || keyboard_recv(0x11d)))