fakeinput: Keep track of pressed buttons, keys and touches

To prevent having them eternally pressed when the device is
destroyed.
This commit is contained in:
David Redondo 2024-08-12 11:47:56 +02:00
parent 82a49d8abc
commit 436211ad45
2 changed files with 42 additions and 7 deletions

View file

@ -68,11 +68,22 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_destroy(Resource *resource
void FakeInputBackendPrivate::org_kde_kwin_fake_input_destroy_resource(Resource *resource) void FakeInputBackendPrivate::org_kde_kwin_fake_input_destroy_resource(Resource *resource)
{ {
auto it = devices.find(resource); auto it = devices.find(resource);
if (it != devices.end()) { if (it == devices.end()) {
const auto [resource, device] = std::move(*it); return;
devices.erase(it);
Q_EMIT q->deviceRemoved(device.get());
} }
const auto [r, device] = std::move(*it);
for (const auto button : device->pressedButtons) {
Q_EMIT device->pointerButtonChanged(button, InputRedirection::PointerButtonReleased, currentTime(), device.get());
}
for (const auto key : device->pressedKeys) {
Q_EMIT device->keyChanged(key, InputRedirection::KeyboardKeyReleased, currentTime(), device.get());
}
if (!device->activeTouches.empty()) {
Q_EMIT device->touchCanceled(device.get());
}
devices.erase(it);
Q_EMIT q->deviceRemoved(device.get());
} }
FakeInputDevice *FakeInputBackendPrivate::findDevice(Resource *resource) FakeInputDevice *FakeInputBackendPrivate::findDevice(Resource *resource)
@ -117,9 +128,16 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_button(Resource *resource,
switch (state) { switch (state) {
case WL_POINTER_BUTTON_STATE_PRESSED: case WL_POINTER_BUTTON_STATE_PRESSED:
nativeState = InputRedirection::PointerButtonPressed; nativeState = InputRedirection::PointerButtonPressed;
if (device->pressedButtons.contains(button)) {
return;
}
device->pressedButtons.insert(button);
break; break;
case WL_POINTER_BUTTON_STATE_RELEASED: case WL_POINTER_BUTTON_STATE_RELEASED:
nativeState = InputRedirection::PointerButtonReleased; nativeState = InputRedirection::PointerButtonReleased;
if (!device->pressedButtons.remove(button)) {
return;
}
break; break;
default: default:
return; return;
@ -164,6 +182,7 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_down(Resource *resou
return; return;
} }
touchIds << id; touchIds << id;
device->activeTouches.push_back(id);
Q_EMIT device->touchDown(id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), currentTime(), device); Q_EMIT device->touchDown(id, QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y)), currentTime(), device);
} }
@ -189,7 +208,9 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_up(Resource *resourc
return; return;
} }
touchIds.removeOne(id); touchIds.removeOne(id);
Q_EMIT device->touchUp(id, currentTime(), device); if (device->activeTouches.removeAll(id)) {
Q_EMIT device->touchUp(id, currentTime(), device);
}
} }
void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_cancel(Resource *resource) void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_cancel(Resource *resource)
@ -199,6 +220,7 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_touch_cancel(Resource *res
return; return;
} }
touchIds.clear(); touchIds.clear();
device->activeTouches.clear();
Q_EMIT device->touchCanceled(device); Q_EMIT device->touchCanceled(device);
} }
@ -222,7 +244,7 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_pointer_motion_absolute(Re
Q_EMIT device->pointerFrame(device); Q_EMIT device->pointerFrame(device);
} }
void FakeInputBackendPrivate::org_kde_kwin_fake_input_keyboard_key(Resource *resource, uint32_t button, uint32_t state) void FakeInputBackendPrivate::org_kde_kwin_fake_input_keyboard_key(Resource *resource, uint32_t key, uint32_t state)
{ {
FakeInputDevice *device = findDevice(resource); FakeInputDevice *device = findDevice(resource);
if (!device->isAuthenticated()) { if (!device->isAuthenticated()) {
@ -233,9 +255,16 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_keyboard_key(Resource *res
switch (state) { switch (state) {
case WL_KEYBOARD_KEY_STATE_PRESSED: case WL_KEYBOARD_KEY_STATE_PRESSED:
nativeState = InputRedirection::KeyboardKeyPressed; nativeState = InputRedirection::KeyboardKeyPressed;
if (device->pressedKeys.contains(key)) {
return;
}
device->pressedKeys.insert(key);
break; break;
case WL_KEYBOARD_KEY_STATE_RELEASED: case WL_KEYBOARD_KEY_STATE_RELEASED:
if (!device->pressedKeys.remove(key)) {
return;
}
nativeState = InputRedirection::KeyboardKeyReleased; nativeState = InputRedirection::KeyboardKeyReleased;
break; break;
@ -243,7 +272,7 @@ void FakeInputBackendPrivate::org_kde_kwin_fake_input_keyboard_key(Resource *res
return; return;
} }
Q_EMIT device->keyChanged(button, nativeState, currentTime(), device); Q_EMIT device->keyChanged(key, nativeState, currentTime(), device);
} }
FakeInputBackend::FakeInputBackend(Display *display) FakeInputBackend::FakeInputBackend(Display *display)

View file

@ -8,6 +8,8 @@
#include "core/inputdevice.h" #include "core/inputdevice.h"
#include <QSet>
namespace KWin namespace KWin
{ {
@ -39,6 +41,10 @@ public:
void setAuthenticated(bool authenticated); void setAuthenticated(bool authenticated);
bool isAuthenticated() const; bool isAuthenticated() const;
QSet<quint32> pressedButtons;
QSet<quint32> pressedKeys;
QList<quint32> activeTouches;
private: private:
QString m_name; QString m_name;
bool m_authenticated = false; bool m_authenticated = false;