From 3bc608939444f88dd855130982ce176d393d3ab5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 5 Oct 2016 08:26:29 +0200 Subject: [PATCH] Only repeat one key Summary: So far KWin tried to repeat all pressed keys which should repeat. But this is not how X11 and e.g. QtWayland handle it. There only one key - the last one which got pressed - repeats. And this makes sense as the key is used to generate a keysym and that one KWin caches. Thus the logic so far resulted in incorrect keysyms to be generated during the repeat. E.g. pressing a, pressing b, releasing b would repeat b instead of the hold a as b was the last generated keysym. This change addresses this problem and let's only one key repeat at a time. When the currently repeating key gets released the repeat timer is stopped and other hold keys won't repeat any more. This also matches the behavior of X11 and QtWayland. BUG: 369091 FIXED-IN: 5.8.1 Reviewers: #kwin, #plasma_on_wayland Subscribers: plasma-devel, kwin Tags: #plasma_on_wayland, #kwin Differential Revision: https://phabricator.kde.org/D2941 --- .../integration/globalshortcuts_test.cpp | 1 - keyboard_input.cpp | 42 +++++++++---------- keyboard_input.h | 6 ++- 3 files changed, 24 insertions(+), 25 deletions(-) diff --git a/autotests/integration/globalshortcuts_test.cpp b/autotests/integration/globalshortcuts_test.cpp index 2b8bc4c6c7..3eca6f1225 100644 --- a/autotests/integration/globalshortcuts_test.cpp +++ b/autotests/integration/globalshortcuts_test.cpp @@ -133,7 +133,6 @@ void GlobalShortcutsTest::testRepeatedTrigger() QVERIFY(triggeredSpy.wait()); // now release the key kwinApp()->platform()->keyboardKeyReleased(KEY_5, timestamp++); - QEXPECT_FAIL("", "BUG 369091", Continue); QVERIFY(!triggeredSpy.wait(500)); kwinApp()->platform()->keyboardKeyReleased(KEY_WAKEUP, timestamp++); diff --git a/keyboard_input.cpp b/keyboard_input.cpp index a2138a3f74..08ababb24f 100644 --- a/keyboard_input.cpp +++ b/keyboard_input.cpp @@ -463,17 +463,25 @@ KeyboardInputRedirection::KeyboardInputRedirection(InputRedirection *parent) { } -KeyboardInputRedirection::~KeyboardInputRedirection() -{ - qDeleteAll(m_repeatTimers); - m_repeatTimers.clear(); -} +KeyboardInputRedirection::~KeyboardInputRedirection() = default; void KeyboardInputRedirection::init() { Q_ASSERT(!m_inited); m_inited = true; + // setup key repeat + m_keyRepeat.timer = new QTimer(this); + connect(m_keyRepeat.timer, &QTimer::timeout, this, + [this] { + if (waylandServer()->seat()->keyRepeatRate() != 0) { + m_keyRepeat.timer->setInterval(1000 / waylandServer()->seat()->keyRepeatRate()); + } + // TODO: better time + processKey(m_keyRepeat.key, InputRedirection::KeyboardKeyAutoRepeat, m_keyRepeat.time); + } + ); + connect(workspace(), &QObject::destroyed, this, [this] { m_inited = false; }); connect(waylandServer(), &QObject::destroyed, this, [this] { m_inited = false; }); connect(workspace(), &Workspace::clientActivated, this, @@ -615,26 +623,14 @@ void KeyboardInputRedirection::processKey(uint32_t key, InputRedirection::Keyboa device); if (state == InputRedirection::KeyboardKeyPressed) { if (m_xkb->shouldKeyRepeat(key) && waylandServer()->seat()->keyRepeatDelay() != 0) { - QTimer *timer = new QTimer; - timer->setInterval(waylandServer()->seat()->keyRepeatDelay()); - connect(timer, &QTimer::timeout, this, - [this, timer, time, key] { - const int delay = 1000 / waylandServer()->seat()->keyRepeatRate(); - if (timer->interval() != delay) { - timer->setInterval(delay); - } - // TODO: better time - processKey(key, InputRedirection::KeyboardKeyAutoRepeat, time); - } - ); - m_repeatTimers.insert(key, timer); - timer->start(); + m_keyRepeat.timer->setInterval(waylandServer()->seat()->keyRepeatDelay()); + m_keyRepeat.key = key; + m_keyRepeat.time = time; + m_keyRepeat.timer->start(); } } else if (state == InputRedirection::KeyboardKeyReleased) { - auto it = m_repeatTimers.find(key); - if (it != m_repeatTimers.end()) { - delete it.value(); - m_repeatTimers.erase(it); + if (key == m_keyRepeat.key) { + m_keyRepeat.timer->stop(); } } diff --git a/keyboard_input.h b/keyboard_input.h index 3e9808d937..dd43326556 100644 --- a/keyboard_input.h +++ b/keyboard_input.h @@ -140,8 +140,12 @@ private: InputRedirection *m_input; bool m_inited = false; QScopedPointer m_xkb; - QHash m_repeatTimers; QMetaObject::Connection m_activeClientSurfaceChangedConnection; + struct { + quint32 key = 0; + quint32 time = 0; + QTimer *timer = nullptr; + } m_keyRepeat; }; inline