From b0d8df6f125ace41de97c5caf3d01cda5e9a380d Mon Sep 17 00:00:00 2001 From: "Roessel, Mario (DI MC MTS SP SWHMI 3)" Date: Fri, 24 Feb 2023 15:35:36 +0100 Subject: [PATCH] Fix missing Qt::KeypadModifier for local keyboard input on Linux Keyboard input on Linux with a local keyboard is handled in the Wayland Compositor. The compositor receives QKeyEvents of the keyboard in its compositor window. The data of those QKeyEvents (key code, modifiers, etc.) is retrieved from the xkbcommon library in WindowSystemEventHandler::handleKeyEvent() in qwaylandcompositor.cpp via a wrapper class, QWaylandXkb in Qt 5.12, QXkbCommon in Qt 5.15. In Qt 5.12 the modifier data came from two different sources (methods): QWaylandXkb::modifiers() and QWaylandXkb::keysymToQtKey(). The Qt::KeypadModifier was added in QWaylandXkb::keysymToQtKey(). In Qt 5.15 QWaylandXkb was refactored to a new class QXkbCommon in the platform support of QtBase. QXkbCommon::modifiers() is identical to QWaylandXkb::modifiers(). But QXkbCommon::keysymToQtKey() does no longer change the modifier flags. Therefore Qt::KeypadModifier is never set. This commit extends the QXkbCommon::modifiers() method to also set the Qt::KeypadModifier. This is a bugfix for #416184 and #415580. --- .../platformsupport/input/libinput/qlibinputkeyboard.cpp | 4 ++-- .../src/platformsupport/input/xkbcommon/qxkbcommon.cpp | 8 +++++--- .../src/platformsupport/input/xkbcommon/qxkbcommon_p.h | 2 +- .../src/compositor/compositor_api/qwaylandcompositor.cpp | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/qtbase/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/qtbase/src/platformsupport/input/libinput/qlibinputkeyboard.cpp index 405225937b..9382c1864c 100644 --- a/src/qtbase/src/platformsupport/input/libinput/qlibinputkeyboard.cpp +++ b/src/qtbase/src/platformsupport/input/libinput/qlibinputkeyboard.cpp @@ -109,14 +109,14 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e) // Modifiers here is the modifier state before the event, i.e. not // including the current key in case it is a modifier. See the XOR // logic in QKeyEvent::modifiers(). ### QTBUG-73826 - Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(m_state); + Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(m_state, sym); const QString text = QXkbCommon::lookupString(m_state, keycode); const int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, m_state, keycode); xkb_state_update_key(m_state, keycode, pressed ? XKB_KEY_DOWN : XKB_KEY_UP); - Qt::KeyboardModifiers modifiersAfterStateChange = QXkbCommon::modifiers(m_state); + Qt::KeyboardModifiers modifiersAfterStateChange = QXkbCommon::modifiers(m_state, sym); QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(modifiersAfterStateChange); QWindowSystemInterface::handleExtendedKeyEvent(nullptr, diff --git a/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp b/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp index 313e861585..12e01c11d3 100644 --- a/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp +++ b/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon.cpp @@ -544,8 +544,8 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod // function keys qtKey = Qt::Key_F1 + (keysym - XKB_KEY_F1); } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) { - // numeric keypad keys - qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0); + // numeric keypad keys + qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0); } else if (QXkbCommon::isLatin(keysym)) { qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym); } else { @@ -591,7 +591,7 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod return qtKey; } -Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state) +Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state, xkb_keysym_t keysym) { Qt::KeyboardModifiers modifiers = Qt::NoModifier; @@ -603,6 +603,8 @@ Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state) modifiers |= Qt::ShiftModifier; if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0) modifiers |= Qt::MetaModifier; + if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) + modifiers |= Qt::KeypadModifier; return modifiers; } diff --git a/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h index 86cda12862..ce871a7ce9 100644 --- a/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h +++ b/src/qtbase/src/platformsupport/input/xkbcommon/qxkbcommon_p.h @@ -86,7 +86,7 @@ public: static void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper); static xkb_keysym_t qxkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks); - static Qt::KeyboardModifiers modifiers(struct xkb_state *state); + static Qt::KeyboardModifiers modifiers(struct xkb_state *state, xkb_keysym_t keysym = XKB_KEY_VoidSymbol); static QList possibleKeys(xkb_state *state, const QKeyEvent *event, bool superAsMeta = false, bool hyperAsMeta = false); diff --git a/src/qtwayland/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/qtwayland/src/compositor/compositor_api/qwaylandcompositor.cpp index 483bae4044..cdeb58a9f6 100644 --- a/src/qtwayland/src/compositor/compositor_api/qwaylandcompositor.cpp +++ b/src/qtwayland/src/compositor/compositor_api/qwaylandcompositor.cpp @@ -128,9 +128,9 @@ public: #if QT_CONFIG(xkbcommon) xkb_state *xkbState = keyb->xkbState(); - Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(xkbState); const xkb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code); + Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(xkbState, sym); int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, xkbState, code); QString text = QXkbCommon::lookupString(xkbState, code); -- 2.39.1.windows.1