diff --git a/src/wayland/autotests/client/test_fake_input.cpp b/src/wayland/autotests/client/test_fake_input.cpp index ca35ce889e..e752957bf1 100644 --- a/src/wayland/autotests/client/test_fake_input.cpp +++ b/src/wayland/autotests/client/test_fake_input.cpp @@ -52,6 +52,8 @@ private Q_SLOTS: void testAxis_data(); void testAxis(); void testTouch(); + void testKeyboardKeyLinux_data(); + void testKeyboardKeyLinux(); private: Display *m_display = nullptr; @@ -423,6 +425,57 @@ void FakeInputTest::testTouch() QCOMPARE(touchCancelSpy.count(), 1); } +void FakeInputTest::testKeyboardKeyLinux_data() +{ + QTest::addColumn("linuxKey"); + + QTest::newRow("A") << quint32(KEY_A); + QTest::newRow("S") << quint32(KEY_S); + QTest::newRow("D") << quint32(KEY_D); + QTest::newRow("F") << quint32(KEY_F); +} + +void FakeInputTest::testKeyboardKeyLinux() +{ + // this test verifies that keyboard key events are properly passed to the server with Qt button codes + QVERIFY(!m_device->isAuthenticated()); + QSignalSpy pressedSpy(m_device, &FakeInputDevice::keyboardKeyPressRequested); + QVERIFY(pressedSpy.isValid()); + QSignalSpy releasedSpy(m_device, &FakeInputDevice::keyboardKeyReleaseRequested); + QVERIFY(releasedSpy.isValid()); + + // without an authentication we shouldn't get the signals + QFETCH(quint32, linuxKey); + m_fakeInput->requestKeyboardKeyPress(linuxKey); + m_fakeInput->requestKeyboardKeyRelease(linuxKey); + QVERIFY(!pressedSpy.wait(100)); + QVERIFY(pressedSpy.isEmpty()); + QVERIFY(releasedSpy.isEmpty()); + + // now authenticate + m_device->setAuthentication(true); + // now our click should work + m_fakeInput->requestKeyboardKeyPress(linuxKey); + m_fakeInput->requestKeyboardKeyRelease(linuxKey); + QVERIFY(releasedSpy.wait()); + QCOMPARE(pressedSpy.count(), 1); + QCOMPARE(releasedSpy.count(), 1); + QTEST(pressedSpy.last().first().value(), "linuxKey"); + QTEST(releasedSpy.last().first().value(), "linuxKey"); + + // and a press/release "manually" + m_fakeInput->requestKeyboardKeyPress(linuxKey); + QVERIFY(pressedSpy.wait()); + QCOMPARE(pressedSpy.count(), 2); + QCOMPARE(releasedSpy.count(), 1); + QTEST(pressedSpy.last().first().value(), "linuxKey"); + // and release + m_fakeInput->requestKeyboardKeyRelease(linuxKey); + QVERIFY(releasedSpy.wait()); + QCOMPARE(pressedSpy.count(), 2); + QCOMPARE(releasedSpy.count(), 2); + QTEST(releasedSpy.last().first().value(), "linuxKey"); +} QTEST_GUILESS_MAIN(FakeInputTest) #include "test_fake_input.moc" diff --git a/src/wayland/fakeinput_interface.cpp b/src/wayland/fakeinput_interface.cpp index 0486435be2..b1380a580f 100644 --- a/src/wayland/fakeinput_interface.cpp +++ b/src/wayland/fakeinput_interface.cpp @@ -50,6 +50,7 @@ private: static void touchUpCallback(wl_client *client, wl_resource *resource, quint32 id); static void touchCancelCallback(wl_client *client, wl_resource *resource); static void touchFrameCallback(wl_client *client, wl_resource *resource); + static void keyboardKeyCallback(wl_client *client, wl_resource *resource, uint32_t button, uint32_t state); static void unbind(wl_resource *resource); static Private *cast(wl_resource *r) { @@ -75,7 +76,7 @@ private: FakeInputDevice *q; }; -const quint32 FakeInputInterface::Private::s_version = 3; +const quint32 FakeInputInterface::Private::s_version = 4; QList FakeInputInterface::Private::touchIds = QList(); #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -89,7 +90,8 @@ const struct org_kde_kwin_fake_input_interface FakeInputInterface::Private::s_in touchUpCallback, touchCancelCallback, touchFrameCallback, - pointerMotionAbsoluteCallback + pointerMotionAbsoluteCallback, + keyboardKeyCallback }; #endif @@ -265,6 +267,26 @@ void FakeInputInterface::Private::touchFrameCallback(wl_client *client, wl_resou emit d->touchFrameRequested(); } +void FakeInputInterface::Private::keyboardKeyCallback(wl_client *client, wl_resource *resource, uint32_t button, uint32_t state) +{ + Q_UNUSED(client) + FakeInputDevice *d = device(resource); + if (!d || !d->isAuthenticated()) { + return; + } + switch (state) { + case WL_KEYBOARD_KEY_STATE_PRESSED: + emit d->keyboardKeyPressRequested(button); + break; + case WL_KEYBOARD_KEY_STATE_RELEASED: + emit d->keyboardKeyReleaseRequested(button); + break; + default: + // nothing + break; + } +} + FakeInputInterface::FakeInputInterface(Display *display, QObject *parent) : Global(new Private(this, display), parent) { diff --git a/src/wayland/fakeinput_interface.h b/src/wayland/fakeinput_interface.h index 99d9784111..9921fc4938 100644 --- a/src/wayland/fakeinput_interface.h +++ b/src/wayland/fakeinput_interface.h @@ -161,6 +161,18 @@ Q_SIGNALS: * @since 5.23 **/ void touchFrameRequested(); + /** + * Requests a keyboard key pressed for @p key. + * + * @since 5.63 + **/ + void keyboardKeyPressRequested(quint32 key); + /** + * Requests a keyboard key release for @p key. + * + * @since 5.63 + **/ + void keyboardKeyReleaseRequested(quint32 key); private: friend class FakeInputInterface;