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 @@ -626,6 +626,9 @@ QVERIFY(!childDamagedSpy.wait(100)); QVERIFY(!childSurface->buffer()); + QVERIFY(!childSurface->isMapped()); + QVERIFY(!parentSurface->isMapped()); + QImage image2(QSize(400, 400), QImage::Format_ARGB32); image2.fill(Qt::red); parent->attachBuffer(m_shm->createBuffer(image2)); @@ -636,6 +639,8 @@ QCOMPARE(subSurfaceTreeChangedSpy.count(), 2); QCOMPARE(childSurface->buffer()->data(), image); QCOMPARE(parentSurface->buffer()->data(), image2); + QVERIFY(childSurface->isMapped()); + QVERIFY(parentSurface->isMapped()); // sending frame rendered to parent should also send it to child QSignalSpy frameRenderedSpy(surface.data(), &Surface::frameRendered); @@ -681,12 +686,16 @@ // state should be applied when the parent surface's state gets applied or when the subsurface switches to desync QVERIFY(!childDamagedSpy.wait(100)); + QVERIFY(!childSurface->isMapped()); + QVERIFY(!parentSurface->isMapped()); // setting to desync should apply the state directly subSurface->setMode(SubSurface::Mode::Desynchronized); QVERIFY(childDamagedSpy.wait()); QCOMPARE(subSurfaceTreeChangedSpy.count(), 2); QCOMPARE(childSurface->buffer()->data(), image); + QVERIFY(!childSurface->isMapped()); + QVERIFY(!parentSurface->isMapped()); // and damaging again, should directly be applied image.fill(Qt::red); diff --git a/autotests/client/test_wayland_surface.cpp b/autotests/client/test_wayland_surface.cpp --- a/autotests/client/test_wayland_surface.cpp +++ b/autotests/client/test_wayland_surface.cpp @@ -231,6 +231,7 @@ QVERIFY(serverSurface); QCOMPARE(serverSurface->damage(), QRegion()); QVERIFY(serverSurface->parentResource()); + QVERIFY(!serverSurface->isMapped()); QSignalSpy damageSpy(serverSurface, SIGNAL(damaged(QRegion))); QVERIFY(damageSpy.isValid()); @@ -242,6 +243,7 @@ QCoreApplication::processEvents(); QCoreApplication::processEvents(); QVERIFY(damageSpy.isEmpty()); + QVERIFY(!serverSurface->isMapped()); QImage img(QSize(10, 10), QImage::Format_ARGB32); img.fill(Qt::black); @@ -252,6 +254,7 @@ QVERIFY(damageSpy.wait()); QCOMPARE(serverSurface->damage(), QRegion(0, 0, 10, 10)); QCOMPARE(damageSpy.first().first().value(), QRegion(0, 0, 10, 10)); + QVERIFY(serverSurface->isMapped()); // damage multiple times QRegion testRegion(5, 8, 3, 6); @@ -266,6 +269,7 @@ QVERIFY(damageSpy.wait()); QCOMPARE(serverSurface->damage(), testRegion); QCOMPARE(damageSpy.first().first().value(), testRegion); + QVERIFY(serverSurface->isMapped()); } void TestWaylandSurface::testFrameCallback() @@ -408,6 +412,7 @@ QCOMPARE(serverSurface->buffer(), buffer3); QVERIFY(damageSpy.isEmpty()); QVERIFY(unmappedSpy.isEmpty()); + QVERIFY(serverSurface->isMapped()); // clear the surface s->attachBuffer(blackBuffer); @@ -420,6 +425,7 @@ QVERIFY(!unmappedSpy.isEmpty()); QCOMPARE(unmappedSpy.count(), 1); QVERIFY(damageSpy.isEmpty()); + QVERIFY(!serverSurface->isMapped()); // TODO: add signal test on release buffer->unref(); diff --git a/src/server/surface_interface.h b/src/server/surface_interface.h --- a/src/server/surface_interface.h +++ b/src/server/surface_interface.h @@ -153,6 +153,17 @@ QPointer contrast() const; /** + * Whether the SurfaceInterface is currently considered to be mapped. + * A SurfaceInterface is mapped if it has a non-null BufferInterface attached. + * If the SurfaceInterface references a SubSurfaceInterface it is only considered + * mapped if it has a BufferInterface attached and the parent SurfaceInterface is mapped. + * + * @returns Whether the SurfaceInterface is currently mapped + * @since 5.7 + **/ + bool isMapped() const; + + /** * @returns The SurfaceInterface for the @p native resource. **/ static SurfaceInterface *get(wl_resource *native); diff --git a/src/server/surface_interface.cpp b/src/server/surface_interface.cpp --- a/src/server/surface_interface.cpp +++ b/src/server/surface_interface.cpp @@ -662,6 +662,17 @@ return d->current.slide; } +bool SurfaceInterface::isMapped() const +{ + Q_D(); + if (d->subSurface) { + // from spec: + // "A sub-surface becomes mapped, when a non-NULL wl_buffer is applied and the parent surface is mapped." + return d->current.buffer && !d->subSurface->parentSurface().isNull() && d->subSurface->parentSurface()->isMapped(); + } + return d->current.buffer != nullptr; +} + SurfaceInterface::Private *SurfaceInterface::d_func() const { return reinterpret_cast(d.data());