summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2022-04-04 12:14:04 +0200
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2022-05-03 04:46:57 +0000
commit4910b7adfa706520cd5180d5384b999488550aef (patch)
treecc58dab46374362acf6f8b447144f9d294867293
parent6d8e7567d7d1737c240cfca4402bf6ec5a67b02e (diff)
downloadqtwayland-4910b7adfa706520cd5180d5384b999488550aef.tar.gz
Clear keyboard modifier state when application deactivates
When the application deactivates while a modifier is held down, the modifier would get stuck and be set for all subsequent shortcut events. This could easily happen when nesting a Wayland compositor inside another compositor and using ALT+TAB to switch to another application. The alt modifier would then get stuck, since it never received any release event. When the application is inactive and then comes back, we can't know which keys are pressed, so it's better to just assume they are all cleared at this point. [ChangeLog][QtWaylandCompositor] Fixed a bug where keyboard modifiers would get stuck if the compositor was running nested inside e.g. X11 and then ALT-TAB was used to switch to a different application. This would cause shortcuts to misbehave. Fixes: QTBUG-101862 Change-Id: I9645418719d8ef8fc2ce2203ca5b6a159f3d9a7c Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp16
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.h3
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard.cpp40
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard_p.h2
4 files changed, 53 insertions, 8 deletions
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 98a0bb7f..7b06a1c0 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -229,6 +229,11 @@ void QWaylandCompositorPrivate::init()
QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents()));
+ QObject::connect(static_cast<QGuiApplication *>(QGuiApplication::instance()),
+ &QGuiApplication::applicationStateChanged,
+ q,
+ &QWaylandCompositor::applicationStateChanged);
+
initializeHardwareIntegration();
initializeSeats();
@@ -1101,6 +1106,17 @@ QVector<QWaylandCompositor::ShmFormat> QWaylandCompositor::additionalShmFormats(
return d->shmFormats;
}
+void QWaylandCompositor::applicationStateChanged(Qt::ApplicationState state)
+{
+ if (state == Qt::ApplicationInactive) {
+ auto *seat = defaultSeat();
+ if (seat != nullptr) {
+ QWaylandKeyboardPrivate *keyb = QWaylandKeyboardPrivate::get(seat->keyboard());
+ keyb->resetKeyboardState();
+ }
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qwaylandcompositor.cpp"
diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h
index 3be304df..54b45b4c 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.h
+++ b/src/compositor/compositor_api/qwaylandcompositor.h
@@ -148,6 +148,9 @@ public:
public Q_SLOTS:
void processWaylandEvents();
+private Q_SLOTS:
+ void applicationStateChanged(Qt::ApplicationState state);
+
Q_SIGNALS:
void createdChanged();
void socketNameChanged(const QByteArray &socketName);
diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp
index 97cc3138..4baeaddb 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard.cpp
+++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp
@@ -202,6 +202,18 @@ void QWaylandKeyboardPrivate::maybeUpdateXkbScanCodeTable()
}
#endif
+void QWaylandKeyboardPrivate::resetKeyboardState()
+{
+ if (!xkbContext())
+ return;
+
+ while (!keys.isEmpty()) {
+ uint32_t code = fromWaylandKey(keys.first());
+ keyEvent(code, WL_KEYBOARD_KEY_STATE_RELEASED);
+ updateModifierState(code, WL_KEYBOARD_KEY_STATE_RELEASED);
+ }
+}
+
void QWaylandKeyboardPrivate::updateModifierState(uint code, uint32_t state)
{
#if QT_CONFIG(xkbcommon)
@@ -277,17 +289,29 @@ void QWaylandKeyboardPrivate::maybeUpdateKeymap()
#endif
}
+// In all current XKB keymaps there's a constant offset of 8 (for historical
+// reasons) from hardware/evdev scancodes to XKB keycodes. On X11, we pass
+// XKB keycodes (as sent by X server) via QKeyEvent::nativeScanCode. eglfs+evdev
+// adds 8 for consistency, see qtbase/05c07c7636012ebb4131ca099ca4ea093af76410.
+// eglfs+libinput also adds 8, for the same reason. Wayland protocol uses
+// hardware/evdev scancodes, thus we need to subtract 8 before sending the event
+// out and add it when mapping back.
+#define QTWAYLANDKEYBOARD_XKB_HISTORICAL_OFFSET 8
+
+uint QWaylandKeyboardPrivate::fromWaylandKey(const uint key)
+{
+#if QT_CONFIG(xkbcommon)
+ const uint offset = QTWAYLANDKEYBOARD_XKB_HISTORICAL_OFFSET;
+ return key + offset;
+#else
+ return key;
+#endif
+}
+
uint QWaylandKeyboardPrivate::toWaylandKey(const uint nativeScanCode)
{
#if QT_CONFIG(xkbcommon)
- // In all current XKB keymaps there's a constant offset of 8 (for historical
- // reasons) from hardware/evdev scancodes to XKB keycodes. On X11, we pass
- // XKB keycodes (as sent by X server) via QKeyEvent::nativeScanCode. eglfs+evdev
- // adds 8 for consistency, see qtbase/05c07c7636012ebb4131ca099ca4ea093af76410.
- // eglfs+libinput also adds 8, for the same reason. Wayland protocol uses
- // hardware/evdev scancodes, thus we need to minus 8 before sending the event
- // out.
- const uint offset = 8;
+ const uint offset = QTWAYLANDKEYBOARD_XKB_HISTORICAL_OFFSET;
Q_ASSERT(nativeScanCode >= offset);
return nativeScanCode - offset;
#else
diff --git a/src/compositor/compositor_api/qwaylandkeyboard_p.h b/src/compositor/compositor_api/qwaylandkeyboard_p.h
index 942e4191..f9abb645 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard_p.h
+++ b/src/compositor/compositor_api/qwaylandkeyboard_p.h
@@ -83,6 +83,7 @@ public:
}
uint32_t xkbModsMask() const { return modsDepressed | modsLatched | modsLocked; }
void maybeUpdateXkbScanCodeTable();
+ void resetKeyboardState();
#endif
void keyEvent(uint code, uint32_t state);
@@ -105,6 +106,7 @@ private:
void createXKBState(xkb_keymap *keymap);
#endif
static uint toWaylandKey(const uint nativeScanCode);
+ static uint fromWaylandKey(const uint key);
void sendRepeatInfo();