Commit 9e8f1235 authored by Martin Flöser's avatar Martin Flöser
Browse files

[server] Don't send key release for not pressed keys and no double key press

Summary:
This change makes use of the internal key state in better way. If a
key is not considered pressed, no key release is sent. This can happen
for example if the compositor grabs a key press (global shortcut) but not
the release. The Wayland client cannot do anything with the release as it
never got the press. Thus it doesn't make sense to send the release.

Similar if a key is already pressed, it doesn't make sense to send
another press event. This ensures that if the server sends in repeating
key presses they are filtered out. Key repeat is handled on client side.
Also if several physical keys send the same key code, pressing them at
the same time won't send double press/release event.

This change might cause regressions in KWin in case KWin does not handle
the situation correctly. But that would be a bug in KWin which needs to
be fixed there. If it causes regressions the bug might have shown in
other situations as well.

BUG: 366625
FIXED-IN: 5.27

Reviewers: #plasma_on_wayland, #kwin

Subscribers: plasma-devel, kwin

Tags: #plasma_on_wayland, #kwin

Differential Revision: https://phabricator.kde.org/D2786
parent 2f1beca4
......@@ -1201,6 +1201,21 @@ void TestWaylandSeat::testKeyboard()
QCOMPARE(keyChangedSpy.at(4).at(1).value<Keyboard::KeyState>(), Keyboard::KeyState::Released);
QCOMPARE(keyChangedSpy.at(4).at(2).value<quint32>(), quint32(8));
// releasing a key which is already released should not set a key changed
m_seatInterface->keyReleased(KEY_F1);
QVERIFY(!keyChangedSpy.wait(200));
// let's press it again
m_seatInterface->keyPressed(KEY_F1);
QVERIFY(keyChangedSpy.wait());
QCOMPARE(keyChangedSpy.count(), 6);
// press again should be ignored
m_seatInterface->keyPressed(KEY_F1);
QVERIFY(!keyChangedSpy.wait(200));
// and release
m_seatInterface->keyReleased(KEY_F1);
QVERIFY(keyChangedSpy.wait());
QCOMPARE(keyChangedSpy.count(), 7);
m_seatInterface->updateKeyboardModifiers(1, 2, 3, 4);
QVERIFY(modifierSpy.wait());
QCOMPARE(modifierSpy.count(), 2);
......
......@@ -132,14 +132,18 @@ void SeatInterface::Private::updatePointerButtonState(quint32 button, Pointer::S
it.value() = state;
}
void SeatInterface::Private::updateKey(quint32 key, Keyboard::State state)
bool SeatInterface::Private::updateKey(quint32 key, Keyboard::State state)
{
auto it = keys.states.find(key);
if (it == keys.states.end()) {
keys.states.insert(key, state);
return;
return true;
}
if (it.value() == state) {
return false;
}
it.value() = state;
return true;
}
void SeatInterface::Private::sendName(wl_resource *r)
......@@ -825,7 +829,9 @@ void SeatInterface::keyPressed(quint32 key)
{
Q_D();
d->keys.lastStateSerial = d->display->nextSerial();
d->updateKey(key, Private::Keyboard::State::Pressed);
if (!d->updateKey(key, Private::Keyboard::State::Pressed)) {
return;
}
if (d->keys.focus.keyboard && d->keys.focus.surface) {
d->keys.focus.keyboard->keyPressed(key, d->keys.lastStateSerial);
}
......@@ -835,7 +841,9 @@ void SeatInterface::keyReleased(quint32 key)
{
Q_D();
d->keys.lastStateSerial = d->display->nextSerial();
d->updateKey(key, Private::Keyboard::State::Released);
if (!d->updateKey(key, Private::Keyboard::State::Released)) {
return;
}
if (d->keys.focus.keyboard && d->keys.focus.surface) {
d->keys.focus.keyboard->keyReleased(key, d->keys.lastStateSerial);
}
......
......@@ -124,7 +124,7 @@ public:
} keyRepeat;
};
Keyboard keys;
void updateKey(quint32 key, Keyboard::State state);
bool updateKey(quint32 key, Keyboard::State state);
struct TextInput {
struct Focus {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment