From 84118fad132d66b721519ce1d3ee189be00ff7aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Wed, 23 Mar 2016 16:59:18 +0100 Subject: [PATCH] [server] Add method to get to the main surface from a sub surface Summary: Recursively go up to the main surface, that is the top level surface which doesn't have a parent. This is useful to know to which surface tree a sub-surface belongs to. Reviewers: #plasma Subscribers: plasma-devel Projects: #plasma Differential Revision: https://phabricator.kde.org/D1207 --- .../client/test_wayland_subsurface.cpp | 53 +++++++++++++++++++ src/wayland/subcompositor_interface.cpp | 9 ++++ src/wayland/subcompositor_interface.h | 6 +++ 3 files changed, 68 insertions(+) diff --git a/src/wayland/autotests/client/test_wayland_subsurface.cpp b/src/wayland/autotests/client/test_wayland_subsurface.cpp index 938e986d05..97a7641abc 100644 --- a/src/wayland/autotests/client/test_wayland_subsurface.cpp +++ b/src/wayland/autotests/client/test_wayland_subsurface.cpp @@ -54,6 +54,7 @@ private Q_SLOTS: void testCast(); void testSyncMode(); void testDeSyncMode(); + void testMainSurfaceFromTree(); private: KWayland::Server::Display *m_display; @@ -206,6 +207,7 @@ void TestSubSurface::testCreate() QCOMPARE(serverSubSurface->parentSurface().data(), serverParentSurface); QCOMPARE(serverSubSurface->surface().data(), serverSurface); QCOMPARE(serverSurface->subSurface().data(), serverSubSurface); + QCOMPARE(serverSubSurface->mainSurface().data(), serverParentSurface); // children are only added after committing the surface QEXPECT_FAIL("", "Incorrect adding of child windows to workaround QtWayland behavior", Continue); QCOMPARE(serverParentSurface->childSubSurfaces().count(), 0); @@ -695,5 +697,56 @@ void TestSubSurface::testDeSyncMode() QCOMPARE(childSurface->buffer()->data(), image); } + +void TestSubSurface::testMainSurfaceFromTree() +{ + // this test verifies that in a tree of surfaces every surface has the same main surface + using namespace KWayland::Client; + using namespace KWayland::Server; + QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); + QVERIFY(surfaceCreatedSpy.isValid()); + + QScopedPointer parentSurface(m_compositor->createSurface()); + QVERIFY(surfaceCreatedSpy.wait()); + auto parentServerSurface = surfaceCreatedSpy.last().first().value(); + QVERIFY(parentServerSurface); + QScopedPointer childLevel1Surface(m_compositor->createSurface()); + QVERIFY(surfaceCreatedSpy.wait()); + auto childLevel1ServerSurface = surfaceCreatedSpy.last().first().value(); + QVERIFY(childLevel1ServerSurface); + QScopedPointer childLevel2Surface(m_compositor->createSurface()); + QVERIFY(surfaceCreatedSpy.wait()); + auto childLevel2ServerSurface = surfaceCreatedSpy.last().first().value(); + QVERIFY(childLevel2ServerSurface); + QScopedPointer childLevel3Surface(m_compositor->createSurface()); + QVERIFY(surfaceCreatedSpy.wait()); + auto childLevel3ServerSurface = surfaceCreatedSpy.last().first().value(); + QVERIFY(childLevel3ServerSurface); + + QSignalSpy subSurfaceTreeChangedSpy(parentServerSurface, &SurfaceInterface::subSurfaceTreeChanged); + QVERIFY(subSurfaceTreeChangedSpy.isValid()); + + m_subCompositor->createSubSurface(childLevel1Surface.data(), parentSurface.data()); + m_subCompositor->createSubSurface(childLevel2Surface.data(), childLevel1Surface.data()); + m_subCompositor->createSubSurface(childLevel3Surface.data(), childLevel2Surface.data()); + + parentSurface->commit(Surface::CommitFlag::None); + QVERIFY(subSurfaceTreeChangedSpy.wait()); + + QCOMPARE(parentServerSurface->childSubSurfaces().count(), 1); + auto child = parentServerSurface->childSubSurfaces().first(); + QCOMPARE(child->parentSurface().data(), parentServerSurface); + QCOMPARE(child->mainSurface().data(), parentServerSurface); + QCOMPARE(child->surface()->childSubSurfaces().count(), 1); + auto child2 = child->surface()->childSubSurfaces().first(); + QCOMPARE(child2->parentSurface().data(), child->surface().data()); + QCOMPARE(child2->mainSurface().data(), parentServerSurface); + QCOMPARE(child2->surface()->childSubSurfaces().count(), 1); + auto child3 = child2->surface()->childSubSurfaces().first(); + QCOMPARE(child3->parentSurface().data(), child2->surface().data()); + QCOMPARE(child3->mainSurface().data(), parentServerSurface); + QCOMPARE(child3->surface()->childSubSurfaces().count(), 0); +} + QTEST_GUILESS_MAIN(TestSubSurface) #include "test_wayland_subsurface.moc" diff --git a/src/wayland/subcompositor_interface.cpp b/src/wayland/subcompositor_interface.cpp index 30bfd5bb09..9c77a5a3c4 100644 --- a/src/wayland/subcompositor_interface.cpp +++ b/src/wayland/subcompositor_interface.cpp @@ -329,6 +329,15 @@ bool SubSurfaceInterface::isSynchronized() const return false; } +QPointer SubSurfaceInterface::mainSurface() const +{ + Q_D(); + if (d->parent->d_func()->subSurface) { + return d->parent->d_func()->subSurface->mainSurface(); + } + return d->parent; +} + SubSurfaceInterface::Private *SubSurfaceInterface::d_func() const { return reinterpret_cast(d.data()); diff --git a/src/wayland/subcompositor_interface.h b/src/wayland/subcompositor_interface.h index 56470e251a..674ea1d89d 100644 --- a/src/wayland/subcompositor_interface.h +++ b/src/wayland/subcompositor_interface.h @@ -85,6 +85,12 @@ public: QPointer surface(); QPointer parentSurface(); + /** + * @returns the main surface for the sub-surface tree, that is the first surface without a parent + * @since 5.7 + **/ + QPointer mainSurface() const; + Q_SIGNALS: void positionChanged(const QPoint&); void modeChanged(KWayland::Server::SubSurfaceInterface::Mode);