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
This commit is contained in:
parent
26ad65b1e9
commit
3bc6089394
3 changed files with 24 additions and 25 deletions
|
@ -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++);
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,8 +140,12 @@ private:
|
|||
InputRedirection *m_input;
|
||||
bool m_inited = false;
|
||||
QScopedPointer<Xkb> m_xkb;
|
||||
QHash<quint32, QTimer*> m_repeatTimers;
|
||||
QMetaObject::Connection m_activeClientSurfaceChangedConnection;
|
||||
struct {
|
||||
quint32 key = 0;
|
||||
quint32 time = 0;
|
||||
QTimer *timer = nullptr;
|
||||
} m_keyRepeat;
|
||||
};
|
||||
|
||||
inline
|
||||
|
|
Loading…
Reference in a new issue