diff --git a/autotests/client/test_fake_input.cpp b/autotests/client/test_fake_input.cpp --- a/autotests/client/test_fake_input.cpp +++ b/autotests/client/test_fake_input.cpp @@ -44,6 +44,7 @@ void testAuthenticate(); void testMotion(); + void testMotionAbsolute(); void testPointerButtonQt_data(); void testPointerButtonQt(); void testPointerButtonLinux_data(); @@ -179,6 +180,31 @@ QCOMPARE(motionSpy.last().first().toSizeF(), QSizeF(0, 0)); } +void FakeInputTest::testMotionAbsolute() +{ + // this test verifies that motion is properly passed to the server + QVERIFY(!m_device->isAuthenticated()); + QSignalSpy motionSpy(m_device, &FakeInputDevice::pointerMotionAbsoluteRequested); + QVERIFY(motionSpy.isValid()); + + // without an authentication we shouldn't get the signals + m_fakeInput->requestPointerMoveAbsolute(QPointF(1, 2)); + QVERIFY(!motionSpy.wait(100)); + + // now let's authenticate the interface + m_device->setAuthentication(true); + m_fakeInput->requestPointerMoveAbsolute(QPointF(1, 2)); + QVERIFY(motionSpy.wait()); + QCOMPARE(motionSpy.count(), 1); + QCOMPARE(motionSpy.last().first().toPointF(), QPointF(1, 2)); + + // just for the fun: once more + m_fakeInput->requestPointerMoveAbsolute(QPointF(0, 0)); + QVERIFY(motionSpy.wait()); + QCOMPARE(motionSpy.count(), 2); + QCOMPARE(motionSpy.last().first().toPointF(), QPointF(0, 0)); +} + void FakeInputTest::testPointerButtonQt_data() { QTest::addColumn("qtButton"); diff --git a/src/client/fakeinput.h b/src/client/fakeinput.h --- a/src/client/fakeinput.h +++ b/src/client/fakeinput.h @@ -133,6 +133,12 @@ * Request a relative pointer motion of @p delta pixels. **/ void requestPointerMove(const QSizeF &delta); + /** + * Request an absolute pointer motion to @p pos position. + * + * @since 5.54 + **/ + void requestPointerMoveAbsolute(const QPointF &pos); /** * Convenience overload. * @see requestPointerButtonPress(quint32) diff --git a/src/client/fakeinput.cpp b/src/client/fakeinput.cpp --- a/src/client/fakeinput.cpp +++ b/src/client/fakeinput.cpp @@ -100,6 +100,16 @@ org_kde_kwin_fake_input_pointer_motion(d->manager, wl_fixed_from_double(delta.width()), wl_fixed_from_double(delta.height())); } +void FakeInput::requestPointerMoveAbsolute(const QPointF &pos) +{ + Q_ASSERT(d->manager.isValid()); + if (wl_proxy_get_version(d->manager) < ORG_KDE_KWIN_FAKE_INPUT_POINTER_MOTION_ABSOLUTE_SINCE_VERSION) { + return; + } + + org_kde_kwin_fake_input_pointer_motion_absolute(d->manager, wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); +} + void FakeInput::Private::sendPointerButtonState(Qt::MouseButton button, quint32 state) { #if HAVE_LINUX_INPUT_H diff --git a/src/client/protocols/fake-input.xml b/src/client/protocols/fake-input.xml --- a/src/client/protocols/fake-input.xml +++ b/src/client/protocols/fake-input.xml @@ -16,7 +16,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . ]]> - + This interface allows other processes to provide fake input events. Purpose is on the one hand side to provide testing facilities like XTest on X11. @@ -83,5 +83,9 @@ A client should use this request to send touch frame event. + + + + diff --git a/src/client/registry.cpp b/src/client/registry.cpp --- a/src/client/registry.cpp +++ b/src/client/registry.cpp @@ -204,7 +204,7 @@ &Registry::remoteAccessManagerRemoved }}, {Registry::Interface::FakeInput, { - 2, + 3, QByteArrayLiteral("org_kde_kwin_fake_input"), &org_kde_kwin_fake_input_interface, &Registry::fakeInputAnnounced, diff --git a/src/server/fakeinput_interface.h b/src/server/fakeinput_interface.h --- a/src/server/fakeinput_interface.h +++ b/src/server/fakeinput_interface.h @@ -113,6 +113,12 @@ * Request a pointer motion by @p delta. **/ void pointerMotionRequested(const QSizeF &delta); + /** + * Request an absolute pointer motion to @p pos. + * + * @since 5.54 + **/ + void pointerMotionAbsoluteRequested(const QPointF &pos); /** * Requests a pointer button pressed for @p button. **/ diff --git a/src/server/fakeinput_interface.cpp b/src/server/fakeinput_interface.cpp --- a/src/server/fakeinput_interface.cpp +++ b/src/server/fakeinput_interface.cpp @@ -42,6 +42,7 @@ void bind(wl_client *client, uint32_t version, uint32_t id) override; static void authenticateCallback(wl_client *client, wl_resource *resource, const char *application, const char *reason); static void pointerMotionCallback(wl_client *client, wl_resource *resource, wl_fixed_t delta_x, wl_fixed_t delta_y); + static void pointerMotionAbsoluteCallback(wl_client *client, wl_resource *resource, wl_fixed_t x, wl_fixed_t y); static void buttonCallback(wl_client *client, wl_resource *resource, uint32_t button, uint32_t state); static void axisCallback(wl_client *client, wl_resource *resource, uint32_t axis, wl_fixed_t value); static void touchDownCallback(wl_client *client, wl_resource *resource, quint32 id, wl_fixed_t x, wl_fixed_t y); @@ -74,7 +75,7 @@ FakeInputDevice *q; }; -const quint32 FakeInputInterface::Private::s_version = 2; +const quint32 FakeInputInterface::Private::s_version = 3; QList FakeInputInterface::Private::touchIds = QList(); #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -87,7 +88,8 @@ touchMotionCallback, touchUpCallback, touchCancelCallback, - touchFrameCallback + touchFrameCallback, + pointerMotionAbsoluteCallback }; #endif @@ -149,6 +151,16 @@ emit d->pointerMotionRequested(QSizeF(wl_fixed_to_double(delta_x), wl_fixed_to_double(delta_y))); } +void FakeInputInterface::Private::pointerMotionAbsoluteCallback(wl_client *client, wl_resource *resource, wl_fixed_t x, wl_fixed_t y) +{ + Q_UNUSED(client) + FakeInputDevice *d = device(resource); + if (!d || !d->isAuthenticated()) { + return; + } + emit d->pointerMotionAbsoluteRequested(QPointF(wl_fixed_to_double(x), wl_fixed_to_double(y))); +} + void FakeInputInterface::Private::axisCallback(wl_client *client, wl_resource *resource, uint32_t axis, wl_fixed_t value) { Q_UNUSED(client)