File 0001-Fix-keyboard-layout-change-notifications.patch of Package kglobalaccel.openSUSE_Leap_15.0_Update
From 4d28bd4183d20a9bff4f50e88cbb47ffef0ede43 Mon Sep 17 00:00:00 2001
From: Fabian Vogt <fabian@ritter-vogt.de>
Date: Fri, 26 Oct 2018 10:01:03 +0200
Subject: [PATCH] Fix keyboard layout change notifications
Summary:
This rework fixes several issues:
- Qt wasn't informed about XCB_MAPPING_NOTIFY anymore
- With XKB enabled in Qt, X won't send XCB_MAPPING_NOTIFY anymore.
So listen for XKB events as well.
- Install the event filter before fetching the keysym mapping to
close a race window
- Use the old mapping for ungrabbing
BUG: 350816
BUG: 269403
Test Plan:
Ctrl-Alt-Y global shortcut works even when doing
"setxkbmap us; kglobalaccel5 & sleep 1; setxkbmap de;" while it did not
before. On some systems, this race happened on every login, now it works
reliably.
Reviewers: #frameworks, #plasma, romangg
Reviewed By: #plasma, romangg
Subscribers: romangg, ngraham, anthonyfieroni, kde-frameworks-devel
Tags: #frameworks
Differential Revision: https://phabricator.kde.org/D16434
---
CMakeLists.txt | 2 +-
src/runtime/plugins/CMakeLists.txt | 2 +-
src/runtime/plugins/xcb/CMakeLists.txt | 1 +
src/runtime/plugins/xcb/kglobalaccel_x11.cpp | 76 ++++++++++++++------
src/runtime/plugins/xcb/kglobalaccel_x11.h | 1 +
5 files changed, 59 insertions(+), 23 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 85c5913..c12fb4d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -49,7 +49,7 @@ find_package(KF5WindowSystem ${KF5_DEP_VERSION} REQUIRED)
# no X11 stuff on mac
if (NOT APPLE)
- find_package(XCB MODULE COMPONENTS XCB KEYSYMS XTEST)
+ find_package(XCB MODULE COMPONENTS XCB KEYSYMS XTEST XKB)
set_package_properties(XCB PROPERTIES DESCRIPTION "X protocol C-language Binding"
URL "http://xcb.freedesktop.org"
TYPE OPTIONAL
diff --git a/src/runtime/plugins/CMakeLists.txt b/src/runtime/plugins/CMakeLists.txt
index 316b9bf..29e45d4 100644
--- a/src/runtime/plugins/CMakeLists.txt
+++ b/src/runtime/plugins/CMakeLists.txt
@@ -1,4 +1,4 @@
-if (${XCB_XCB_FOUND} AND ${XCB_KEYSYMS_FOUND})
+if (${XCB_XCB_FOUND} AND ${XCB_KEYSYMS_FOUND} AND ${XCB_XKB_FOUND})
add_subdirectory(xcb)
endif()
# if (APPLE)
diff --git a/src/runtime/plugins/xcb/CMakeLists.txt b/src/runtime/plugins/xcb/CMakeLists.txt
index 45bf4dc..b76477f 100644
--- a/src/runtime/plugins/xcb/CMakeLists.txt
+++ b/src/runtime/plugins/xcb/CMakeLists.txt
@@ -8,6 +8,7 @@ target_link_libraries(KF5GlobalAccelPrivateXcb
KF5GlobalAccelPrivate
XCB::XCB
XCB::KEYSYMS
+ XCB::XKB
)
install(
diff --git a/src/runtime/plugins/xcb/kglobalaccel_x11.cpp b/src/runtime/plugins/xcb/kglobalaccel_x11.cpp
index 9b75ec4..cdee881 100644
--- a/src/runtime/plugins/xcb/kglobalaccel_x11.cpp
+++ b/src/runtime/plugins/xcb/kglobalaccel_x11.cpp
@@ -33,9 +33,13 @@
#include <X11/keysym.h>
// xcb
+
+// It uses "explicit" as a variable name, which is not allowed in C++
+#define explicit xcb_explicit
#include <xcb/xcb.h>
#include <xcb/xcb_keysyms.h>
-
+#include <xcb/xkb.h>
+#undef explicit
// g_keyModMaskXAccel
// mask of modifiers which can be used in shortcuts
@@ -63,11 +67,16 @@ static void calculateGrabMasks()
KGlobalAccelImpl::KGlobalAccelImpl(QObject *parent)
: KGlobalAccelInterface(parent)
, m_keySymbols(nullptr)
+ , m_xkb_first_event(0)
{
+ Q_ASSERT(QX11Info::connection());
+
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(QX11Info::connection(), &xcb_xkb_id);
+ if (reply && reply->present) {
+ m_xkb_first_event = reply->first_event;
+ }
+
calculateGrabMasks();
- if (QX11Info::isPlatformX11()) {
- m_keySymbols = xcb_key_symbols_alloc(QX11Info::connection());
- }
}
KGlobalAccelImpl::~KGlobalAccelImpl()
@@ -87,8 +96,12 @@ bool KGlobalAccelImpl::grabKey( int keyQt, bool grab )
}
if (!m_keySymbols) {
- return false;
+ m_keySymbols = xcb_key_symbols_alloc(QX11Info::connection());
+ if (!m_keySymbols) {
+ return false;
+ }
}
+
if( !keyQt ) {
qCDebug(KGLOBALACCELD) << "Tried to grab key with null code.";
return false;
@@ -192,30 +205,45 @@ bool KGlobalAccelImpl::nativeEventFilter(const QByteArray &eventType, void *mess
}
xcb_generic_event_t *event = reinterpret_cast<xcb_generic_event_t*>(message);
const uint8_t responseType = event->response_type & ~0x80;
- switch (responseType) {
- case XCB_MAPPING_NOTIFY:
- qCDebug(KGLOBALACCELD) << "Got XMappingNotify event";
- xcb_refresh_keyboard_mapping(m_keySymbols, reinterpret_cast<xcb_mapping_notify_event_t*>(event));
- x11MappingNotify();
- return true;
-
- case XCB_KEY_PRESS:
+ if (responseType == XCB_MAPPING_NOTIFY) {
+ x11MappingNotify();
+
+ // Make sure to let Qt handle it as well
+ return false;
+ } else if (responseType == XCB_KEY_PRESS) {
#ifdef KDEDGLOBALACCEL_TRACE
- qCDebug(KGLOBALACCELD) << "Got XKeyPress event";
+ qCDebug(KGLOBALACCELD) << "Got XKeyPress event";
#endif
- return x11KeyPress(reinterpret_cast<xcb_key_press_event_t*>(event));
+ return x11KeyPress(reinterpret_cast<xcb_key_press_event_t*>(event));
+ } else if (m_xkb_first_event && responseType == m_xkb_first_event) {
+ const uint8_t xkbEvent = event->pad0;
+ switch (xkbEvent) {
+ case XCB_XKB_MAP_NOTIFY:
+ x11MappingNotify();
+ break;
+ case XCB_XKB_NEW_KEYBOARD_NOTIFY: {
+ const xcb_xkb_new_keyboard_notify_event_t *ev =
+ reinterpret_cast<xcb_xkb_new_keyboard_notify_event_t*>(event);
+ if (ev->changed & XCB_XKB_NKN_DETAIL_KEYCODES)
+ x11MappingNotify();
+ break;
+ }
+ default:
+ break;
+ }
- default:
- // We get all XEvents. Just ignore them.
- return false;
+ // Make sure to let Qt handle it as well
+ return false;
+ } else {
+ // We get all XEvents. Just ignore them.
+ return false;
}
-
- Q_ASSERT(false);
- return false;
}
void KGlobalAccelImpl::x11MappingNotify()
{
+ qCDebug(KGLOBALACCELD) << "Got XMappingNotify event";
+
// Maybe the X modifier map has been changed.
// uint oldKeyModMaskXAccel = g_keyModMaskXAccel;
// uint oldKeyModMaskXOnOrOff = g_keyModMaskXOnOrOff;
@@ -226,6 +254,12 @@ void KGlobalAccelImpl::x11MappingNotify()
// different keycodes.
ungrabKeys();
+ if (m_keySymbols) {
+ // Force reloading of the keySym mapping
+ xcb_key_symbols_free(m_keySymbols);
+ m_keySymbols = nullptr;
+ }
+
KKeyServer::initializeMods();
calculateGrabMasks();
diff --git a/src/runtime/plugins/xcb/kglobalaccel_x11.h b/src/runtime/plugins/xcb/kglobalaccel_x11.h
index 4011719..1ed75d1 100644
--- a/src/runtime/plugins/xcb/kglobalaccel_x11.h
+++ b/src/runtime/plugins/xcb/kglobalaccel_x11.h
@@ -77,6 +77,7 @@ private:
bool x11KeyPress(xcb_key_press_event_t *event);
xcb_key_symbols_t *m_keySymbols;
+ uint8_t m_xkb_first_event;
};
#endif // _KGLOBALACCEL_X11_H
--
2.19.0