From c29035a6f0415967545f426cd7ba9734d1a6ac58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Fl=C3=B6ser?= Date: Thu, 1 Feb 2018 17:46:53 +0100 Subject: [PATCH] [server] Add support for the frame semantics of Pointer version 5 Summary: This change implements the required changes for wl_seat version 5. There seem to be applications which require version 5 and refuse to start if the server doesn't provide it. Thus we need to provide it. The main difference with version 5 is that pointer need to send a frame event after each logical group of events. As we don't support the new events from version 5 yet, we just emit the frame after each event and implement the suggested semantics for the enter/leave behavior. To really make use of this, we will have to implement additions in the API and then in KWin to expose the new API elements. But to just support the semantics we don't need it. BUG: 389189 FIXED-IN: 5.45 Test Plan: Extended autotest Reviewers: #kwin, #plasma, #frameworks Subscribers: plasma-devel Tags: #frameworks, #plasma Differential Revision: https://phabricator.kde.org/D10235 --- .../autotests/client/test_wayland_seat.cpp | 17 ++++++++++- src/wayland/pointer_interface.cpp | 14 +++++++++ src/wayland/pointer_interface_p.h | 1 + src/wayland/seat_interface.cpp | 30 +++++++++++++++---- src/wayland/seat_interface_p.h | 1 + 5 files changed, 57 insertions(+), 6 deletions(-) diff --git a/src/wayland/autotests/client/test_wayland_seat.cpp b/src/wayland/autotests/client/test_wayland_seat.cpp index 480259aa18..8164e1b269 100644 --- a/src/wayland/autotests/client/test_wayland_seat.cpp +++ b/src/wayland/autotests/client/test_wayland_seat.cpp @@ -392,6 +392,8 @@ void TestWaylandSeat::testPointer() QVERIFY(!m_seatInterface->focusedPointer()); Pointer *p = m_seat->createPointer(m_seat); + QSignalSpy frameSpy(p, &Pointer::frame); + QVERIFY(frameSpy.isValid()); const Pointer &cp = *p; QVERIFY(p->isValid()); QScopedPointer relativePointer(m_relativePointerManager->createRelativePointer(p)); @@ -404,12 +406,15 @@ void TestWaylandSeat::testPointer() QCOMPARE(pointerCreatedSpy.first().first().value(), m_seatInterface->focusedPointer()); QCOMPARE(focusedPointerChangedSpy.count(), 2); QCOMPARE(focusedPointerChangedSpy.last().first().value(), m_seatInterface->focusedPointer()); + QVERIFY(frameSpy.wait()); + QCOMPARE(frameSpy.count(), 1); m_seatInterface->setFocusedPointerSurface(nullptr); QCOMPARE(focusedPointerChangedSpy.count(), 3); QVERIFY(!focusedPointerChangedSpy.last().first().value()); serverSurface->client()->flush(); - QTest::qWait(100); + QVERIFY(frameSpy.wait()); + QCOMPARE(frameSpy.count(), 2); QSignalSpy enteredSpy(p, SIGNAL(entered(quint32,QPointF))); QVERIFY(enteredSpy.isValid()); @@ -436,6 +441,7 @@ void TestWaylandSeat::testPointer() QVERIFY(enteredSpy.wait()); QCOMPARE(enteredSpy.first().first().value(), m_display->serial()); QCOMPARE(enteredSpy.first().last().toPoint(), QPoint(10, 3)); + QCOMPARE(frameSpy.count(), 3); PointerInterface *serverPointer = m_seatInterface->focusedPointer(); QVERIFY(serverPointer); QCOMPARE(p->enteredSurface(), s); @@ -447,6 +453,7 @@ void TestWaylandSeat::testPointer() m_seatInterface->setTimestamp(1); m_seatInterface->setPointerPos(QPoint(10, 16)); QVERIFY(motionSpy.wait()); + QCOMPARE(frameSpy.count(), 4); QCOMPARE(motionSpy.first().first().toPoint(), QPoint(0, 1)); QCOMPARE(motionSpy.first().last().value(), quint32(1)); @@ -462,9 +469,11 @@ void TestWaylandSeat::testPointer() m_seatInterface->setTimestamp(2); m_seatInterface->pointerAxis(Qt::Horizontal, 10); QVERIFY(axisSpy.wait()); + QCOMPARE(frameSpy.count(), 5); m_seatInterface->setTimestamp(3); m_seatInterface->pointerAxis(Qt::Vertical, 20); QVERIFY(axisSpy.wait()); + QCOMPARE(frameSpy.count(), 6); QCOMPARE(axisSpy.first().at(0).value(), quint32(2)); QCOMPARE(axisSpy.first().at(1).value(), Pointer::Axis::Horizontal); QCOMPARE(axisSpy.first().at(2).value(), qreal(10)); @@ -477,18 +486,22 @@ void TestWaylandSeat::testPointer() m_seatInterface->setTimestamp(4); m_seatInterface->pointerButtonPressed(1); QVERIFY(buttonSpy.wait()); + QCOMPARE(frameSpy.count(), 7); QCOMPARE(buttonSpy.at(0).at(0).value(), m_display->serial()); m_seatInterface->setTimestamp(5); m_seatInterface->pointerButtonPressed(2); QVERIFY(buttonSpy.wait()); + QCOMPARE(frameSpy.count(), 8); QCOMPARE(buttonSpy.at(1).at(0).value(), m_display->serial()); m_seatInterface->setTimestamp(6); m_seatInterface->pointerButtonReleased(2); QVERIFY(buttonSpy.wait()); + QCOMPARE(frameSpy.count(), 9); QCOMPARE(buttonSpy.at(2).at(0).value(), m_display->serial()); m_seatInterface->setTimestamp(7); m_seatInterface->pointerButtonReleased(1); QVERIFY(buttonSpy.wait()); + QCOMPARE(frameSpy.count(), 10); QCOMPARE(buttonSpy.count(), 4); // timestamp @@ -521,6 +534,7 @@ void TestWaylandSeat::testPointer() m_seatInterface->setFocusedPointerSurface(nullptr); QCOMPARE(focusedPointerChangedSpy.count(), 5); QVERIFY(leftSpy.wait()); + QCOMPARE(frameSpy.count(), 11); QCOMPARE(leftSpy.first().first().value(), m_display->serial()); QVERIFY(!p->enteredSurface()); QVERIFY(!cp.enteredSurface()); @@ -533,6 +547,7 @@ void TestWaylandSeat::testPointer() m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(0, 0)); QCOMPARE(focusedPointerChangedSpy.count(), 6); QVERIFY(enteredSpy.wait()); + QCOMPARE(frameSpy.count(), 12); QCOMPARE(p->enteredSurface(), s); QCOMPARE(cp.enteredSurface(), s); diff --git a/src/wayland/pointer_interface.cpp b/src/wayland/pointer_interface.cpp index fc85995352..1a4c33823b 100644 --- a/src/wayland/pointer_interface.cpp +++ b/src/wayland/pointer_interface.cpp @@ -211,6 +211,14 @@ void PointerInterface::Private::cancelPinchGesture(quint32 serial) } } +void PointerInterface::Private::sendFrame() +{ + if (!resource || wl_resource_get_version(resource) < WL_POINTER_FRAME_SINCE_VERSION) { + return; + } + wl_pointer_send_frame(resource); +} + #ifndef DOXYGEN_SHOULD_SKIP_THIS const struct wl_pointer_interface PointerInterface::Private::s_interface = { setCursorCallback, @@ -242,11 +250,13 @@ PointerInterface::PointerInterface(SeatInterface *parent, wl_resource *parentRes d->sendLeave(d->focusedChildSurface.data(), serial); d->focusedChildSurface = QPointer(targetSurface); d->sendEnter(targetSurface, pos, serial); + d->sendFrame(); d->client->flush(); } else { const QPointF adjustedPos = pos - surfacePosition(d->focusedChildSurface); wl_pointer_send_motion(d->resource, d->seat->timestamp(), wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y())); + d->sendFrame(); } } }); @@ -269,6 +279,7 @@ void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 seri [this] { Q_D(); d->sendLeave(d->focusedChildSurface.data(), d->global->display()->nextSerial()); + d->sendFrame(); d->focusedSurface = nullptr; d->focusedChildSurface.clear(); } @@ -291,6 +302,7 @@ void PointerInterface::buttonPressed(quint32 button, quint32 serial) return; } wl_pointer_send_button(d->resource, serial, d->seat->timestamp(), button, WL_POINTER_BUTTON_STATE_PRESSED); + d->sendFrame(); } void PointerInterface::buttonReleased(quint32 button, quint32 serial) @@ -301,6 +313,7 @@ void PointerInterface::buttonReleased(quint32 button, quint32 serial) return; } wl_pointer_send_button(d->resource, serial, d->seat->timestamp(), button, WL_POINTER_BUTTON_STATE_RELEASED); + d->sendFrame(); } void PointerInterface::axis(Qt::Orientation orientation, quint32 delta) @@ -313,6 +326,7 @@ void PointerInterface::axis(Qt::Orientation orientation, quint32 delta) wl_pointer_send_axis(d->resource, d->seat->timestamp(), (orientation == Qt::Vertical) ? WL_POINTER_AXIS_VERTICAL_SCROLL : WL_POINTER_AXIS_HORIZONTAL_SCROLL, wl_fixed_from_int(delta)); + d->sendFrame(); } void PointerInterface::Private::setCursorCallback(wl_client *client, wl_resource *resource, uint32_t serial, diff --git a/src/wayland/pointer_interface_p.h b/src/wayland/pointer_interface_p.h index 2e842aca0c..c964e36071 100644 --- a/src/wayland/pointer_interface_p.h +++ b/src/wayland/pointer_interface_p.h @@ -49,6 +49,7 @@ public: void sendLeave(SurfaceInterface *surface, quint32 serial); void sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial); + void sendFrame(); void registerRelativePointer(RelativePointerInterface *relativePointer); void registerSwipeGesture(PointerSwipeGestureInterface *gesture); diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index 68e9c03150..598ba1cb8c 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -46,10 +46,10 @@ namespace KWayland namespace Server { -const quint32 SeatInterface::Private::s_version = 4; -const qint32 SeatInterface::Private::s_pointerVersion = 3; -const qint32 SeatInterface::Private::s_touchVersion = 3; -const qint32 SeatInterface::Private::s_keyboardVersion = 4; +const quint32 SeatInterface::Private::s_version = 5; +const qint32 SeatInterface::Private::s_pointerVersion = 5; +const qint32 SeatInterface::Private::s_touchVersion = 5; +const qint32 SeatInterface::Private::s_keyboardVersion = 5; SeatInterface::Private::Private(SeatInterface *q, Display *display) : Global::Private(display, &wl_seat_interface, s_version) @@ -61,7 +61,8 @@ SeatInterface::Private::Private(SeatInterface *q, Display *display) const struct wl_seat_interface SeatInterface::Private::s_interface = { getPointerCallback, getKeyboardCallback, - getTouchCallback + getTouchCallback, + releaseCallback }; #endif @@ -114,6 +115,12 @@ void SeatInterface::Private::unbind(wl_resource *r) cast(r)->resources.removeAll(r); } +void SeatInterface::Private::releaseCallback(wl_client *client, wl_resource *resource) +{ + Q_UNUSED(client) + wl_resource_destroy(resource); +} + void SeatInterface::Private::updatePointerButtonSerial(quint32 button, quint32 serial) { auto it = globalPointer.buttonSerials.find(button); @@ -473,6 +480,7 @@ void SeatInterface::Private::getPointer(wl_client *client, wl_resource *resource // this is a pointer for the currently focused pointer surface globalPointer.focus.pointers << pointer; pointer->setFocusedSurface(globalPointer.focus.surface, globalPointer.focus.serial); + pointer->d_func()->sendFrame(); if (globalPointer.focus.pointers.count() == 1) { // got a new pointer emit q->focusedPointerChanged(pointer); @@ -687,8 +695,10 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM return; } const quint32 serial = d->display->nextSerial(); + QSet framePointers; for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) { (*it)->setFocusedSurface(nullptr, serial); + framePointers << *it; } if (d->globalPointer.focus.surface) { disconnect(d->globalPointer.focus.destroyConnection); @@ -711,12 +721,21 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM } if (p.isEmpty()) { emit focusedPointerChanged(nullptr); + for (auto p : qAsConst(framePointers)) + { + p->d_func()->sendFrame(); + } return; } // TODO: signal with all pointers emit focusedPointerChanged(p.first()); for (auto it = p.constBegin(), end = p.constEnd(); it != end; ++it) { (*it)->setFocusedSurface(surface, serial); + framePointers << *it; + } + for (auto p : qAsConst(framePointers)) + { + p->d_func()->sendFrame(); } } @@ -1322,6 +1341,7 @@ qint32 SeatInterface::touchDown(const QPointF &globalPosition) wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED); + p->d_func()->sendFrame(); } ); if (!result) { diff --git a/src/wayland/seat_interface_p.h b/src/wayland/seat_interface_p.h index 0b42e9fa9e..64d2aca4c3 100644 --- a/src/wayland/seat_interface_p.h +++ b/src/wayland/seat_interface_p.h @@ -186,6 +186,7 @@ private: static void getPointerCallback(wl_client *client, wl_resource *resource, uint32_t id); static void getKeyboardCallback(wl_client *client, wl_resource *resource, uint32_t id); static void getTouchCallback(wl_client *client, wl_resource *resource, uint32_t id); + static void releaseCallback(wl_client *client, wl_resource *resource); static const struct wl_seat_interface s_interface; static const quint32 s_version; static const qint32 s_pointerVersion;