diff --git a/autotests/client/test_wayland_subsurface.cpp b/autotests/client/test_wayland_subsurface.cpp --- a/autotests/client/test_wayland_subsurface.cpp +++ b/autotests/client/test_wayland_subsurface.cpp @@ -54,6 +54,7 @@ void testCast(); void testSyncMode(); void testDeSyncMode(); + void testMainSurfaceFromTree(); private: KWayland::Server::Display *m_display; @@ -206,6 +207,7 @@ 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 @@ 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/server/subcompositor_interface.h b/src/server/subcompositor_interface.h --- a/src/server/subcompositor_interface.h +++ b/src/server/subcompositor_interface.h @@ -85,6 +85,12 @@ 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); diff --git a/src/server/subcompositor_interface.cpp b/src/server/subcompositor_interface.cpp --- a/src/server/subcompositor_interface.cpp +++ b/src/server/subcompositor_interface.cpp @@ -329,6 +329,15 @@ 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());