diff --git a/src/wayland/autotests/client/test_datadevice.cpp b/src/wayland/autotests/client/test_datadevice.cpp index 30d052bb40..6b8af7d211 100644 --- a/src/wayland/autotests/client/test_datadevice.cpp +++ b/src/wayland/autotests/client/test_datadevice.cpp @@ -254,12 +254,14 @@ void TestDataDevice::testDrag() if (!hasGrab) { // in case we don't have grab, still generate a pointer serial to make it more interesting m_seatInterface->pointerButtonPressed(Qt::LeftButton); + m_seatInterface->pointerFrame(); } if (hasPointerFocus) { m_seatInterface->setFocusedPointerSurface(surfaceInterface); } if (hasGrab) { m_seatInterface->pointerButtonPressed(Qt::LeftButton); + m_seatInterface->pointerFrame(); } // TODO: This test would be better, if it could also test that a client trying to guess @@ -333,12 +335,14 @@ void TestDataDevice::testDragInternally() if (!hasGrab) { // in case we don't have grab, still generate a pointer serial to make it more interesting m_seatInterface->pointerButtonPressed(Qt::LeftButton); + m_seatInterface->pointerFrame(); } if (hasPointerFocus) { m_seatInterface->setFocusedPointerSurface(surfaceInterface); } if (hasGrab) { m_seatInterface->pointerButtonPressed(Qt::LeftButton); + m_seatInterface->pointerFrame(); } // TODO: This test would be better, if it could also test that a client trying to guess diff --git a/src/wayland/autotests/client/test_drag_drop.cpp b/src/wayland/autotests/client/test_drag_drop.cpp index 9ee65176eb..b5fc72f9e5 100644 --- a/src/wayland/autotests/client/test_drag_drop.cpp +++ b/src/wayland/autotests/client/test_drag_drop.cpp @@ -209,6 +209,7 @@ void TestDragAndDrop::testPointerDragAndDrop() m_seatInterface->setFocusedPointerSurface(serverSurface); m_seatInterface->setTimestamp(2); m_seatInterface->pointerButtonPressed(1); + m_seatInterface->pointerFrame(); QVERIFY(buttonPressSpy.wait()); QCOMPARE(buttonPressSpy.first().at(1).value(), quint32(2)); @@ -256,6 +257,7 @@ void TestDragAndDrop::testPointerDragAndDrop() // simulate motion m_seatInterface->setTimestamp(3); m_seatInterface->setPointerPos(QPointF(3, 3)); + m_seatInterface->pointerFrame(); QVERIFY(dragMotionSpy.wait()); QCOMPARE(dragMotionSpy.count(), 1); QCOMPARE(dragMotionSpy.first().first().toPointF(), QPointF(3, 3)); @@ -268,6 +270,7 @@ void TestDragAndDrop::testPointerDragAndDrop() QVERIFY(droppedSpy.isValid()); m_seatInterface->setTimestamp(4); m_seatInterface->pointerButtonReleased(1); + m_seatInterface->pointerFrame(); QVERIFY(sourceDropSpy.isEmpty()); QVERIFY(droppedSpy.wait()); QCOMPARE(sourceDropSpy.count(), 1); @@ -405,6 +408,7 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource() m_seatInterface->setFocusedPointerSurface(serverSurface); m_seatInterface->setTimestamp(2); m_seatInterface->pointerButtonPressed(1); + m_seatInterface->pointerFrame(); QVERIFY(buttonPressSpy.wait()); QCOMPARE(buttonPressSpy.first().at(1).value(), quint32(2)); @@ -452,6 +456,7 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource() // simulate motion m_seatInterface->setTimestamp(3); m_seatInterface->setPointerPos(QPointF(3, 3)); + m_seatInterface->pointerFrame(); QVERIFY(dragMotionSpy.wait()); QCOMPARE(dragMotionSpy.count(), 1); QCOMPARE(dragMotionSpy.first().first().toPointF(), QPointF(3, 3)); @@ -472,6 +477,7 @@ void TestDragAndDrop::testDragAndDropWithCancelByDestroyDataSource() QVERIFY(droppedSpy.isValid()); m_seatInterface->setTimestamp(4); m_seatInterface->pointerButtonReleased(1); + m_seatInterface->pointerFrame(); QVERIFY(!droppedSpy.wait(500)); // verify that we did not get any further input events @@ -511,7 +517,8 @@ void TestDragAndDrop::testPointerEventsIgnored() m_seatInterface->setTimestamp(timestamp++); m_seatInterface->setPointerPos(QPointF(10, 10)); m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->pointerAxis(Qt::Vertical, 5); + m_seatInterface->pointerAxis(Qt::Vertical, 5, 1, PointerAxisSource::Wheel); + m_seatInterface->pointerFrame(); // verify that we have those QVERIFY(axisSpy.wait()); QCOMPARE(axisSpy.count(), 1); @@ -523,6 +530,7 @@ void TestDragAndDrop::testPointerEventsIgnored() // let's start the drag m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonPressed(1); + m_seatInterface->pointerFrame(); QVERIFY(buttonSpy.wait()); QCOMPARE(buttonSpy.count(), 1); m_dataDevice->startDrag(buttonSpy.first().first().value(), m_dataSource, s.data()); @@ -531,24 +539,32 @@ void TestDragAndDrop::testPointerEventsIgnored() // now simulate all the possible pointer interactions m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonPressed(2); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonReleased(2); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->pointerAxis(Qt::Vertical, 5); + m_seatInterface->pointerAxis(Qt::Vertical, 5, 1, PointerAxisSource::Wheel); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->pointerAxis(Qt::Horizontal, 5); + m_seatInterface->pointerAxis(Qt::Vertical, 5, 1, PointerAxisSource::Wheel); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); m_seatInterface->setFocusedPointerSurface(nullptr); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); m_seatInterface->setFocusedPointerSurface(serverSurface); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); m_seatInterface->setPointerPos(QPointF(50, 50)); + m_seatInterface->pointerFrame(); // last but not least, simulate the drop QSignalSpy cancelledSpy(m_dataSource, &DataSource::cancelled); QVERIFY(cancelledSpy.isValid()); m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonReleased(1); + m_seatInterface->pointerFrame(); QVERIFY(cancelledSpy.wait()); // all the changes should have been ignored diff --git a/src/wayland/autotests/client/test_pointer_constraints.cpp b/src/wayland/autotests/client/test_pointer_constraints.cpp index e27a80e2d3..9422cd0824 100644 --- a/src/wayland/autotests/client/test_pointer_constraints.cpp +++ b/src/wayland/autotests/client/test_pointer_constraints.cpp @@ -225,11 +225,13 @@ void TestPointerConstraints::testLockPointer() QSignalSpy pointerMotionSpy(m_pointer, &Pointer::motion); QVERIFY(pointerMotionSpy.isValid()); m_seatInterface->setPointerPos(QPoint(0, 1)); + m_seatInterface->pointerFrame(); QVERIFY(pointerMotionSpy.wait()); serverLockedPointer->setLocked(true); QCOMPARE(serverLockedPointer->isLocked(), true); m_seatInterface->setPointerPos(QPoint(1, 1)); + m_seatInterface->pointerFrame(); QCOMPARE(lockedChangedSpy.count(), 1); QCOMPARE(pointerMotionSpy.count(), 1); QVERIFY(lockedSpy.isEmpty()); @@ -257,6 +259,7 @@ void TestPointerConstraints::testLockPointer() // now motion should work again m_seatInterface->setPointerPos(QPoint(0, 1)); + m_seatInterface->pointerFrame(); QVERIFY(pointerMotionSpy.wait()); QCOMPARE(pointerMotionSpy.count(), 2); diff --git a/src/wayland/autotests/client/test_wayland_seat.cpp b/src/wayland/autotests/client/test_wayland_seat.cpp index cf8208e629..ddc69799da 100644 --- a/src/wayland/autotests/client/test_wayland_seat.cpp +++ b/src/wayland/autotests/client/test_wayland_seat.cpp @@ -345,16 +345,16 @@ void TestWaylandSeat::testPointer() SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); - QSignalSpy focusedPointerChangedSpy(m_seatInterface, &SeatInterface::focusedPointerChanged); - QVERIFY(focusedPointerChangedSpy.isValid()); + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + s->attachBuffer(m_shm->createBuffer(image)); + s->damage(image.rect()); + s->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); m_seatInterface->setPointerPos(QPoint(20, 18)); m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15)); - QCOMPARE(focusedPointerChangedSpy.count(), 1); - QVERIFY(!focusedPointerChangedSpy.first().first().value()); - // no pointer yet - QVERIFY(m_seatInterface->focusedPointerSurface()); - QVERIFY(!m_seatInterface->focusedPointer()); Pointer *p = m_seat->createPointer(m_seat); QSignalSpy frameSpy(p, &Pointer::frame); @@ -363,20 +363,10 @@ void TestWaylandSeat::testPointer() QVERIFY(p->isValid()); QScopedPointer relativePointer(m_relativePointerManager->createRelativePointer(p)); QVERIFY(relativePointer->isValid()); - QSignalSpy pointerCreatedSpy(m_seatInterface, &KWaylandServer::SeatInterface::pointerCreated); - QVERIFY(pointerCreatedSpy.isValid()); - // once the pointer is created it should be set as the focused pointer - QVERIFY(pointerCreatedSpy.wait()); - QVERIFY(m_seatInterface->focusedPointer()); - 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(); QVERIFY(frameSpy.wait()); QCOMPARE(frameSpy.count(), 2); @@ -407,16 +397,13 @@ void TestWaylandSeat::testPointer() 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); QCOMPARE(cp.enteredSurface(), s); - QCOMPARE(focusedPointerChangedSpy.count(), 4); - QCOMPARE(focusedPointerChangedSpy.last().first().value(), serverPointer); // test motion m_seatInterface->setTimestamp(1); m_seatInterface->setPointerPos(QPoint(10, 16)); + m_seatInterface->pointerFrame(); QVERIFY(motionSpy.wait()); QCOMPARE(frameSpy.count(), 4); QCOMPARE(motionSpy.first().first().toPoint(), QPoint(0, 1)); @@ -424,6 +411,7 @@ void TestWaylandSeat::testPointer() // test relative motion m_seatInterface->relativePointerMotion(QSizeF(1, 2), QSizeF(3, 4), quint64(-1)); + m_seatInterface->pointerFrame(); QVERIFY(relativeMotionSpy.wait()); QCOMPARE(relativeMotionSpy.count(), 1); QCOMPARE(frameSpy.count(), 5); @@ -433,11 +421,13 @@ void TestWaylandSeat::testPointer() // test axis m_seatInterface->setTimestamp(2); - m_seatInterface->pointerAxis(Qt::Horizontal, 10); + m_seatInterface->pointerAxis(Qt::Horizontal, 10, 1, PointerAxisSource::Wheel); + m_seatInterface->pointerFrame(); QVERIFY(axisSpy.wait()); QCOMPARE(frameSpy.count(), 6); m_seatInterface->setTimestamp(3); - m_seatInterface->pointerAxis(Qt::Vertical, 20); + m_seatInterface->pointerAxis(Qt::Vertical, 20, 2, PointerAxisSource::Wheel); + m_seatInterface->pointerFrame(); QVERIFY(axisSpy.wait()); QCOMPARE(frameSpy.count(), 7); QCOMPARE(axisSpy.first().at(0).value(), quint32(2)); @@ -451,21 +441,25 @@ void TestWaylandSeat::testPointer() // test button m_seatInterface->setTimestamp(4); m_seatInterface->pointerButtonPressed(1); + m_seatInterface->pointerFrame(); QVERIFY(buttonSpy.wait()); QCOMPARE(frameSpy.count(), 8); QCOMPARE(buttonSpy.at(0).at(0).value(), m_display->serial()); m_seatInterface->setTimestamp(5); m_seatInterface->pointerButtonPressed(2); + m_seatInterface->pointerFrame(); QVERIFY(buttonSpy.wait()); QCOMPARE(frameSpy.count(), 9); QCOMPARE(buttonSpy.at(1).at(0).value(), m_display->serial()); m_seatInterface->setTimestamp(6); m_seatInterface->pointerButtonReleased(2); + m_seatInterface->pointerFrame(); QVERIFY(buttonSpy.wait()); QCOMPARE(frameSpy.count(), 10); QCOMPARE(buttonSpy.at(2).at(0).value(), m_display->serial()); m_seatInterface->setTimestamp(7); m_seatInterface->pointerButtonReleased(1); + m_seatInterface->pointerFrame(); QVERIFY(buttonSpy.wait()); QCOMPARE(frameSpy.count(), 11); QCOMPARE(buttonSpy.count(), 4); @@ -498,7 +492,6 @@ void TestWaylandSeat::testPointer() // leave the surface m_seatInterface->setFocusedPointerSurface(nullptr); - QCOMPARE(focusedPointerChangedSpy.count(), 5); QVERIFY(leftSpy.wait()); QCOMPARE(frameSpy.count(), 12); QCOMPARE(leftSpy.first().first().value(), m_display->serial()); @@ -511,7 +504,6 @@ void TestWaylandSeat::testPointer() // enter it again m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(0, 0)); - QCOMPARE(focusedPointerChangedSpy.count(), 6); QVERIFY(enteredSpy.wait()); QCOMPARE(frameSpy.count(), 13); QCOMPARE(p->enteredSurface(), s); @@ -524,62 +516,6 @@ void TestWaylandSeat::testPointer() QCOMPARE(relativeMotionSpy.last().at(0).toSizeF(), QSizeF(4, 5)); QCOMPARE(relativeMotionSpy.last().at(1).toSizeF(), QSizeF(6, 7)); QCOMPARE(relativeMotionSpy.last().at(2).value(), quint64(1)); - - // destroy the focused pointer - QSignalSpy unboundSpy(serverPointer, &Resource::unbound); - QVERIFY(unboundSpy.isValid()); - QSignalSpy destroyedSpy(serverPointer, &Resource::destroyed); - QVERIFY(destroyedSpy.isValid()); - delete p; - QVERIFY(unboundSpy.wait()); - QCOMPARE(unboundSpy.count(), 1); - QCOMPARE(destroyedSpy.count(), 0); - // now test that calling into the methods in Seat does not crash - QCOMPARE(m_seatInterface->focusedPointer(), serverPointer); - QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); - m_seatInterface->setTimestamp(8); - m_seatInterface->setPointerPos(QPoint(10, 15)); - m_seatInterface->setTimestamp(9); - m_seatInterface->pointerButtonPressed(1); - m_seatInterface->setTimestamp(10); - m_seatInterface->pointerButtonReleased(1); - m_seatInterface->setTimestamp(11); - m_seatInterface->pointerAxis(Qt::Horizontal, 10); - m_seatInterface->setTimestamp(12); - m_seatInterface->pointerAxis(Qt::Vertical, 20); - m_seatInterface->setFocusedPointerSurface(nullptr); - QCOMPARE(focusedPointerChangedSpy.count(), 7); - m_seatInterface->setFocusedPointerSurface(serverSurface); - QCOMPARE(focusedPointerChangedSpy.count(), 8); - QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); - QVERIFY(!m_seatInterface->focusedPointer()); - - // and now destroy - QVERIFY(destroyedSpy.wait()); - QCOMPARE(unboundSpy.count(), 1); - QCOMPARE(destroyedSpy.count(), 1); - QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); - QVERIFY(!m_seatInterface->focusedPointer()); - - // create a pointer again - p = m_seat->createPointer(m_seat); - QVERIFY(focusedPointerChangedSpy.wait()); - QCOMPARE(focusedPointerChangedSpy.count(), 9); - QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); - serverPointer = m_seatInterface->focusedPointer(); - QVERIFY(serverPointer); - - QSignalSpy entered2Spy(p, &Pointer::entered); - QVERIFY(entered2Spy.wait()); - QCOMPARE(p->enteredSurface(), s); - QSignalSpy leftSpy2(p, &Pointer::left); - QVERIFY(leftSpy2.isValid()); - delete s; - QVERIFY(!p->enteredSurface()); - QVERIFY(leftSpy2.wait()); - QCOMPARE(focusedPointerChangedSpy.count(), 10); - QVERIFY(!m_seatInterface->focusedPointerSurface()); - QVERIFY(!m_seatInterface->focusedPointer()); } void TestWaylandSeat::testPointerTransformation_data() @@ -618,23 +554,26 @@ void TestWaylandSeat::testPointerTransformation() SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + s->attachBuffer(m_shm->createBuffer(image)); + s->damage(image.rect()); + s->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); + m_seatInterface->setPointerPos(QPoint(20, 18)); QFETCH(QMatrix4x4, enterTransformation); m_seatInterface->setFocusedPointerSurface(serverSurface, enterTransformation); QCOMPARE(m_seatInterface->focusedPointerSurfaceTransformation(), enterTransformation); // no pointer yet QVERIFY(m_seatInterface->focusedPointerSurface()); - QVERIFY(!m_seatInterface->focusedPointer()); Pointer *p = m_seat->createPointer(m_seat); - const Pointer &cp = *p; QVERIFY(p->isValid()); - QSignalSpy pointerCreatedSpy(m_seatInterface, &SeatInterface::pointerCreated); - QVERIFY(pointerCreatedSpy.isValid()); - // once the pointer is created it should be set as the focused pointer - QVERIFY(pointerCreatedSpy.wait()); - QVERIFY(m_seatInterface->focusedPointer()); - QCOMPARE(pointerCreatedSpy.first().first().value(), m_seatInterface->focusedPointer()); + QSignalSpy frameSpy(p, &Pointer::frame); + QVERIFY(frameSpy.wait()); + const Pointer &cp = *p; m_seatInterface->setFocusedPointerSurface(nullptr); serverSurface->client()->flush(); @@ -656,14 +595,13 @@ void TestWaylandSeat::testPointerTransformation() QVERIFY(enteredSpy.wait()); QCOMPARE(enteredSpy.first().first().value(), m_display->serial()); QTEST(enteredSpy.first().last().toPointF(), "expectedEnterPoint"); - PointerInterface *serverPointer = m_seatInterface->focusedPointer(); - QVERIFY(serverPointer); QCOMPARE(p->enteredSurface(), s); QCOMPARE(cp.enteredSurface(), s); // test motion m_seatInterface->setTimestamp(1); m_seatInterface->setPointerPos(QPoint(10, 16)); + m_seatInterface->pointerFrame(); QVERIFY(motionSpy.wait()); QTEST(motionSpy.first().first().toPointF(), "expectedMovePoint"); QCOMPARE(motionSpy.first().last().value(), quint32(1)); @@ -730,11 +668,19 @@ void TestWaylandSeat::testPointerButton() QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWaylandServer::CompositorInterface::surfaceCreated); QVERIFY(surfaceCreatedSpy.isValid()); - m_compositor->createSurface(m_compositor); + KWayland::Client::Surface *s = m_compositor->createSurface(m_compositor); QVERIFY(surfaceCreatedSpy.wait()); SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + s->attachBuffer(m_shm->createBuffer(image)); + s->damage(image.rect()); + s->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); + QScopedPointer p(m_seat->createPointer()); QVERIFY(p->isValid()); QSignalSpy buttonChangedSpy(p.data(), &KWayland::Client::Pointer::buttonStateChanged); @@ -745,13 +691,10 @@ void TestWaylandSeat::testPointerButton() m_seatInterface->setPointerPos(QPoint(20, 18)); m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15)); QVERIFY(m_seatInterface->focusedPointerSurface()); - QVERIFY(m_seatInterface->focusedPointer()); QCoreApplication::processEvents(); m_seatInterface->setFocusedPointerSurface(serverSurface, QPoint(10, 15)); - PointerInterface *serverPointer = m_seatInterface->focusedPointer(); - QVERIFY(serverPointer); QFETCH(Qt::MouseButton, qtButton); QFETCH(quint32, waylandButton); quint32 msec = QDateTime::currentMSecsSinceEpoch(); @@ -759,6 +702,7 @@ void TestWaylandSeat::testPointerButton() QCOMPARE(m_seatInterface->isPointerButtonPressed(qtButton), false); m_seatInterface->setTimestamp(msec); m_seatInterface->pointerButtonPressed(qtButton); + m_seatInterface->pointerFrame(); QCOMPARE(m_seatInterface->isPointerButtonPressed(waylandButton), true); QCOMPARE(m_seatInterface->isPointerButtonPressed(qtButton), true); QVERIFY(buttonChangedSpy.wait()); @@ -771,6 +715,7 @@ void TestWaylandSeat::testPointerButton() msec = QDateTime::currentMSecsSinceEpoch(); m_seatInterface->setTimestamp(QDateTime::currentMSecsSinceEpoch()); m_seatInterface->pointerButtonReleased(qtButton); + m_seatInterface->pointerFrame(); QCOMPARE(m_seatInterface->isPointerButtonPressed(waylandButton), false); QCOMPARE(m_seatInterface->isPointerButtonPressed(qtButton), false); QVERIFY(buttonChangedSpy.wait()); @@ -847,6 +792,7 @@ void TestWaylandSeat::testPointerSubSurfaceTree() // a motion on grandchild2 m_seatInterface->setTimestamp(timestamp++); m_seatInterface->setPointerPos(QPointF(25, 60)); + m_seatInterface->pointerFrame(); QVERIFY(motionSpy.wait()); QCOMPARE(enteredSpy.count(), 1); QCOMPARE(leftSpy.count(), 0); @@ -855,10 +801,11 @@ void TestWaylandSeat::testPointerSubSurfaceTree() // motion which changes to childSurface m_seatInterface->setTimestamp(timestamp++); m_seatInterface->setPointerPos(QPointF(25, 80)); + m_seatInterface->pointerFrame(); QVERIFY(enteredSpy.wait()); QCOMPARE(enteredSpy.count(), 2); QCOMPARE(leftSpy.count(), 1); - QCOMPARE(motionSpy.count(), 1); + QCOMPARE(motionSpy.count(), 2); QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(25, 80)); QCOMPARE(pointer->enteredSurface(), childSurface.data()); // a leave for the whole surface @@ -867,7 +814,7 @@ void TestWaylandSeat::testPointerSubSurfaceTree() QVERIFY(leftSpy.wait()); QCOMPARE(enteredSpy.count(), 2); QCOMPARE(leftSpy.count(), 2); - QCOMPARE(motionSpy.count(), 1); + QCOMPARE(motionSpy.count(), 2); // a new enter on the main surface m_seatInterface->setTimestamp(timestamp++); m_seatInterface->setPointerPos(QPointF(75, 50)); @@ -875,7 +822,7 @@ void TestWaylandSeat::testPointerSubSurfaceTree() QVERIFY(enteredSpy.wait()); QCOMPARE(enteredSpy.count(), 3); QCOMPARE(leftSpy.count(), 2); - QCOMPARE(motionSpy.count(), 1); + QCOMPARE(motionSpy.count(), 2); QCOMPARE(enteredSpy.last().last().toPointF(), QPointF(75, 50)); QCOMPARE(pointer->enteredSurface(), parentSurface.data()); } @@ -923,9 +870,18 @@ void TestWaylandSeat::testPointerSwipeGesture() QVERIFY(surfaceCreatedSpy.wait()); auto serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); + + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + surface->attachBuffer(m_shm->createBuffer(image)); + surface->damage(image.rect()); + surface->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); + m_seatInterface->setFocusedPointerSurface(serverSurface); QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); - QVERIFY(m_seatInterface->focusedPointer()); + QVERIFY(m_seatInterface->pointer()); // send in the start quint32 timestamp = 1; @@ -1039,9 +995,18 @@ void TestWaylandSeat::testPointerPinchGesture() QVERIFY(surfaceCreatedSpy.wait()); auto serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); + + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + surface->attachBuffer(m_shm->createBuffer(image)); + surface->damage(image.rect()); + surface->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); + m_seatInterface->setFocusedPointerSurface(serverSurface); QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); - QVERIFY(m_seatInterface->focusedPointer()); + QVERIFY(m_seatInterface->pointer()); // send in the start quint32 timestamp = 1; @@ -1136,9 +1101,17 @@ void TestWaylandSeat::testPointerAxis() QVERIFY(surfaceCreatedSpy.wait()); auto serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); + + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + surface->attachBuffer(m_shm->createBuffer(image)); + surface->damage(image.rect()); + surface->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); + m_seatInterface->setFocusedPointerSurface(serverSurface); QCOMPARE(m_seatInterface->focusedPointerSurface(), serverSurface); - QVERIFY(m_seatInterface->focusedPointer()); QSignalSpy frameSpy(pointer.data(), &Pointer::frame); QVERIFY(frameSpy.isValid()); QVERIFY(frameSpy.wait()); @@ -1156,7 +1129,8 @@ void TestWaylandSeat::testPointerAxis() quint32 timestamp = 1; m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->pointerAxisV5(Qt::Vertical, 10, 1, PointerAxisSource::Wheel); + m_seatInterface->pointerAxis(Qt::Vertical, 10, 1, PointerAxisSource::Wheel); + m_seatInterface->pointerFrame(); QVERIFY(frameSpy.wait()); QCOMPARE(frameSpy.count(), 2); QCOMPARE(axisSourceSpy.count(), 1); @@ -1172,7 +1146,8 @@ void TestWaylandSeat::testPointerAxis() // let's scroll using fingers m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->pointerAxisV5(Qt::Horizontal, 42, 0, PointerAxisSource::Finger); + m_seatInterface->pointerAxis(Qt::Horizontal, 42, 0, PointerAxisSource::Finger); + m_seatInterface->pointerFrame(); QVERIFY(frameSpy.wait()); QCOMPARE(frameSpy.count(), 3); QCOMPARE(axisSourceSpy.count(), 2); @@ -1186,7 +1161,8 @@ void TestWaylandSeat::testPointerAxis() // lift the fingers off the device m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->pointerAxisV5(Qt::Horizontal, 0, 0, PointerAxisSource::Finger); + m_seatInterface->pointerAxis(Qt::Horizontal, 0, 0, PointerAxisSource::Finger); + m_seatInterface->pointerFrame(); QVERIFY(frameSpy.wait()); QCOMPARE(frameSpy.count(), 4); QCOMPARE(axisSourceSpy.count(), 3); @@ -1199,7 +1175,8 @@ void TestWaylandSeat::testPointerAxis() // if the device is unknown, no axis_source event should be sent m_seatInterface->setTimestamp(timestamp++); - m_seatInterface->pointerAxisV5(Qt::Horizontal, 42, 1, PointerAxisSource::Unknown); + m_seatInterface->pointerAxis(Qt::Horizontal, 42, 1, PointerAxisSource::Unknown); + m_seatInterface->pointerFrame(); QVERIFY(frameSpy.wait()); QCOMPARE(frameSpy.count(), 5); QCOMPARE(axisSourceSpy.count(), 3); @@ -1291,8 +1268,10 @@ void TestWaylandSeat::testKeyboardSubSurfaceTreeFromPointer() // let's click m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonPressed(Qt::LeftButton); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonReleased(Qt::LeftButton); + m_seatInterface->pointerFrame(); QVERIFY(enterSpy.wait()); QCOMPARE(enterSpy.count(), 2); QCOMPARE(leftSpy.count(), 1); @@ -1301,8 +1280,10 @@ void TestWaylandSeat::testKeyboardSubSurfaceTreeFromPointer() // click on same surface should not trigger another enter m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonPressed(Qt::LeftButton); + m_seatInterface->pointerFrame(); m_seatInterface->setTimestamp(timestamp++); m_seatInterface->pointerButtonReleased(Qt::LeftButton); + m_seatInterface->pointerFrame(); QVERIFY(!enterSpy.wait(200)); QCOMPARE(enterSpy.count(), 2); QCOMPARE(leftSpy.count(), 1); @@ -1310,6 +1291,7 @@ void TestWaylandSeat::testKeyboardSubSurfaceTreeFromPointer() // unfocus keyboard m_seatInterface->setFocusedKeyboardSurface(nullptr); + m_seatInterface->pointerFrame(); QVERIFY(leftSpy.wait()); QCOMPARE(enterSpy.count(), 2); QCOMPARE(leftSpy.count(), 2); @@ -1327,11 +1309,19 @@ void TestWaylandSeat::testCursor() QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWaylandServer::CompositorInterface::surfaceCreated); QVERIFY(surfaceCreatedSpy.isValid()); - m_compositor->createSurface(m_compositor); + KWayland::Client::Surface *surface = m_compositor->createSurface(m_compositor); QVERIFY(surfaceCreatedSpy.wait()); SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + surface->attachBuffer(m_shm->createBuffer(image)); + surface->damage(image.rect()); + surface->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); + QScopedPointer p(m_seat->createPointer()); QVERIFY(p->isValid()); wl_display_flush(m_connection->display()); @@ -1346,21 +1336,20 @@ void TestWaylandSeat::testCursor() QVERIFY(enteredSpy.wait()); QCOMPARE(enteredSpy.first().first().value(), serial); QVERIFY(m_seatInterface->focusedPointerSurface()); - QVERIFY(m_seatInterface->focusedPointer()); - QVERIFY(!m_seatInterface->focusedPointer()->cursor()); + QVERIFY(!m_seatInterface->pointer()->cursor()); - QSignalSpy cursorChangedSpy(m_seatInterface->focusedPointer(), &KWaylandServer::PointerInterface::cursorChanged); + QSignalSpy cursorChangedSpy(m_seatInterface->pointer(), &KWaylandServer::PointerInterface::cursorChanged); QVERIFY(cursorChangedSpy.isValid()); // just remove the pointer p->setCursor(nullptr); QVERIFY(cursorChangedSpy.wait()); QCOMPARE(cursorChangedSpy.count(), 1); - auto cursor = m_seatInterface->focusedPointer()->cursor(); + auto cursor = m_seatInterface->pointer()->cursor(); QVERIFY(cursor); QVERIFY(!cursor->surface()); QCOMPARE(cursor->hotspot(), QPoint()); QCOMPARE(cursor->enteredSerial(), serial); - QCOMPARE(cursor->pointer(), m_seatInterface->focusedPointer()); + QCOMPARE(cursor->pointer(), m_seatInterface->pointer()); QSignalSpy hotspotChangedSpy(cursor, &KWaylandServer::Cursor::hotspotChanged); QVERIFY(hotspotChangedSpy.isValid()); @@ -1443,17 +1432,25 @@ void TestWaylandSeat::testCursorDamage() // create surface QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); QVERIFY(surfaceCreatedSpy.isValid()); - m_compositor->createSurface(m_compositor); + KWayland::Client::Surface *surface = m_compositor->createSurface(m_compositor); QVERIFY(surfaceCreatedSpy.wait()); SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value(); QVERIFY(serverSurface); + QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::black); + surface->attachBuffer(m_shm->createBuffer(image)); + surface->damage(image.rect()); + surface->commit(Surface::CommitFlag::None); + QSignalSpy committedSpy(serverSurface, &KWaylandServer::SurfaceInterface::committed); + QVERIFY(committedSpy.wait()); + // send enter to the surface m_seatInterface->setFocusedPointerSurface(serverSurface); QVERIFY(enteredSpy.wait()); // create a signal spy for the cursor changed signal - auto pointer = m_seatInterface->focusedPointer(); + auto pointer = m_seatInterface->pointer(); QSignalSpy cursorChangedSpy(pointer, &PointerInterface::cursorChanged); QVERIFY(cursorChangedSpy.isValid()); @@ -2167,14 +2164,11 @@ void TestWaylandSeat::testDisconnect() using namespace KWaylandServer; QSignalSpy keyboardCreatedSpy(m_seatInterface, &SeatInterface::keyboardCreated); QVERIFY(keyboardCreatedSpy.isValid()); - QSignalSpy pointerCreatedSpy(m_seatInterface, &SeatInterface::pointerCreated); - QVERIFY(pointerCreatedSpy.isValid()); QSignalSpy touchCreatedSpy(m_seatInterface, &SeatInterface::touchCreated); QVERIFY(touchCreatedSpy.isValid()); // create the things we need m_seatInterface->setHasKeyboard(true); - m_seatInterface->setHasPointer(true); m_seatInterface->setHasTouch(true); QSignalSpy touchSpy(m_seat, &Seat::hasTouchChanged); QVERIFY(touchSpy.isValid()); @@ -2186,12 +2180,6 @@ void TestWaylandSeat::testDisconnect() auto serverKeyboard = keyboardCreatedSpy.first().first().value(); QVERIFY(serverKeyboard); - QScopedPointer pointer(m_seat->createPointer()); - QVERIFY(!pointer.isNull()); - QVERIFY(pointerCreatedSpy.wait()); - auto serverPointer = pointerCreatedSpy.first().first().value(); - QVERIFY(serverPointer); - QScopedPointer touch(m_seat->createTouch()); QVERIFY(!touch.isNull()); QVERIFY(touchCreatedSpy.wait()); @@ -2201,8 +2189,6 @@ void TestWaylandSeat::testDisconnect() // setup destroys QSignalSpy keyboardDestroyedSpy(serverKeyboard, &QObject::destroyed); QVERIFY(keyboardDestroyedSpy.isValid()); - QSignalSpy pointerDestroyedSpy(serverPointer, &QObject::destroyed); - QVERIFY(pointerDestroyedSpy.isValid()); QSignalSpy touchDestroyedSpy(serverTouch, &QObject::destroyed); QVERIFY(touchDestroyedSpy.isValid()); @@ -2212,7 +2198,6 @@ void TestWaylandSeat::testDisconnect() } keyboard->destroy(); - pointer->destroy(); touch->destroy(); m_relativePointerManager->destroy(); m_pointerGestures->destroy(); diff --git a/src/wayland/autotests/server/test_seat.cpp b/src/wayland/autotests/server/test_seat.cpp index 1734444255..3dbd863a10 100644 --- a/src/wayland/autotests/server/test_seat.cpp +++ b/src/wayland/autotests/server/test_seat.cpp @@ -102,8 +102,7 @@ void TestWaylandServerSeat::testPointerButton() display.addSocketName(s_socketName); display.start(); SeatInterface *seat = new SeatInterface(&display); - PointerInterface *pointer = seat->focusedPointer(); - QVERIFY(!pointer); + seat->setHasPointer(true); // no button pressed yet, should be released and no serial QVERIFY(!seat->isPointerButtonPressed(0)); @@ -113,6 +112,7 @@ void TestWaylandServerSeat::testPointerButton() // mark the button as pressed seat->pointerButtonPressed(0); + seat->pointerFrame(); QVERIFY(seat->isPointerButtonPressed(0)); QCOMPARE(seat->pointerButtonSerial(0), display.serial()); @@ -122,6 +122,7 @@ void TestWaylandServerSeat::testPointerButton() // release it again seat->pointerButtonReleased(0); + seat->pointerFrame(); QVERIFY(!seat->isPointerButtonPressed(0)); QCOMPARE(seat->pointerButtonSerial(0), display.serial()); } @@ -132,22 +133,24 @@ void TestWaylandServerSeat::testPointerPos() display.addSocketName(s_socketName); display.start(); SeatInterface *seat = new SeatInterface(&display); + seat->setHasPointer(true); QSignalSpy seatPosSpy(seat, SIGNAL(pointerPosChanged(QPointF))); QVERIFY(seatPosSpy.isValid()); - PointerInterface *pointer = seat->focusedPointer(); - QVERIFY(!pointer); QCOMPARE(seat->pointerPos(), QPointF()); seat->setPointerPos(QPointF(10, 15)); + seat->pointerFrame(); QCOMPARE(seat->pointerPos(), QPointF(10, 15)); QCOMPARE(seatPosSpy.count(), 1); QCOMPARE(seatPosSpy.first().first().toPointF(), QPointF(10, 15)); seat->setPointerPos(QPointF(10, 15)); + seat->pointerFrame(); QCOMPARE(seatPosSpy.count(), 1); seat->setPointerPos(QPointF(5, 7)); + seat->pointerFrame(); QCOMPARE(seat->pointerPos(), QPointF(5, 7)); QCOMPARE(seatPosSpy.count(), 2); QCOMPARE(seatPosSpy.first().first().toPointF(), QPointF(10, 15)); diff --git a/src/wayland/pointer_interface.cpp b/src/wayland/pointer_interface.cpp index 4fcb8d9598..d2f57c45d3 100644 --- a/src/wayland/pointer_interface.cpp +++ b/src/wayland/pointer_interface.cpp @@ -1,411 +1,315 @@ /* SPDX-FileCopyrightText: 2014 Martin Gräßlin + SPDX-FileCopyrightText: 2020 Adrien Faveraux + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ + #include "pointer_interface.h" +#include "clientconnection.h" +#include "display.h" +#include "logging.h" #include "pointer_interface_p.h" -#include "pointerconstraints_v1_interface.h" #include "pointergestures_v1_interface_p.h" -#include "resource_p.h" #include "relativepointer_v1_interface_p.h" #include "seat_interface.h" -#include "display.h" -#include "subcompositor_interface.h" #include "surface_interface.h" -#include "datadevice_interface.h" -// Wayland -#include +#include "surfacerole_p.h" +#include "utils.h" namespace KWaylandServer { -class Cursor::Private +class CursorPrivate { public: - Private(Cursor *q, PointerInterface *pointer); + CursorPrivate(Cursor *q, PointerInterface *pointer); + + Cursor *q; PointerInterface *pointer; quint32 enteredSerial = 0; QPoint hotspot; QPointer surface; - void update(const QPointer &surface, quint32 serial, const QPoint &hotspot); - -private: - Cursor *q; + void update(SurfaceInterface *surface, quint32 serial, const QPoint &hotspot); }; -PointerInterface::Private::Private(SeatInterface *parent, wl_resource *parentResource, PointerInterface *q) - : Resource::Private(q, parent, parentResource, &wl_pointer_interface, &s_interface) - , seat(parent) +PointerInterfacePrivate *PointerInterfacePrivate::get(PointerInterface *pointer) +{ + return pointer->d.data(); +} + +PointerInterfacePrivate::PointerInterfacePrivate(PointerInterface *q, SeatInterface *seat) + : q(q) + , seat(seat) + , relativePointersV1(new RelativePointerV1Interface(q)) + , swipeGesturesV1(new PointerSwipeGestureV1Interface(q)) + , pinchGesturesV1(new PointerPinchGestureV1Interface(q)) { } -void PointerInterface::Private::setCursor(quint32 serial, SurfaceInterface *surface, const QPoint &hotspot) +PointerInterfacePrivate::~PointerInterfacePrivate() { - if (!cursor) { - Q_Q(PointerInterface); +} + +QList PointerInterfacePrivate::pointersForClient(ClientConnection *client) const +{ + return resourceMap().values(client->client()); +} + +void PointerInterfacePrivate::pointer_set_cursor(Resource *resource, uint32_t serial, + ::wl_resource *surface_resource, + int32_t hotspot_x, int32_t hotspot_y) +{ + SurfaceInterface *surface = nullptr; + + if (!focusedSurface) { + return; + } + if (focusedSurface->client()->client() != resource->client()) { + qCDebug(KWAYLAND_SERVER, "Denied set_cursor request from unfocused client"); + return; + } + + if (surface_resource) { + surface = SurfaceInterface::get(surface_resource); + if (!surface) { + wl_resource_post_error(resource->handle, WL_DISPLAY_ERROR_INVALID_OBJECT, + "invalid surface"); + return; + } + + const SurfaceRole *surfaceRole = SurfaceRole::get(surface); + if (surfaceRole) { + wl_resource_post_error(resource->handle, error_role, + "the wl_surface already has a role assigned %s", + surfaceRole->name().constData()); + return; + } + } + + if (!cursor) { // TODO: Assign the cursor surface role. cursor = new Cursor(q); - cursor->d->update(QPointer(surface), serial, hotspot); + cursor->d->update(surface, serial, QPoint(hotspot_x, hotspot_y)); QObject::connect(cursor, &Cursor::changed, q, &PointerInterface::cursorChanged); emit q->cursorChanged(); } else { - cursor->d->update(QPointer(surface), serial, hotspot); + cursor->d->update(surface, serial, QPoint(hotspot_x, hotspot_y)); } } -void PointerInterface::Private::sendLeave(SurfaceInterface *surface, quint32 serial) +void PointerInterfacePrivate::pointer_release(Resource *resource) { - if (!surface) { - return; - } - if (resource && surface->resource()) { - wl_pointer_send_leave(resource, serial, surface->resource()); - } + wl_resource_destroy(resource->handle); } -void PointerInterface::Private::registerRelativePointerV1(RelativePointerV1Interface *relativePointer) +void PointerInterfacePrivate::pointer_bind_resource(Resource *resource) { - Q_ASSERT(!relativePointersV1.contains(relativePointer)); - relativePointersV1.append(relativePointer); -} + const ClientConnection *focusedClient = focusedSurface ? focusedSurface->client() : nullptr; -void PointerInterface::Private::unregisterRelativePointerV1(RelativePointerV1Interface *relativePointer) -{ - Q_ASSERT(relativePointersV1.contains(relativePointer)); - relativePointersV1.removeOne(relativePointer); -} - -void PointerInterface::Private::registerSwipeGestureV1(PointerSwipeGestureV1Interface *gesture) -{ - Q_ASSERT(!swipeGesturesV1.contains(gesture)); - swipeGesturesV1.append(gesture); -} - -void PointerInterface::Private::unregisterSwipeGestureV1(PointerSwipeGestureV1Interface *gesture) -{ - Q_ASSERT(swipeGesturesV1.contains(gesture)); - swipeGesturesV1.removeOne(gesture); -} - -void PointerInterface::Private::registerPinchGestureV1(PointerPinchGestureV1Interface *gesture) -{ - Q_ASSERT(!pinchGesturesV1.contains(gesture)); - pinchGesturesV1.append(gesture); -} - -void PointerInterface::Private::unregisterPinchGestureV1(PointerPinchGestureV1Interface *gesture) -{ - Q_ASSERT(pinchGesturesV1.contains(gesture)); - pinchGesturesV1.removeOne(gesture); -} - -namespace { -static QPointF surfacePosition(SurfaceInterface *surface) { - if (surface && surface->subSurface()) { - return surface->subSurface()->position() + surfacePosition(surface->subSurface()->parentSurface()); - } - return QPointF(); -} -} - -void PointerInterface::Private::sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial) -{ - if (!surface || !surface->resource()) { - return; - } - const QPointF adjustedPos = parentSurfacePosition - surfacePosition(surface); - wl_pointer_send_enter(resource, serial, - surface->resource(), - wl_fixed_from_double(adjustedPos.x()), wl_fixed_from_double(adjustedPos.y())); -} - -void PointerInterface::Private::startSwipeGesture(quint32 serial, quint32 fingerCount) -{ - if (!focusedSurface) { - return; - } - for (PointerSwipeGestureV1Interface *gesture : qAsConst(swipeGesturesV1)) { - gesture->send_begin(serial, seat->timestamp(), focusedSurface->resource(), fingerCount); - } -} - -void PointerInterface::Private::updateSwipeGesture(const QSizeF &delta) -{ - for (PointerSwipeGestureV1Interface *gesture : qAsConst(swipeGesturesV1)) { - gesture->send_update(seat->timestamp(), - wl_fixed_from_double(delta.width()), - wl_fixed_from_double(delta.height())); - } -} - -void PointerInterface::Private::endSwipeGesture(quint32 serial) -{ - for (PointerSwipeGestureV1Interface *gesture : qAsConst(swipeGesturesV1)) { - gesture->send_end(serial, seat->timestamp(), false); - } -} - -void PointerInterface::Private::cancelSwipeGesture(quint32 serial) -{ - for (PointerSwipeGestureV1Interface *gesture : qAsConst(swipeGesturesV1)) { - gesture->send_end(serial, seat->timestamp(), true); - } -} - -void PointerInterface::Private::startPinchGesture(quint32 serial, quint32 fingerCount) -{ - if (!focusedSurface) { - return; - } - for (PointerPinchGestureV1Interface *gesture : qAsConst(pinchGesturesV1)) { - gesture->send_begin(serial, seat->timestamp(), focusedSurface->resource(), fingerCount); - } -} - -void PointerInterface::Private::updatePinchGesture(const QSizeF &delta, qreal scale, qreal rotation) -{ - for (PointerPinchGestureV1Interface *gesture : qAsConst(pinchGesturesV1)) { - gesture->send_update(seat->timestamp(), - wl_fixed_from_double(delta.width()), - wl_fixed_from_double(delta.height()), - wl_fixed_from_double(scale), - wl_fixed_from_double(rotation)); - } -} - -void PointerInterface::Private::endPinchGesture(quint32 serial) -{ - for (PointerPinchGestureV1Interface *gesture : qAsConst(pinchGesturesV1)) { - gesture->send_end(serial, seat->timestamp(), false); - } -} - -void PointerInterface::Private::cancelPinchGesture(quint32 serial) -{ - for (PointerPinchGestureV1Interface *gesture : qAsConst(pinchGesturesV1)) { - gesture->send_end(serial, seat->timestamp(), true); - } -} - -void PointerInterface::Private::sendFrame() -{ - if (!resource || wl_resource_get_version(resource) < WL_POINTER_FRAME_SINCE_VERSION) { - return; - } - wl_pointer_send_frame(resource); -} - -#ifndef K_DOXYGEN -const struct wl_pointer_interface PointerInterface::Private::s_interface = { - setCursorCallback, - resourceDestroyedCallback -}; -#endif - -PointerInterface::PointerInterface(SeatInterface *parent, wl_resource *parentResource) - : Resource(new Private(parent, parentResource, this)) -{ - // TODO: handle touch - connect(parent, &SeatInterface::pointerPosChanged, this, [this] { - Q_D(); - if (!d->focusedSurface || !d->resource) { - return; + if (focusedClient && focusedClient->client() == resource->client()) { + const quint32 serial = seat->display()->nextSerial(); + send_enter(resource->handle, serial, focusedSurface->resource(), + wl_fixed_from_double(lastPosition.x()), wl_fixed_from_double(lastPosition.y())); + if (resource->version() >= WL_POINTER_FRAME_SINCE_VERSION) { + send_frame(resource->handle); } - if (d->seat->isDragPointer()) { - const auto *originSurface = d->seat->dragSource()->origin(); - const bool proxyRemoteFocused = originSurface->dataProxy() && originSurface == d->focusedSurface; - if (!proxyRemoteFocused) { - // handled by DataDevice - return; - } + } +} + +void PointerInterfacePrivate::sendLeave(quint32 serial) +{ + const QList pointerResources = pointersForClient(focusedSurface->client()); + for (Resource *resource : pointerResources) { + send_leave(resource->handle, serial, focusedSurface->resource()); + } +} + +void PointerInterfacePrivate::sendEnter(const QPointF &position, quint32 serial) +{ + const QList pointerResources = pointersForClient(focusedSurface->client()); + for (Resource *resource : pointerResources) { + send_enter(resource->handle, serial, focusedSurface->resource(), + wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); + } +} + +void PointerInterfacePrivate::sendFrame() +{ + const QList pointerResources = pointersForClient(focusedSurface->client()); + for (Resource *resource : pointerResources) { + if (resource->version() >= WL_POINTER_FRAME_SINCE_VERSION) { + send_frame(resource->handle); } - if (d->focusedSurface->lockedPointer() && d->focusedSurface->lockedPointer()->isLocked()) { - return; - } - const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos()); - auto targetSurface = d->focusedSurface->inputSurfaceAt(pos); - if (!targetSurface) { - targetSurface = d->focusedSurface; - } - if (targetSurface != d->focusedChildSurface.data()) { - const quint32 serial = d->seat->display()->nextSerial(); - 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())); + } +} + +PointerInterface::PointerInterface(SeatInterface *seat) + : d(new PointerInterfacePrivate(this, seat)) +{ +} + +PointerInterface::~PointerInterface() +{ +} + +SurfaceInterface *PointerInterface::focusedSurface() const +{ + return d->focusedSurface; +} + +void PointerInterface::setFocusedSurface(SurfaceInterface *surface, const QPointF &position, quint32 serial) +{ + if (d->focusedSurface == surface) { + return; + } + + if (d->focusedSurface) { + d->sendLeave(serial); + if (!surface || d->focusedSurface->client() != surface->client()) { d->sendFrame(); } - }); -} - -PointerInterface::~PointerInterface() = default; - -void PointerInterface::setFocusedSurface(SurfaceInterface *surface, quint32 serial) -{ - Q_D(); - d->sendLeave(d->focusedChildSurface.data(), serial); - disconnect(d->destroyConnection); - if (!surface) { - d->focusedSurface = nullptr; - d->focusedChildSurface.clear(); - return; + disconnect(d->destroyConnection); } + d->focusedSurface = surface; - d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this, - [this] { - Q_D(); - d->sendLeave(d->focusedChildSurface.data(), d->global->display()->nextSerial()); + + if (d->focusedSurface) { + d->destroyConnection = connect(d->focusedSurface, &SurfaceInterface::aboutToBeDestroyed, this, [this]() { + d->sendLeave(d->seat->display()->nextSerial()); d->sendFrame(); d->focusedSurface = nullptr; - d->focusedChildSurface.clear(); + emit focusedSurfaceChanged(); + }); + d->sendEnter(position, serial); + d->sendFrame(); + d->lastPosition = position; + } + + emit focusedSurfaceChanged(); +} + +void PointerInterface::sendPressed(quint32 button, quint32 serial) +{ + if (!d->focusedSurface) { + return; + } + + const auto pointerResources = d->pointersForClient(d->focusedSurface->client()); + for (PointerInterfacePrivate::Resource *resource : pointerResources) { + d->send_button(resource->handle, serial, d->seat->timestamp(), button, + PointerInterfacePrivate::button_state_pressed); + } +} + +void PointerInterface::sendReleased(quint32 button, quint32 serial) +{ + if (!d->focusedSurface) { + return; + } + + const auto pointerResources = d->pointersForClient(d->focusedSurface->client()); + for (PointerInterfacePrivate::Resource *resource : pointerResources) { + d->send_button(resource->handle, serial, d->seat->timestamp(), button, + PointerInterfacePrivate::button_state_released); + } +} + +void PointerInterface::sendAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source) +{ + if (!d->focusedSurface) { + return; + } + + const auto pointerResources = d->pointersForClient(d->focusedSurface->client()); + for (PointerInterfacePrivate::Resource *resource : pointerResources) { + const quint32 version = resource->version(); + + const auto wlOrientation = (orientation == Qt::Vertical) + ? PointerInterfacePrivate::axis_vertical_scroll + : PointerInterfacePrivate::axis_horizontal_scroll; + + if (source != PointerAxisSource::Unknown && version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) { + PointerInterfacePrivate::axis_source wlSource; + switch (source) { + case PointerAxisSource::Wheel: + wlSource = PointerInterfacePrivate::axis_source_wheel; + break; + case PointerAxisSource::Finger: + wlSource = PointerInterfacePrivate::axis_source_finger; + break; + case PointerAxisSource::Continuous: + wlSource = PointerInterfacePrivate::axis_source_continuous; + break; + case PointerAxisSource::WheelTilt: + wlSource = PointerInterfacePrivate::axis_source_wheel_tilt; + break; + default: + Q_UNREACHABLE(); + break; + } + d->send_axis_source(resource->handle, wlSource); } - ); - const QPointF pos = d->seat->focusedPointerSurfaceTransformation().map(d->seat->pointerPos()); - d->focusedChildSurface = QPointer(d->focusedSurface->inputSurfaceAt(pos)); - if (!d->focusedChildSurface) { - d->focusedChildSurface = QPointer(d->focusedSurface); - } - d->sendEnter(d->focusedChildSurface.data(), pos, serial); - d->client->flush(); -} - -void PointerInterface::buttonPressed(quint32 button, quint32 serial) -{ - Q_D(); - Q_ASSERT(d->focusedSurface); - if (!d->resource) { - 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) -{ - Q_D(); - Q_ASSERT(d->focusedSurface); - if (!d->resource) { - 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, qreal delta, qint32 discreteDelta, PointerAxisSource source) -{ - Q_D(); - Q_ASSERT(d->focusedSurface); - if (!d->resource) { - return; - } - - const quint32 version = wl_resource_get_version(d->resource); - - const auto wlOrientation = (orientation == Qt::Vertical) - ? WL_POINTER_AXIS_VERTICAL_SCROLL - : WL_POINTER_AXIS_HORIZONTAL_SCROLL; - - if (source != PointerAxisSource::Unknown && version >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION) { - wl_pointer_axis_source wlSource; - switch (source) { - case PointerAxisSource::Wheel: - wlSource = WL_POINTER_AXIS_SOURCE_WHEEL; - break; - case PointerAxisSource::Finger: - wlSource = WL_POINTER_AXIS_SOURCE_FINGER; - break; - case PointerAxisSource::Continuous: - wlSource = WL_POINTER_AXIS_SOURCE_CONTINUOUS; - break; - case PointerAxisSource::WheelTilt: - wlSource = WL_POINTER_AXIS_SOURCE_WHEEL_TILT; - break; - default: - Q_UNREACHABLE(); - break; + if (delta != 0.0) { + if (discreteDelta && version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { + d->send_axis_discrete(resource->handle, wlOrientation, discreteDelta); + } + d->send_axis(resource->handle, d->seat->timestamp(), wlOrientation, wl_fixed_from_double(delta)); + } else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) { + d->send_axis_stop(resource->handle, d->seat->timestamp(), wlOrientation); } - wl_pointer_send_axis_source(d->resource, wlSource); } - - if (delta != 0.0) { - if (discreteDelta && version >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { - wl_pointer_send_axis_discrete(d->resource, wlOrientation, discreteDelta); - } - wl_pointer_send_axis(d->resource, d->seat->timestamp(), wlOrientation, wl_fixed_from_double(delta)); - } else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) { - wl_pointer_send_axis_stop(d->resource, d->seat->timestamp(), wlOrientation); - } - - d->sendFrame(); } -void PointerInterface::axis(Qt::Orientation orientation, quint32 delta) +void PointerInterface::sendMotion(const QPointF &position) { - Q_D(); - Q_ASSERT(d->focusedSurface); - if (!d->resource) { + d->lastPosition = position; + + if (!d->focusedSurface) { return; } - 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(); + + const auto pointerResources = d->pointersForClient(d->focusedSurface->client()); + for (PointerInterfacePrivate::Resource *resource : pointerResources) { + d->send_motion(resource->handle, d->seat->timestamp(), + wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y())); + } } -void PointerInterface::Private::setCursorCallback(wl_client *client, wl_resource *resource, uint32_t serial, - wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y) +void PointerInterface::sendFrame() { - auto p = cast(resource); - Q_ASSERT(p->client->client() == client); - p->setCursor(serial, SurfaceInterface::get(surface), QPoint(hotspot_x, hotspot_y)); + if (d->focusedSurface) { + d->sendFrame(); + } } Cursor *PointerInterface::cursor() const { - Q_D(); return d->cursor; } -void PointerInterface::relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) +SeatInterface *PointerInterface::seat() const { - Q_D(); - if (d->relativePointersV1.isEmpty()) { - return; - } - for (RelativePointerV1Interface *relativePointer : qAsConst(d->relativePointersV1)) { - relativePointer->send_relative_motion(microseconds >> 32, microseconds & 0xffffffff, - wl_fixed_from_double(delta.width()), - wl_fixed_from_double(delta.height()), - wl_fixed_from_double(deltaNonAccelerated.width()), - wl_fixed_from_double(deltaNonAccelerated.height())); - } - d->sendFrame(); -} - -PointerInterface::Private *PointerInterface::d_func() const -{ - return reinterpret_cast(d.data()); + return d->seat; } PointerInterface *PointerInterface::get(wl_resource *native) { - return Private::get(native); + if (PointerInterfacePrivate *pointerPrivate = resource_cast(native)) { + return pointerPrivate->q; + } + return nullptr; } -Cursor::Private::Private(Cursor *q, PointerInterface *pointer) - : pointer(pointer) - , q(q) +CursorPrivate::CursorPrivate(Cursor *q, PointerInterface *pointer) + : q(q) + , pointer(pointer) { } -void Cursor::Private::update(const QPointer< SurfaceInterface > &s, quint32 serial, const QPoint &p) +void CursorPrivate::update(SurfaceInterface *s, quint32 serial, const QPoint &p) { bool emitChanged = false; if (enteredSerial != serial) { @@ -436,11 +340,13 @@ void Cursor::Private::update(const QPointer< SurfaceInterface > &s, quint32 seri Cursor::Cursor(PointerInterface *parent) : QObject(parent) - , d(new Private(this, parent)) + , d(new CursorPrivate(this, parent)) { } -Cursor::~Cursor() = default; +Cursor::~Cursor() +{ +} quint32 Cursor::enteredSerial() const { @@ -457,7 +363,7 @@ PointerInterface *Cursor::pointer() const return d->pointer; } -QPointer< SurfaceInterface > Cursor::surface() const +SurfaceInterface *Cursor::surface() const { return d->surface; } diff --git a/src/wayland/pointer_interface.h b/src/wayland/pointer_interface.h index b6a3092a3f..f81a449aad 100644 --- a/src/wayland/pointer_interface.h +++ b/src/wayland/pointer_interface.h @@ -1,5 +1,7 @@ /* SPDX-FileCopyrightText: 2014 Martin Gräßlin + SPDX-FileCopyrightText: 2020 Adrien Faveraux + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ @@ -8,93 +10,106 @@ #include -#include "resource.h" +#include + +struct wl_resource; namespace KWaylandServer { +class CursorPrivate; class Cursor; +class PointerInterfacePrivate; class SeatInterface; class SurfaceInterface; enum class PointerAxisSource; /** - * @brief Resource for the wl_pointer interface. - * - * @see SeatInterface - **/ -class KWAYLANDSERVER_EXPORT PointerInterface : public Resource + * The PointerInterface class represents one or more input devices such as mice, which control + * the pointer location. It corresponds to the Wayland interface @c wl_pointer. + */ +class KWAYLANDSERVER_EXPORT PointerInterface : public QObject { Q_OBJECT + public: - virtual ~PointerInterface(); + ~PointerInterface() override; /** - * @returns the focused SurfaceInterface on this pointer resource, if any. - **/ + * Returns the focused pointer surface. Note that the returned value may be different + * from SurfaceInterface::focusedSurfacePointerSurface() because this function returns + * the effective focused surface. + */ SurfaceInterface *focusedSurface() const; - /** - * The Cursor set on this PointerInterface. Might be @c null. - * @since 5.3 - **/ + * Sets the effective focused pointer surface to @a surface. The @a position indicates + * where the pointer has entered the surface. + */ + void setFocusedSurface(SurfaceInterface *surface, const QPointF &position, quint32 serial); + Cursor *cursor() const; + /** + * Returns the seat to which this pointer belongs to. + */ + SeatInterface *seat() const; + /** * @returns The PointerInterface for the @p native resource. - * @since 5.28 - **/ + */ static PointerInterface *get(wl_resource *native); + void sendPressed(quint32 button, quint32 serial); + void sendReleased(quint32 button, quint32 serial); + void sendAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source); + void sendMotion(const QPointF &position); + void sendFrame(); + Q_SIGNALS: /** - * Signal emitted whenever the Cursor changes. - **/ + * This signal is emitted whenever the cursor surface changes. As long as there is no + * any focused surface, the cursor cannot be changed. + */ void cursorChanged(); + /** + * This signal is emitted whenever the focused pointer surface changes. + */ + void focusedSurfaceChanged(); private: - void setFocusedSurface(SurfaceInterface *surface, quint32 serial); - void buttonPressed(quint32 button, quint32 serial); - void buttonReleased(quint32 button, quint32 serial); - void axis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source); - void axis(Qt::Orientation orientation, quint32 delta); - void relativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds); + explicit PointerInterface(SeatInterface *seat); + QScopedPointer d; + friend class SeatInterface; - friend class RelativePointerV1Interface; - friend class PointerPinchGestureV1Interface; - friend class PointerSwipeGestureV1Interface; - explicit PointerInterface(SeatInterface *parent, wl_resource *parentResource); - class Private; - Private *d_func() const; + friend class PointerInterfacePrivate; }; /** * @brief Class encapsulating a Cursor image. - * - * @since 5.3 - **/ + */ class KWAYLANDSERVER_EXPORT Cursor : public QObject { Q_OBJECT + public: virtual ~Cursor(); /** * The hotspot of the cursor image in surface-relative coordinates. - **/ + */ QPoint hotspot() const; /** * The entered serial when the Cursor got set. - **/ + */ quint32 enteredSerial() const; /** * The PointerInterface this Cursor belongs to. - **/ + */ PointerInterface *pointer() const; /** * The SurfaceInterface for the image content of the Cursor. - **/ - QPointer surface() const; + */ + SurfaceInterface *surface() const; Q_SIGNALS: void hotspotChanged(); @@ -103,14 +118,11 @@ Q_SIGNALS: void changed(); private: - friend class PointerInterface; - Cursor(PointerInterface *parent); - class Private; - const QScopedPointer d; + QScopedPointer d; + friend class PointerInterfacePrivate; + explicit Cursor(PointerInterface *parent); }; } -Q_DECLARE_METATYPE(KWaylandServer::PointerInterface*) - #endif diff --git a/src/wayland/pointer_interface_p.h b/src/wayland/pointer_interface_p.h index 911b8c0f50..f731363508 100644 --- a/src/wayland/pointer_interface_p.h +++ b/src/wayland/pointer_interface_p.h @@ -1,68 +1,58 @@ /* SPDX-FileCopyrightText: 2016 Martin Gräßlin + SPDX-FileCopyrightText: 2020 Adrien Faveraux + SPDX-FileCopyrightText: 2021 Vlad Zahorodnii SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #ifndef WAYLAND_SERVER_POINTER_INTERFACE_P_H #define WAYLAND_SERVER_POINTER_INTERFACE_P_H #include "pointer_interface.h" -#include "resource_p.h" +#include #include #include +#include "qwayland-server-wayland.h" + namespace KWaylandServer { + +class ClientConnection; class PointerPinchGestureV1Interface; class PointerSwipeGestureV1Interface; class RelativePointerV1Interface; -class PointerInterface::Private : public Resource::Private +class PointerInterfacePrivate : public QtWaylandServer::wl_pointer { public: - Private(SeatInterface *parent, wl_resource *parentResource, PointerInterface *q); + static PointerInterfacePrivate *get(PointerInterface *pointer); + PointerInterfacePrivate(PointerInterface *q, SeatInterface *seat); + ~PointerInterfacePrivate() override; + + QList pointersForClient(ClientConnection *client) const; + + PointerInterface *q; SeatInterface *seat; SurfaceInterface *focusedSurface = nullptr; - QPointer focusedChildSurface; QMetaObject::Connection destroyConnection; Cursor *cursor = nullptr; - QVector relativePointersV1; - QVector swipeGesturesV1; - QVector pinchGesturesV1; + QScopedPointer relativePointersV1; + QScopedPointer swipeGesturesV1; + QScopedPointer pinchGesturesV1; + QPointF lastPosition; - void sendLeave(SurfaceInterface *surface, quint32 serial); - void sendEnter(SurfaceInterface *surface, const QPointF &parentSurfacePosition, quint32 serial); + void sendLeave(quint32 serial); + void sendEnter(const QPointF &parentSurfacePosition, quint32 serial); void sendFrame(); - void registerRelativePointerV1(RelativePointerV1Interface *relativePointer); - void registerSwipeGestureV1(PointerSwipeGestureV1Interface *gesture); - void registerPinchGestureV1(PointerPinchGestureV1Interface *gesture); - - void unregisterRelativePointerV1(RelativePointerV1Interface *relativePointer); - void unregisterSwipeGestureV1(PointerSwipeGestureV1Interface *gesture); - void unregisterPinchGestureV1(PointerPinchGestureV1Interface *gesture); - - void startSwipeGesture(quint32 serial, quint32 fingerCount); - void updateSwipeGesture(const QSizeF &delta); - void endSwipeGesture(quint32 serial); - void cancelSwipeGesture(quint32 serial); - - void startPinchGesture(quint32 serial, quint32 fingerCount); - void updatePinchGesture(const QSizeF &delta, qreal scale, qreal rotation); - void endPinchGesture(quint32 serial); - void cancelPinchGesture(quint32 serial); - -private: - PointerInterface *q_func() { - return reinterpret_cast(q); - } - void setCursor(quint32 serial, SurfaceInterface *surface, const QPoint &hotspot); - // interface - static void setCursorCallback(wl_client *client, wl_resource *resource, uint32_t serial, - wl_resource *surface, int32_t hotspot_x, int32_t hotspot_y); - - static const struct wl_pointer_interface s_interface; +protected: + void pointer_set_cursor(Resource *resource, uint32_t serial, + ::wl_resource *surface_resource, + int32_t hotspot_x, int32_t hotspot_y) override; + void pointer_release(Resource *resource) override; + void pointer_bind_resource(Resource *resource) override; }; } diff --git a/src/wayland/pointergestures_v1_interface.cpp b/src/wayland/pointergestures_v1_interface.cpp index 17f1f23cd3..19b5f2a874 100644 --- a/src/wayland/pointergestures_v1_interface.cpp +++ b/src/wayland/pointergestures_v1_interface.cpp @@ -6,14 +6,17 @@ */ #include "pointergestures_v1_interface.h" +#include "clientconnection.h" #include "display.h" #include "pointer_interface_p.h" #include "pointergestures_v1_interface_p.h" +#include "seat_interface.h" +#include "surface_interface.h" namespace KWaylandServer { -static const int s_version = 1; +static const int s_version = 2; PointerGesturesV1InterfacePrivate::PointerGesturesV1InterfacePrivate(Display *display) : QtWaylandServer::zwp_pointer_gestures_v1(*display, s_version) @@ -29,14 +32,8 @@ void PointerGesturesV1InterfacePrivate::zwp_pointer_gestures_v1_get_swipe_gestur return; } - wl_resource *swipeResource = wl_resource_create(resource->client(), &zwp_pointer_gesture_swipe_v1_interface, - resource->version(), id); - if (!swipeResource) { - wl_resource_post_no_memory(resource->handle); - return; - } - - new PointerSwipeGestureV1Interface(pointer, swipeResource); + PointerSwipeGestureV1Interface *swipeGesture = PointerSwipeGestureV1Interface::get(pointer); + swipeGesture->add(resource->client(), id, resource->version()); } void PointerGesturesV1InterfacePrivate::zwp_pointer_gestures_v1_get_pinch_gesture(Resource *resource, uint32_t id, struct ::wl_resource *pointer_resource) @@ -48,14 +45,8 @@ void PointerGesturesV1InterfacePrivate::zwp_pointer_gestures_v1_get_pinch_gestur return; } - wl_resource *pinchResource = wl_resource_create(resource->client(), &zwp_pointer_gesture_pinch_v1_interface, - resource->version(), id); - if (!pinchResource) { - wl_resource_post_no_memory(resource->handle); - return; - } - - new PointerPinchGestureV1Interface(pointer, pinchResource); + PointerPinchGestureV1Interface *pinchGesture = PointerPinchGestureV1Interface::get(pointer); + pinchGesture->add(resource->client(), id, resource->version()); } void PointerGesturesV1InterfacePrivate::zwp_pointer_gestures_v1_release(Resource *resource) @@ -73,25 +64,18 @@ PointerGesturesV1Interface::~PointerGesturesV1Interface() { } -PointerSwipeGestureV1Interface::PointerSwipeGestureV1Interface(PointerInterface *pointer, - ::wl_resource *resource) - : QtWaylandServer::zwp_pointer_gesture_swipe_v1(resource) - , pointer(pointer) +PointerSwipeGestureV1Interface::PointerSwipeGestureV1Interface(PointerInterface *pointer) + : pointer(pointer) { - pointer->d_func()->registerSwipeGestureV1(this); } -PointerSwipeGestureV1Interface::~PointerSwipeGestureV1Interface() +PointerSwipeGestureV1Interface *PointerSwipeGestureV1Interface::get(PointerInterface *pointer) { if (pointer) { - pointer->d_func()->unregisterSwipeGestureV1(this); + PointerInterfacePrivate *pointerPrivate = PointerInterfacePrivate::get(pointer); + return pointerPrivate->swipeGesturesV1.data(); } -} - -void PointerSwipeGestureV1Interface::zwp_pointer_gesture_swipe_v1_destroy_resource(Resource *resource) -{ - Q_UNUSED(resource) - delete this; + return nullptr; } void PointerSwipeGestureV1Interface::zwp_pointer_gesture_swipe_v1_destroy(Resource *resource) @@ -99,25 +83,94 @@ void PointerSwipeGestureV1Interface::zwp_pointer_gesture_swipe_v1_destroy(Resour wl_resource_destroy(resource->handle); } -PointerPinchGestureV1Interface::PointerPinchGestureV1Interface(PointerInterface *pointer, - ::wl_resource *resource) - : QtWaylandServer::zwp_pointer_gesture_pinch_v1(resource) - , pointer(pointer) +void PointerSwipeGestureV1Interface::sendBegin(quint32 serial, quint32 fingerCount) { - pointer->d_func()->registerPinchGestureV1(this); -} + if (focusedClient) { + return; + } + if (!pointer->focusedSurface()) { + return; + } -PointerPinchGestureV1Interface::~PointerPinchGestureV1Interface() -{ - if (pointer) { - pointer->d_func()->unregisterPinchGestureV1(this); + const SurfaceInterface *focusedSurface = pointer->focusedSurface(); + focusedClient = focusedSurface->client(); + SeatInterface *seat = pointer->seat(); + + const QList swipeResources = resourceMap().values(focusedClient->client()); + for (Resource *swipeResource : swipeResources) { + if (swipeResource->client() == focusedClient->client()) { + send_begin(swipeResource->handle, serial, seat->timestamp(), focusedSurface->resource(), fingerCount); + } } } -void PointerPinchGestureV1Interface::zwp_pointer_gesture_pinch_v1_destroy_resource(Resource *resource) +void PointerSwipeGestureV1Interface::sendUpdate(const QSizeF &delta) { - Q_UNUSED(resource) - delete this; + if (!focusedClient) { + return; + } + + SeatInterface *seat = pointer->seat(); + + const QList swipeResources = resourceMap().values(focusedClient->client()); + for (Resource *swipeResource : swipeResources) { + if (swipeResource->client() == focusedClient->client()) { + send_update(swipeResource->handle, seat->timestamp(), + wl_fixed_from_double(delta.width()), wl_fixed_from_double(delta.height())); + } + } +} + +void PointerSwipeGestureV1Interface::sendEnd(quint32 serial) +{ + if (!focusedClient) { + return; + } + + SeatInterface *seat = pointer->seat(); + + const QList swipeResources = resourceMap().values(focusedClient->client()); + for (Resource *swipeResource : swipeResources) { + if (swipeResource->client() == focusedClient->client()) { + send_end(swipeResource->handle, serial, seat->timestamp(), false); + } + } + + // The gesture session has been just finished, reset the cached focused client. + focusedClient = nullptr; +} + +void PointerSwipeGestureV1Interface::sendCancel(quint32 serial) +{ + if (!focusedClient) { + return; + } + + SeatInterface *seat = pointer->seat(); + + const QList swipeResources = resourceMap().values(focusedClient->client()); + for (Resource *swipeResource : swipeResources) { + if (swipeResource->client() == focusedClient->client()) { + send_end(swipeResource->handle, serial, seat->timestamp(), true); + } + } + + // The gesture session has been just finished, reset the cached focused client. + focusedClient = nullptr; +} + +PointerPinchGestureV1Interface::PointerPinchGestureV1Interface(PointerInterface *pointer) + : pointer(pointer) +{ +} + +PointerPinchGestureV1Interface *PointerPinchGestureV1Interface::get(PointerInterface *pointer) +{ + if (pointer) { + PointerInterfacePrivate *pointerPrivate = PointerInterfacePrivate::get(pointer); + return pointerPrivate->pinchGesturesV1.data(); + } + return nullptr; } void PointerPinchGestureV1Interface::zwp_pointer_gesture_pinch_v1_destroy(Resource *resource) @@ -125,4 +178,81 @@ void PointerPinchGestureV1Interface::zwp_pointer_gesture_pinch_v1_destroy(Resour wl_resource_destroy(resource->handle); } +void PointerPinchGestureV1Interface::sendBegin(quint32 serial, quint32 fingerCount) +{ + if (focusedClient) { + return; // gesture is already active + } + if (!pointer->focusedSurface()) { + return; + } + + const SurfaceInterface *focusedSurface = pointer->focusedSurface(); + focusedClient = focusedSurface->client(); + SeatInterface *seat = pointer->seat(); + + const QList pinchResources = resourceMap().values(*focusedClient); + for (Resource *pinchResource : pinchResources) { + if (pinchResource->client() == focusedClient->client()) { + send_begin(pinchResource->handle, serial, seat->timestamp(), focusedSurface->resource(), fingerCount); + } + } +} + +void PointerPinchGestureV1Interface::sendUpdate(const QSizeF &delta, qreal scale, qreal rotation) +{ + if (!focusedClient) { + return; + } + + SeatInterface *seat = pointer->seat(); + + const QList pinchResources = resourceMap().values(*focusedClient); + for (Resource *pinchResource : pinchResources) { + if (pinchResource->client() == focusedClient->client()) { + send_update(pinchResource->handle, seat->timestamp(), + wl_fixed_from_double(delta.width()), wl_fixed_from_double(delta.height()), + wl_fixed_from_double(scale), wl_fixed_from_double(rotation)); + } + } +} + +void PointerPinchGestureV1Interface::sendEnd(quint32 serial) +{ + if (!focusedClient) { + return; + } + + SeatInterface *seat = pointer->seat(); + + const QList pinchResources = resourceMap().values(*focusedClient); + for (Resource *pinchResource : pinchResources) { + if (pinchResource->client() == focusedClient->client()) { + send_end(pinchResource->handle, serial, seat->timestamp(), false); + } + } + + // The gesture session has been just finished, reset the cached focused client. + focusedClient = nullptr; +} + +void PointerPinchGestureV1Interface::sendCancel(quint32 serial) +{ + if (!focusedClient) { + return; + } + + SeatInterface *seat = pointer->seat(); + + const QList pinchResources = resourceMap().values(*focusedClient); + for (Resource *pinchResource : pinchResources) { + if (pinchResource->client() == focusedClient->client()) { + send_end(pinchResource->handle, serial, seat->timestamp(), true); + } + } + + // The gesture session has been just finished, reset the cached focused client. + focusedClient = nullptr; +} + } // namespace KWaylandServer diff --git a/src/wayland/pointergestures_v1_interface_p.h b/src/wayland/pointergestures_v1_interface_p.h index 37ed456627..9bde74a771 100644 --- a/src/wayland/pointergestures_v1_interface_p.h +++ b/src/wayland/pointergestures_v1_interface_p.h @@ -14,8 +14,10 @@ namespace KWaylandServer { +class ClientConnection; class Display; class PointerInterface; +class SurfaceInterface; class PointerGesturesV1InterfacePrivate : public QtWaylandServer::zwp_pointer_gestures_v1 { @@ -33,27 +35,41 @@ protected: class PointerSwipeGestureV1Interface : public QtWaylandServer::zwp_pointer_gesture_swipe_v1 { public: - PointerSwipeGestureV1Interface(PointerInterface *pointer, ::wl_resource *resource); - ~PointerSwipeGestureV1Interface() override; + explicit PointerSwipeGestureV1Interface(PointerInterface *pointer); - QPointer pointer; + static PointerSwipeGestureV1Interface *get(PointerInterface *pointer); + + void sendBegin(quint32 serial, quint32 fingerCount); + void sendUpdate(const QSizeF &delta); + void sendEnd(quint32 serial); + void sendCancel(quint32 serial); protected: - void zwp_pointer_gesture_swipe_v1_destroy_resource(Resource *resource) override; void zwp_pointer_gesture_swipe_v1_destroy(Resource *resource) override; + +private: + PointerInterface *pointer; + QPointer focusedClient; }; class PointerPinchGestureV1Interface : public QtWaylandServer::zwp_pointer_gesture_pinch_v1 { public: - PointerPinchGestureV1Interface(PointerInterface *pointer, ::wl_resource *resource); - ~PointerPinchGestureV1Interface() override; + explicit PointerPinchGestureV1Interface(PointerInterface *pointer); - QPointer pointer; + static PointerPinchGestureV1Interface *get(PointerInterface *pointer); + + void sendBegin(quint32 serial, quint32 fingerCount); + void sendUpdate(const QSizeF &delta, qreal scale, qreal rotation); + void sendEnd(quint32 serial); + void sendCancel(quint32 serial); protected: - void zwp_pointer_gesture_pinch_v1_destroy_resource(Resource *resource) override; void zwp_pointer_gesture_pinch_v1_destroy(Resource *resource) override; + +private: + PointerInterface *pointer; + QPointer focusedClient; }; } // namespace KWaylandServer diff --git a/src/wayland/relativepointer_v1_interface.cpp b/src/wayland/relativepointer_v1_interface.cpp index 3973477f9e..a9cba272c3 100644 --- a/src/wayland/relativepointer_v1_interface.cpp +++ b/src/wayland/relativepointer_v1_interface.cpp @@ -6,9 +6,12 @@ */ #include "relativepointer_v1_interface.h" +#include "clientconnection.h" #include "display.h" #include "pointer_interface_p.h" #include "relativepointer_v1_interface_p.h" +#include "seat_interface.h" +#include "surface_interface.h" namespace KWaylandServer { @@ -34,15 +37,8 @@ void RelativePointerManagerV1InterfacePrivate::zwp_relative_pointer_manager_v1_g return; } - wl_resource *relativePointerResource = wl_resource_create(resource->client(), - &zwp_relative_pointer_v1_interface, - resource->version(), id); - if (!relativePointerResource) { - wl_resource_post_no_memory(resource->handle); - return; - } - - new RelativePointerV1Interface(pointer, relativePointerResource); + RelativePointerV1Interface *relativePointer = RelativePointerV1Interface::get(pointer); + relativePointer->add(resource->client(), id, resource->version()); } RelativePointerManagerV1Interface::RelativePointerManagerV1Interface(Display *display, QObject *parent) @@ -55,24 +51,18 @@ RelativePointerManagerV1Interface::~RelativePointerManagerV1Interface() { } -RelativePointerV1Interface::RelativePointerV1Interface(PointerInterface *pointer, ::wl_resource *resource) - : QtWaylandServer::zwp_relative_pointer_v1(resource) - , pointer(pointer) +RelativePointerV1Interface::RelativePointerV1Interface(PointerInterface *pointer) + : pointer(pointer) { - pointer->d_func()->registerRelativePointerV1(this); } -RelativePointerV1Interface::~RelativePointerV1Interface() +RelativePointerV1Interface *RelativePointerV1Interface::get(PointerInterface *pointer) { if (pointer) { - pointer->d_func()->unregisterRelativePointerV1(this); + PointerInterfacePrivate *pointerPrivate = PointerInterfacePrivate::get(pointer); + return pointerPrivate->relativePointersV1.data(); } -} - -void RelativePointerV1Interface::zwp_relative_pointer_v1_destroy_resource(Resource *resource) -{ - Q_UNUSED(resource) - delete this; + return nullptr; } void RelativePointerV1Interface::zwp_relative_pointer_v1_destroy(Resource *resource) @@ -80,4 +70,24 @@ void RelativePointerV1Interface::zwp_relative_pointer_v1_destroy(Resource *resou wl_resource_destroy(resource->handle); } +void RelativePointerV1Interface::sendRelativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) +{ + if (!pointer->focusedSurface()) { + return; + } + + ClientConnection *focusedClient = pointer->focusedSurface()->client(); + const QList pointerResources = resourceMap().values(focusedClient->client()); + for (Resource *pointerResource : pointerResources) { + if (pointerResource->client() == focusedClient->client()) { + send_relative_motion(pointerResource->handle, microseconds >> 32, microseconds & 0xffffffff, + wl_fixed_from_double(delta.width()), + wl_fixed_from_double(delta.height()), + wl_fixed_from_double(deltaNonAccelerated.width()), + wl_fixed_from_double(deltaNonAccelerated.height())); + + } + } +} + } // namespace KWaylandServer diff --git a/src/wayland/relativepointer_v1_interface_p.h b/src/wayland/relativepointer_v1_interface_p.h index e39e0197e5..73e70850eb 100644 --- a/src/wayland/relativepointer_v1_interface_p.h +++ b/src/wayland/relativepointer_v1_interface_p.h @@ -9,11 +9,10 @@ #include "qwayland-server-relative-pointer-unstable-v1.h" -#include - namespace KWaylandServer { +class ClientConnection; class Display; class PointerInterface; @@ -31,14 +30,16 @@ protected: class RelativePointerV1Interface : public QtWaylandServer::zwp_relative_pointer_v1 { public: - RelativePointerV1Interface(PointerInterface *pointer, ::wl_resource *resource); - ~RelativePointerV1Interface() override; + explicit RelativePointerV1Interface(PointerInterface *pointer); - QPointer pointer; + static RelativePointerV1Interface *get(PointerInterface *pointer); + void sendRelativeMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds); protected: - void zwp_relative_pointer_v1_destroy_resource(Resource *resource) override; void zwp_relative_pointer_v1_destroy(Resource *resource) override; + +private: + PointerInterface *pointer; }; } // namespace KWaylandServer diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index 94e6444c74..dd18056123 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -17,10 +17,13 @@ #include "keyboard_interface.h" #include "keyboard_interface_p.h" #include "logging.h" +#include "pointerconstraints_v1_interface.h" +#include "pointergestures_v1_interface_p.h" #include "pointer_interface.h" #include "pointer_interface_p.h" #include "primaryselectiondevice_v1_interface.h" #include "primaryselectionsource_v1_interface.h" +#include "relativepointer_v1_interface_p.h" #include "surface_interface.h" #include "textinput_v2_interface_p.h" #include "textinput_v3_interface_p.h" @@ -233,11 +236,6 @@ bool forEachInterface(SurfaceInterface *surface, const QVector &interfaces, } -QVector SeatInterface::Private::pointersForSurface(SurfaceInterface *surface) const -{ - return interfacesForSurface(surface, pointers); -} - QVector SeatInterface::Private::touchsForSurface(SurfaceInterface *surface) const { return interfacesForSurface(surface, touchs); @@ -282,7 +280,6 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice) auto *dragSurface = dataDevice->origin(); if (q->hasImplicitPointerGrab(dragSerial)) { drag.mode = Drag::Mode::Pointer; - drag.sourcePointer = interfaceForSurface(dragSurface, pointers); drag.transformation = globalPointer.focus.transformation; } else if (q->hasImplicitTouchGrab(dragSerial)) { drag.mode = Drag::Mode::Touch; @@ -302,7 +299,6 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice) drag.transformation = globalPointer.focus.transformation; } drag.source = dataDevice; - drag.sourcePointer = interfaceForSurface(originSurface, pointers); drag.destroyConnection = QObject::connect(dataDevice, &DataDeviceInterface::aboutToBeDestroyed, q, [this] { cancelDrag(display->nextSerial()); @@ -479,10 +475,15 @@ void SeatInterface::setHasKeyboard(bool has) void SeatInterface::setHasPointer(bool has) { Q_D(); - if (d->pointer == has) { + if (d->pointer.isNull() != has) { return; } - d->pointer = has; + if (has) { + d->pointer.reset(new PointerInterface(this)); + } else { + d->pointer.reset(); + } + emit hasPointerChanged(d->pointer); } @@ -513,37 +514,10 @@ void SeatInterface::Private::getPointerCallback(wl_client *client, wl_resource * void SeatInterface::Private::getPointer(wl_client *client, wl_resource *resource, uint32_t id) { - // TODO: only create if seat has pointer? - PointerInterface *pointer = new PointerInterface(q, resource); - auto clientConnection = display->getConnection(client); - pointer->create(clientConnection, qMin(wl_resource_get_version(resource), s_pointerVersion), id); - if (!pointer->resource()) { - wl_resource_post_no_memory(resource); - delete pointer; - return; + if (pointer) { + PointerInterfacePrivate *pointerPrivate = PointerInterfacePrivate::get(pointer.data()); + pointerPrivate->add(client, id, wl_resource_get_version(resource)); } - pointers << pointer; - if (globalPointer.focus.surface && globalPointer.focus.surface->client() == clientConnection) { - // 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); - } - } - QObject::connect(pointer, &QObject::destroyed, q, - [pointer,this] { - pointers.removeAt(pointers.indexOf(pointer)); - if (globalPointer.focus.pointers.removeOne(pointer)) { - if (globalPointer.focus.pointers.isEmpty()) { - emit q->focusedPointerChanged(nullptr); - } - } - } - ); - emit q->pointerCreated(pointer); } void SeatInterface::Private::getKeyboardCallback(wl_client *client, wl_resource *resource, uint32_t id) @@ -642,6 +616,37 @@ void SeatInterface::setPointerPos(const QPointF &pos) } d->globalPointer.pos = pos; emit pointerPosChanged(pos); + + SurfaceInterface *focusedSurface = focusedPointerSurface(); + if (!focusedSurface) { + return; + } + if (isDragPointer()) { + const auto *originSurface = dragSource()->origin(); + const bool proxyRemoteFocused = originSurface->dataProxy() && originSurface == focusedSurface; + if (!proxyRemoteFocused) { + // handled by DataDevice + return; + } + } + if (focusedSurface->lockedPointer() && focusedSurface->lockedPointer()->isLocked()) { + return; + } + + QPointF localPosition = focusedPointerSurfaceTransformation().map(pos); + SurfaceInterface *effectiveFocusedSurface = focusedSurface->inputSurfaceAt(localPosition); + if (!effectiveFocusedSurface) { + effectiveFocusedSurface = focusedSurface; + } + if (focusedSurface != effectiveFocusedSurface) { + localPosition = focusedSurface->mapToChild(effectiveFocusedSurface, localPosition); + } + + if (d->pointer->focusedSurface() != effectiveFocusedSurface) { + d->pointer->setFocusedSurface(effectiveFocusedSurface, localPosition, display()->nextSerial()); + } + + d->pointer->sendMotion(localPosition); } quint32 SeatInterface::timestamp() const @@ -683,6 +688,7 @@ void SeatInterface::setDragTarget(SurfaceInterface *surface, const QPointF &glob if (d->drag.mode == Private::Drag::Mode::Pointer) { setPointerPos(globalPosition); + pointerFrame(); } else if (d->drag.mode == Private::Drag::Mode::Touch && d->globalTouch.focus.firstTouchPos != globalPosition) { touchMove(d->globalTouch.ids.first(), globalPosition); @@ -734,58 +740,37 @@ void SeatInterface::setFocusedPointerSurface(SurfaceInterface *surface, const QM // ignore 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); } d->globalPointer.focus = Private::Pointer::Focus(); d->globalPointer.focus.surface = surface; - auto p = d->pointersForSurface(surface); - d->globalPointer.focus.pointers = p; if (d->globalPointer.focus.surface) { - d->globalPointer.focus.destroyConnection = connect(surface, &QObject::destroyed, this, - [this] { - Q_D(); - d->globalPointer.focus = Private::Pointer::Focus(); - emit focusedPointerChanged(nullptr); - } - ); - d->globalPointer.focus.offset = QPointF(); - d->globalPointer.focus.transformation = transformation; + d->globalPointer.focus.destroyConnection = connect(surface, &QObject::destroyed, this, [this] { + Q_D(); + d->globalPointer.focus = Private::Pointer::Focus(); + }); d->globalPointer.focus.serial = serial; + d->globalPointer.focus.transformation = transformation; + d->globalPointer.focus.offset = QPointF(); } - 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(); - } -} -PointerInterface *SeatInterface::focusedPointer() const -{ - Q_D(); - if (d->globalPointer.focus.pointers.isEmpty()) { - return nullptr; + if (surface) { + QPointF localPosition = focusedPointerSurfaceTransformation().map(pointerPos()); + SurfaceInterface *effectiveFocusedSurface = surface->inputSurfaceAt(localPosition); + if (!effectiveFocusedSurface) { + effectiveFocusedSurface = surface; + } + if (surface != effectiveFocusedSurface) { + localPosition = surface->mapToChild(effectiveFocusedSurface, localPosition); + } + d->pointer->setFocusedSurface(effectiveFocusedSurface, localPosition, serial); + } else { + d->pointer->setFocusedSurface(nullptr, QPointF(), serial); } - return d->globalPointer.focus.pointers.first(); } void SeatInterface::setFocusedPointerSurfacePosition(const QPointF &surfacePosition) @@ -818,6 +803,12 @@ QMatrix4x4 SeatInterface::focusedPointerSurfaceTransformation() const return d->globalPointer.focus.transformation; } +PointerInterface *SeatInterface::pointer() const +{ + Q_D(); + return d->pointer.data(); +} + namespace { static quint32 qtToWaylandButton(Qt::MouseButton button) { @@ -863,32 +854,15 @@ bool SeatInterface::isPointerButtonPressed(quint32 button) const return it.value() == Private::Pointer::State::Pressed ? true : false; } -void SeatInterface::pointerAxisV5(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source) +void SeatInterface::pointerAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source) { Q_D(); + Q_ASSERT(d->pointer); if (d->drag.mode == Private::Drag::Mode::Pointer) { // ignore return; } - if (d->globalPointer.focus.surface) { - for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) { - (*it)->axis(orientation, delta, discreteDelta, source); - } - } -} - -void SeatInterface::pointerAxis(Qt::Orientation orientation, quint32 delta) -{ - Q_D(); - if (d->drag.mode == Private::Drag::Mode::Pointer) { - // ignore - return; - } - if (d->globalPointer.focus.surface) { - for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) { - (*it)->axis(orientation, delta); - } - } + d->pointer->sendAxis(orientation, delta, discreteDelta, source); } void SeatInterface::pointerButtonPressed(Qt::MouseButton button) @@ -903,6 +877,7 @@ void SeatInterface::pointerButtonPressed(Qt::MouseButton button) void SeatInterface::pointerButtonPressed(quint32 button) { Q_D(); + Q_ASSERT(d->pointer); const quint32 serial = d->display->nextSerial(); d->updatePointerButtonSerial(button, serial); d->updatePointerButtonState(button, Private::Pointer::State::Pressed); @@ -910,16 +885,11 @@ void SeatInterface::pointerButtonPressed(quint32 button) // ignore return; } - if (auto *focusSurface = d->globalPointer.focus.surface) { - for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) { - (*it)->buttonPressed(button, serial); - } - if (focusSurface == d->globalKeyboard.focus.surface) { - // update the focused child surface - auto p = focusedPointer(); - if (p && d->keyboard) { - d->keyboard->d->focusChildSurface(p->d_func()->focusedChildSurface, serial); - } + d->pointer->sendPressed(button, serial); + + if (focusedPointerSurface() == focusedKeyboardSurface()) { + if (d->keyboard) { + d->keyboard->setFocusedSurface(d->pointer->focusedSurface(), serial); } } } @@ -936,6 +906,7 @@ void SeatInterface::pointerButtonReleased(Qt::MouseButton button) void SeatInterface::pointerButtonReleased(quint32 button) { Q_D(); + Q_ASSERT(d->pointer); const quint32 serial = d->display->nextSerial(); const quint32 currentButtonSerial = pointerButtonSerial(button); d->updatePointerButtonSerial(button, serial); @@ -948,11 +919,14 @@ void SeatInterface::pointerButtonReleased(quint32 button) d->endDrag(serial); return; } - if (d->globalPointer.focus.surface) { - for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) { - (*it)->buttonReleased(button, serial); - } - } + d->pointer->sendReleased(button, serial); +} + +void SeatInterface::pointerFrame() +{ + Q_D(); + Q_ASSERT(d->pointer); + d->pointer->sendFrame(); } quint32 SeatInterface::pointerButtonSerial(Qt::MouseButton button) const @@ -973,133 +947,100 @@ quint32 SeatInterface::pointerButtonSerial(quint32 button) const void SeatInterface::relativePointerMotion(const QSizeF &delta, const QSizeF &deltaNonAccelerated, quint64 microseconds) { Q_D(); - if (d->globalPointer.focus.surface) { - for (auto it = d->globalPointer.focus.pointers.constBegin(), end = d->globalPointer.focus.pointers.constEnd(); it != end; ++it) { - (*it)->relativeMotion(delta, deltaNonAccelerated, microseconds); - } + Q_ASSERT(d->pointer); + + auto relativePointer = RelativePointerV1Interface::get(pointer()); + if (relativePointer) { + relativePointer->sendRelativeMotion(delta, deltaNonAccelerated, microseconds); } } void SeatInterface::startPointerSwipeGesture(quint32 fingerCount) { Q_D(); - if (!d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer()); + if (swipeGesture) { + swipeGesture->sendBegin(d->display->nextSerial(), fingerCount); } - d->globalPointer.gestureSurface = QPointer(d->globalPointer.focus.surface); - if (d->globalPointer.gestureSurface.isNull()) { - return; - } - const quint32 serial = d->display->nextSerial(); - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [serial, fingerCount] (PointerInterface *p) { - p->d_func()->startSwipeGesture(serial, fingerCount); - } - ); } void SeatInterface::updatePointerSwipeGesture(const QSizeF &delta) { Q_D(); - if (d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer()); + if (swipeGesture) { + swipeGesture->sendUpdate(delta); } - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [delta] (PointerInterface *p) { - p->d_func()->updateSwipeGesture(delta); - } - ); } void SeatInterface::endPointerSwipeGesture() { Q_D(); - if (d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer()); + if (swipeGesture) { + swipeGesture->sendEnd(d->display->nextSerial()); } - const quint32 serial = d->display->nextSerial(); - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [serial] (PointerInterface *p) { - p->d_func()->endSwipeGesture(serial); - } - ); - d->globalPointer.gestureSurface.clear(); } void SeatInterface::cancelPointerSwipeGesture() { Q_D(); - if (d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto swipeGesture = PointerSwipeGestureV1Interface::get(pointer()); + if (swipeGesture) { + swipeGesture->sendCancel(d->display->nextSerial()); } - const quint32 serial = d->display->nextSerial(); - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [serial] (PointerInterface *p) { - p->d_func()->cancelSwipeGesture(serial); - } - ); - d->globalPointer.gestureSurface.clear(); } void SeatInterface::startPointerPinchGesture(quint32 fingerCount) { Q_D(); - if (!d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto pinchGesture = PointerPinchGestureV1Interface::get(pointer()); + if (pinchGesture) { + pinchGesture->sendBegin(d->display->nextSerial(), fingerCount); } - d->globalPointer.gestureSurface = QPointer(d->globalPointer.focus.surface); - if (d->globalPointer.gestureSurface.isNull()) { - return; - } - const quint32 serial = d->display->nextSerial(); - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [serial, fingerCount] (PointerInterface *p) { - p->d_func()->startPinchGesture(serial, fingerCount); - } - ); } void SeatInterface::updatePointerPinchGesture(const QSizeF &delta, qreal scale, qreal rotation) { Q_D(); - if (d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto pinchGesture = PointerPinchGestureV1Interface::get(pointer()); + if (pinchGesture) { + pinchGesture->sendUpdate(delta, scale, rotation); } - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [delta, scale, rotation] (PointerInterface *p) { - p->d_func()->updatePinchGesture(delta, scale, rotation); - } - ); } void SeatInterface::endPointerPinchGesture() { Q_D(); - if (d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto pinchGesture = PointerPinchGestureV1Interface::get(pointer()); + if (pinchGesture) { + pinchGesture->sendEnd(d->display->nextSerial()); } - const quint32 serial = d->display->nextSerial(); - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [serial] (PointerInterface *p) { - p->d_func()->endPinchGesture(serial); - } - ); - d->globalPointer.gestureSurface.clear(); } void SeatInterface::cancelPointerPinchGesture() { Q_D(); - if (d->globalPointer.gestureSurface.isNull()) { - return; + Q_ASSERT(d->pointer); + + auto pinchGesture = PointerPinchGestureV1Interface::get(pointer()); + if (pinchGesture) { + pinchGesture->sendCancel(d->display->nextSerial()); } - const quint32 serial = d->display->nextSerial(); - forEachInterface(d->globalPointer.gestureSurface.data(), d->pointers, - [serial] (PointerInterface *p) { - p->d_func()->cancelPinchGesture(serial); - } - ); - d->globalPointer.gestureSurface.clear(); } SurfaceInterface *SeatInterface::focusedKeyboardSurface() const @@ -1267,18 +1208,9 @@ void SeatInterface::touchDown(qint32 id, const QPointF &globalPosition) if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { // If the client did not bind the touch interface fall back // to at least emulating touch through pointer events. - forEachInterface(focusedTouchSurface(), d->pointers, - [this, pos, serial] (PointerInterface *p) { - wl_pointer_send_enter(p->resource(), serial, - focusedTouchSurface()->resource(), - wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); - wl_pointer_send_motion(p->resource(), timestamp(), - 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(); - } - ); + d->pointer->setFocusedSurface(focusedTouchSurface(), pos, serial); + d->pointer->sendMotion(pos); + d->pointer->sendFrame(); } #endif @@ -1300,13 +1232,8 @@ void SeatInterface::touchMove(qint32 id, const QPointF &globalPosition) if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { // Client did not bind touch, fall back to emulating with pointer events. - forEachInterface(focusedTouchSurface(), d->pointers, - [this, pos] (PointerInterface *p) { - wl_pointer_send_motion(p->resource(), timestamp(), - wl_fixed_from_double(pos.x()), wl_fixed_from_double(pos.y())); - p->d_func()->sendFrame(); - } - ); + d->pointer->sendMotion(pos); + d->pointer->sendFrame(); } emit touchMoved(id, d->globalTouch.ids[id], globalPosition); } @@ -1329,12 +1256,8 @@ void SeatInterface::touchUp(qint32 id) if (id == 0 && d->globalTouch.focus.touchs.isEmpty()) { // Client did not bind touch, fall back to emulating with pointer events. const quint32 serial = display()->nextSerial(); - forEachInterface(focusedTouchSurface(), d->pointers, - [this, serial] (PointerInterface *p) { - wl_pointer_send_button(p->resource(), serial, timestamp(), BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED); - p->d_func()->sendFrame(); - } - ); + d->pointer->sendReleased(BTN_LEFT, serial); + d->pointer->sendFrame(); } #endif @@ -1401,16 +1324,6 @@ SurfaceInterface *SeatInterface::dragSurface() const return d->drag.surface; } -PointerInterface *SeatInterface::dragPointer() const -{ - Q_D(); - if (d->drag.mode != Private::Drag::Mode::Pointer) { - return nullptr; - } - - return d->drag.sourcePointer; -} - DataDeviceInterface *SeatInterface::dragSource() const { Q_D(); diff --git a/src/wayland/seat_interface.h b/src/wayland/seat_interface.h index bbb323290c..7801919323 100644 --- a/src/wayland/seat_interface.h +++ b/src/wayland/seat_interface.h @@ -90,10 +90,13 @@ enum class PointerAxisSource { * seat->setFocusedPointerSurface(surface, QPointF(100, 200)); // surface at it's global position * seat->setTimestamp(100); * seat->setPointerPos(QPointF(350, 210)); // global pos, local pos in surface: 250,10 + * seat->pointerFrame(); * seat->setTimestamp(110); * seat->pointerButtonPressed(Qt::LeftButton); + * seat->pointerFrame(); * seat->setTimestamp(120); * seat->pointerButtonReleased(Qt::LeftButton); + * seat->pointerFrame(); * @endcode * * @see KeyboardInterface @@ -190,12 +193,6 @@ public: * @see dragSurfaceChanged **/ SurfaceInterface *dragSurface() const; - /** - * @returns The PointerInterface which triggered the drag operation - * @since 5.6 - * @see isDragPointer - **/ - PointerInterface *dragPointer() const; /** * @returns The DataDeviceInterface which started the drag and drop operation. * @see isDrag @@ -291,11 +288,7 @@ public: * @see setFocusedPointerSurface **/ SurfaceInterface *focusedPointerSurface() const; - /** - * @returns The PointerInterface belonging to the focused pointer surface, if any. - * @see setFocusedPointerSurface - **/ - PointerInterface *focusedPointer() const; + PointerInterface *pointer() const; /** * Updates the global position of the currently focused pointer surface. * @@ -348,6 +341,7 @@ public: * @overload **/ void pointerButtonPressed(Qt::MouseButton button); + void pointerFrame(); /** * Marks the @p button as released. * @@ -384,13 +378,8 @@ public: * @param discreteDelta The number of discrete steps, e.g. mouse wheel clicks. * @param source Describes how the axis event was physically generated. * @since 5.59 - * @todo Drop V5 suffix with KF6. **/ - void pointerAxisV5(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source); - /** - * @see pointerAxisV5 - **/ - void pointerAxis(Qt::Orientation orientation, quint32 delta); + void pointerAxis(Qt::Orientation orientation, qreal delta, qint32 discreteDelta, PointerAxisSource source); /** * @returns true if there is a pressed button with the given @p serial * @since 5.6 @@ -664,16 +653,9 @@ Q_SIGNALS: void touchMoved(qint32 id, quint32 serial, const QPointF &globalPosition); void timestampChanged(quint32); - void pointerCreated(KWaylandServer::PointerInterface*); void keyboardCreated(KWaylandServer::KeyboardInterface*); void touchCreated(KWaylandServer::TouchInterface*); - /** - * Emitted whenever the focused pointer changes - * @since 5.6 - **/ - void focusedPointerChanged(KWaylandServer::PointerInterface*); - /** * Emitted whenever the selection changes * @since 5.56 diff --git a/src/wayland/seat_interface_p.h b/src/wayland/seat_interface_p.h index 4882984b70..d1ec9e637e 100644 --- a/src/wayland/seat_interface_p.h +++ b/src/wayland/seat_interface_p.h @@ -34,7 +34,6 @@ public: void bind(wl_client *client, uint32_t version, uint32_t id) override; void sendCapabilities(wl_resource *r); void sendName(wl_resource *r); - QVector pointersForSurface(SurfaceInterface *surface) const; QVector touchsForSurface(SurfaceInterface *surface) const; QVector dataDevicesForSurface(SurfaceInterface *surface) const; void registerPrimarySelectionDevice(PrimarySelectionDeviceV1Interface *primarySelectionDevice); @@ -45,12 +44,11 @@ public: quint32 nextSerial() const; QString name; - bool pointer = false; bool touch = false; QList resources; quint32 timestamp = 0; - QVector pointers; QScopedPointer keyboard; + QScopedPointer pointer; QVector touchs; QVector dataDevices; QVector primarySelectionDevices; @@ -78,14 +76,12 @@ public: QPointF pos; struct Focus { SurfaceInterface *surface = nullptr; - QVector pointers; QMetaObject::Connection destroyConnection; QPointF offset = QPointF(); QMatrix4x4 transformation; quint32 serial = 0; }; Focus focus; - QPointer gestureSurface; }; Pointer globalPointer; void updatePointerButtonSerial(quint32 button, quint32 serial); @@ -128,7 +124,6 @@ public: DataDeviceInterface *source = nullptr; QPointer target; SurfaceInterface *surface = nullptr; - PointerInterface *sourcePointer = nullptr; TouchInterface *sourceTouch = nullptr; QMatrix4x4 transformation; QMetaObject::Connection destroyConnection; diff --git a/src/wayland/tests/renderingservertest.cpp b/src/wayland/tests/renderingservertest.cpp index f4687e97b2..7bbe421aab 100644 --- a/src/wayland/tests/renderingservertest.cpp +++ b/src/wayland/tests/renderingservertest.cpp @@ -191,6 +191,7 @@ void CompositorWindow::mouseMoveEvent(QMouseEvent *event) } m_seat->setTimestamp(event->timestamp()); m_seat->setPointerPos(event->localPos().toPoint()); + m_seat->pointerFrame(); } void CompositorWindow::mousePressEvent(QMouseEvent *event) @@ -203,6 +204,7 @@ void CompositorWindow::mousePressEvent(QMouseEvent *event) } m_seat->setTimestamp(event->timestamp()); m_seat->pointerButtonPressed(event->button()); + m_seat->pointerFrame(); } void CompositorWindow::mouseReleaseEvent(QMouseEvent *event) @@ -210,6 +212,7 @@ void CompositorWindow::mouseReleaseEvent(QMouseEvent *event) QWidget::mouseReleaseEvent(event); m_seat->setTimestamp(event->timestamp()); m_seat->pointerButtonReleased(event->button()); + m_seat->pointerFrame(); } void CompositorWindow::wheelEvent(QWheelEvent *event) @@ -218,11 +221,12 @@ void CompositorWindow::wheelEvent(QWheelEvent *event) m_seat->setTimestamp(event->timestamp()); const QPoint &angle = event->angleDelta() / (8 * 15); if (angle.x() != 0) { - m_seat->pointerAxis(Qt::Horizontal, angle.x()); + m_seat->pointerAxis(Qt::Horizontal, angle.x(), 1, KWaylandServer::PointerAxisSource::Wheel); } if (angle.y() != 0) { - m_seat->pointerAxis(Qt::Vertical, angle.y()); + m_seat->pointerAxis(Qt::Vertical, angle.y(), 1, KWaylandServer::PointerAxisSource::Wheel); } + m_seat->pointerFrame(); } int main(int argc, char **argv)