From 27c25fc909c19ddc4750f36d26b7c500db9eb0ab Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Wed, 27 Oct 2021 12:01:41 +0200 Subject: xcb: stablilize xkb state when keymap updated QXcbKeyboard only deals with core_device_id. With the reporter's test case: using xdotool to send a string, the deviceID is not changed, then we assume xkb_state_new() is more stable(or correct) than xkb_x11_state_new_from_device() in this case. See also https://www.x.org/releases/current/doc/man/man3/xcb_xkb_new_keyboard_notify_event_t.3.xhtml . Fixes: QTBUG-95933 Pick-to: 6.2 5.15 Change-Id: Ic595e1f1424fbc6814871a85ac159907f1aeb12a Reviewed-by: Qt CI Bot Reviewed-by: Zhang Hao Reviewed-by: Liang Qi --- src/plugins/platforms/xcb/qxcbconnection.cpp | 2 +- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 24 ++++++++++++++++++++---- src/plugins/platforms/xcb/qxcbkeyboard.h | 1 + 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'src/plugins/platforms/xcb') diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index d6257c70b5..191d5af26c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -773,7 +773,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) case XCB_XKB_NEW_KEYBOARD_NOTIFY: { xcb_xkb_new_keyboard_notify_event_t *ev = &xkb_event->new_keyboard_notify; if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES) - m_keyboard->updateKeymap(); + m_keyboard->updateKeymap(ev); break; } default: diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 9ab804ca1b..48abbbf74c 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -365,6 +365,17 @@ void QXcbKeyboard::updateKeymap(xcb_mapping_notify_event_t *event) updateKeymap(); } +void QXcbKeyboard::updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event) +{ + if (!event) + return; + + if (event->deviceID != event->oldDeviceID) + m_config = false; + + updateKeymap(); +} + void QXcbKeyboard::updateKeymap() { KeysymModifierMap keysymMods; @@ -372,8 +383,6 @@ void QXcbKeyboard::updateKeymap() keysymMods = keysymsToModifiers(); updateModifiers(keysymMods); - m_config = true; - if (!m_xkbContext) { m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES)); if (!m_xkbContext) { @@ -389,8 +398,13 @@ void QXcbKeyboard::updateKeymap() if (connection()->hasXKB()) { m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(), core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS)); - if (m_xkbKeymap) - m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id)); + if (m_xkbKeymap) { + if (m_config) + m_xkbState.reset(xkb_state_new(m_xkbKeymap.get())); + else + m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id)); + + } } else { m_xkbKeymap.reset(keymapFromCore(keysymMods)); if (m_xkbKeymap) @@ -411,6 +425,8 @@ void QXcbKeyboard::updateKeymap() updateXKBMods(); QXkbCommon::verifyHasLatinLayout(m_xkbKeymap.get()); + + m_config = true; } QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index cf89acff6d..aaf4577985 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -69,6 +69,7 @@ public: Qt::KeyboardModifiers translateModifiers(int s) const; void updateKeymap(xcb_mapping_notify_event_t *event); + void updateKeymap(xcb_xkb_new_keyboard_notify_event_t *event); void updateKeymap(); QList possibleKeys(const QKeyEvent *event) const; -- cgit v1.2.3