File indexing completed on 2024-11-10 04:56:20

0001 /*
0002     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 // Qt
0007 #include <QSignalSpy>
0008 #include <QTest>
0009 // KWin
0010 #include "wayland/compositor.h"
0011 #include "wayland/display.h"
0012 #include "wayland/subcompositor.h"
0013 #include "wayland/surface.h"
0014 
0015 #include "KWayland/Client/compositor.h"
0016 #include "KWayland/Client/connection_thread.h"
0017 #include "KWayland/Client/event_queue.h"
0018 #include "KWayland/Client/region.h"
0019 #include "KWayland/Client/registry.h"
0020 #include "KWayland/Client/shm_pool.h"
0021 #include "KWayland/Client/subcompositor.h"
0022 #include "KWayland/Client/subsurface.h"
0023 #include "KWayland/Client/surface.h"
0024 
0025 // Wayland
0026 #include <wayland-client.h>
0027 
0028 Q_DECLARE_METATYPE(KWayland::Client::SubSurface::Mode)
0029 
0030 class TestSubSurface : public QObject
0031 {
0032     Q_OBJECT
0033 public:
0034     explicit TestSubSurface(QObject *parent = nullptr);
0035 private Q_SLOTS:
0036     void init();
0037     void cleanup();
0038 
0039     void testCreate();
0040     void testMode();
0041     void testPosition_data();
0042     void testPosition();
0043     void testPlaceAbove();
0044     void testPlaceBelow();
0045     void testSyncMode();
0046     void testDeSyncMode();
0047     void testMainSurfaceFromTree();
0048     void testRemoveSurface();
0049     void testMappingOfSurfaceTree();
0050     void testSurfaceAt();
0051     void testDestroyAttachedBuffer();
0052     void testDestroyParentSurface();
0053 
0054 private:
0055     KWin::Display *m_display;
0056     KWin::CompositorInterface *m_compositorInterface;
0057     KWin::SubCompositorInterface *m_subcompositorInterface;
0058     KWayland::Client::ConnectionThread *m_connection;
0059     KWayland::Client::Compositor *m_compositor;
0060     KWayland::Client::ShmPool *m_shm;
0061     KWayland::Client::SubCompositor *m_subCompositor;
0062     KWayland::Client::EventQueue *m_queue;
0063     QThread *m_thread;
0064 };
0065 
0066 static const QString s_socketName = QStringLiteral("kwayland-test-wayland-subsurface-0");
0067 
0068 TestSubSurface::TestSubSurface(QObject *parent)
0069     : QObject(parent)
0070     , m_display(nullptr)
0071     , m_compositorInterface(nullptr)
0072     , m_subcompositorInterface(nullptr)
0073     , m_connection(nullptr)
0074     , m_compositor(nullptr)
0075     , m_shm(nullptr)
0076     , m_subCompositor(nullptr)
0077     , m_queue(nullptr)
0078     , m_thread(nullptr)
0079 {
0080 }
0081 
0082 void TestSubSurface::init()
0083 {
0084     using namespace KWin;
0085     delete m_display;
0086     m_display = new KWin::Display(this);
0087     m_display->addSocketName(s_socketName);
0088     m_display->start();
0089     QVERIFY(m_display->isRunning());
0090     m_display->createShm();
0091 
0092     // setup connection
0093     m_connection = new KWayland::Client::ConnectionThread;
0094     QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
0095     m_connection->setSocketName(s_socketName);
0096 
0097     m_thread = new QThread(this);
0098     m_connection->moveToThread(m_thread);
0099     m_thread->start();
0100 
0101     m_connection->initConnection();
0102     QVERIFY(connectedSpy.wait());
0103 
0104     m_queue = new KWayland::Client::EventQueue(this);
0105     QVERIFY(!m_queue->isValid());
0106     m_queue->setup(m_connection);
0107     QVERIFY(m_queue->isValid());
0108 
0109     KWayland::Client::Registry registry;
0110     QSignalSpy compositorSpy(&registry, &KWayland::Client::Registry::compositorAnnounced);
0111     QSignalSpy subCompositorSpy(&registry, &KWayland::Client::Registry::subCompositorAnnounced);
0112     QVERIFY(!registry.eventQueue());
0113     registry.setEventQueue(m_queue);
0114     QCOMPARE(registry.eventQueue(), m_queue);
0115     registry.create(m_connection->display());
0116     QVERIFY(registry.isValid());
0117     registry.setup();
0118 
0119     m_compositorInterface = new CompositorInterface(m_display, m_display);
0120     m_subcompositorInterface = new SubCompositorInterface(m_display, m_display);
0121     QVERIFY(m_subcompositorInterface);
0122 
0123     QVERIFY(subCompositorSpy.wait());
0124     m_subCompositor = registry.createSubCompositor(subCompositorSpy.first().first().value<quint32>(), subCompositorSpy.first().last().value<quint32>(), this);
0125 
0126     if (compositorSpy.isEmpty()) {
0127         QVERIFY(compositorSpy.wait());
0128     }
0129     m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
0130 
0131     m_shm = registry.createShmPool(registry.interface(KWayland::Client::Registry::Interface::Shm).name,
0132                                    registry.interface(KWayland::Client::Registry::Interface::Shm).version,
0133                                    this);
0134     QVERIFY(m_shm->isValid());
0135 }
0136 
0137 void TestSubSurface::cleanup()
0138 {
0139     if (m_shm) {
0140         delete m_shm;
0141         m_shm = nullptr;
0142     }
0143     if (m_subCompositor) {
0144         delete m_subCompositor;
0145         m_subCompositor = nullptr;
0146     }
0147     if (m_compositor) {
0148         delete m_compositor;
0149         m_compositor = nullptr;
0150     }
0151     if (m_queue) {
0152         delete m_queue;
0153         m_queue = nullptr;
0154     }
0155     if (m_thread) {
0156         m_thread->quit();
0157         m_thread->wait();
0158         delete m_thread;
0159         m_thread = nullptr;
0160     }
0161     delete m_connection;
0162     m_connection = nullptr;
0163 
0164     delete m_display;
0165     m_display = nullptr;
0166 }
0167 
0168 void TestSubSurface::testCreate()
0169 {
0170     using namespace KWin;
0171     QSignalSpy surfaceCreatedSpy(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated);
0172 
0173     // create two Surfaces
0174     std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
0175     QVERIFY(surfaceCreatedSpy.wait());
0176     SurfaceInterface *serverSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>();
0177     QVERIFY(serverSurface);
0178 
0179     surfaceCreatedSpy.clear();
0180     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0181     QVERIFY(surfaceCreatedSpy.wait());
0182     SurfaceInterface *serverParentSurface = surfaceCreatedSpy.first().first().value<KWin::SurfaceInterface *>();
0183     QVERIFY(serverParentSurface);
0184 
0185     QSignalSpy subSurfaceCreatedSpy(m_subcompositorInterface, &KWin::SubCompositorInterface::subSurfaceCreated);
0186 
0187     // create subSurface for surface of parent
0188     std::unique_ptr<KWayland::Client::SubSurface> subSurface(m_subCompositor->createSubSurface(surface.get(), parent.get()));
0189 
0190     QVERIFY(subSurfaceCreatedSpy.wait());
0191     SubSurfaceInterface *serverSubSurface = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0192     QVERIFY(serverSubSurface);
0193     QVERIFY(serverSubSurface->parentSurface());
0194     QCOMPARE(serverSubSurface->parentSurface(), serverParentSurface);
0195     QCOMPARE(serverSubSurface->surface(), serverSurface);
0196     QCOMPARE(serverSurface->subSurface(), serverSubSurface);
0197     QCOMPARE(serverSubSurface->mainSurface(), serverParentSurface);
0198     // children are only added after committing the surface
0199     QCOMPARE(serverParentSurface->below().count(), 0);
0200     QEXPECT_FAIL("", "Incorrect adding of child windows to workaround QtWayland behavior", Continue);
0201     QCOMPARE(serverParentSurface->above().count(), 0);
0202     // so let's commit the surface, to apply the stacking change
0203     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0204     wl_display_flush(m_connection->display());
0205     QCoreApplication::processEvents();
0206     QCOMPARE(serverParentSurface->below().count(), 0);
0207     QCOMPARE(serverParentSurface->above().count(), 1);
0208     QCOMPARE(serverParentSurface->above().constFirst(), serverSubSurface);
0209 
0210     // and let's destroy it again
0211     QSignalSpy destroyedSpy(serverSubSurface, &QObject::destroyed);
0212     subSurface.reset();
0213     QVERIFY(destroyedSpy.wait());
0214     QCOMPARE(serverSurface->subSurface(), QPointer<SubSurfaceInterface>());
0215     // only applied after next commit
0216     QCOMPARE(serverParentSurface->below().count(), 0);
0217     QEXPECT_FAIL("", "Incorrect removing of child windows to workaround QtWayland behavior", Continue);
0218     QCOMPARE(serverParentSurface->above().count(), 1);
0219     // but the surface should be invalid
0220     if (!serverParentSurface->above().isEmpty()) {
0221         QVERIFY(!serverParentSurface->above().constFirst());
0222     }
0223     // committing the state should solve it
0224     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0225     wl_display_flush(m_connection->display());
0226     QCoreApplication::processEvents();
0227     QCOMPARE(serverParentSurface->below().count(), 0);
0228     QCOMPARE(serverParentSurface->above().count(), 0);
0229 }
0230 
0231 void TestSubSurface::testMode()
0232 {
0233     using namespace KWin;
0234     // create two Surface
0235     std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
0236     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0237 
0238     QSignalSpy subSurfaceCreatedSpy(m_subcompositorInterface, &KWin::SubCompositorInterface::subSurfaceCreated);
0239 
0240     // create the SubSurface for surface of parent
0241     std::unique_ptr<KWayland::Client::SubSurface> subSurface(m_subCompositor->createSubSurface(surface.get(), parent.get()));
0242     QVERIFY(subSurfaceCreatedSpy.wait());
0243     SubSurfaceInterface *serverSubSurface = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0244     QVERIFY(serverSubSurface);
0245 
0246     // both client and server subsurface should be in synchronized mode
0247     QCOMPARE(subSurface->mode(), KWayland::Client::SubSurface::Mode::Synchronized);
0248     QCOMPARE(serverSubSurface->mode(), SubSurfaceInterface::Mode::Synchronized);
0249 
0250     // verify that we can change to desynchronized
0251     QSignalSpy modeChangedSpy(serverSubSurface, &KWin::SubSurfaceInterface::modeChanged);
0252 
0253     subSurface->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0254     QCOMPARE(subSurface->mode(), KWayland::Client::SubSurface::Mode::Desynchronized);
0255 
0256     QVERIFY(modeChangedSpy.wait());
0257     QCOMPARE(modeChangedSpy.first().first().value<KWin::SubSurfaceInterface::Mode>(), SubSurfaceInterface::Mode::Desynchronized);
0258     QCOMPARE(serverSubSurface->mode(), SubSurfaceInterface::Mode::Desynchronized);
0259 
0260     // setting the same again won't change
0261     subSurface->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0262     QCOMPARE(subSurface->mode(), KWayland::Client::SubSurface::Mode::Desynchronized);
0263     // not testing the signal, we do that after changing to synchronized
0264 
0265     // and change back to synchronized
0266     subSurface->setMode(KWayland::Client::SubSurface::Mode::Synchronized);
0267     QCOMPARE(subSurface->mode(), KWayland::Client::SubSurface::Mode::Synchronized);
0268 
0269     QVERIFY(modeChangedSpy.wait());
0270     QCOMPARE(modeChangedSpy.count(), 2);
0271     QCOMPARE(modeChangedSpy.first().first().value<KWin::SubSurfaceInterface::Mode>(), SubSurfaceInterface::Mode::Desynchronized);
0272     QCOMPARE(modeChangedSpy.last().first().value<KWin::SubSurfaceInterface::Mode>(), SubSurfaceInterface::Mode::Synchronized);
0273     QCOMPARE(serverSubSurface->mode(), SubSurfaceInterface::Mode::Synchronized);
0274 }
0275 
0276 void TestSubSurface::testPosition_data()
0277 {
0278     QTest::addColumn<KWayland::Client::SubSurface::Mode>("commitMode");
0279 
0280     QTest::addRow("sync") << KWayland::Client::SubSurface::Mode::Synchronized;
0281     QTest::addRow("desync") << KWayland::Client::SubSurface::Mode::Desynchronized;
0282 }
0283 
0284 void TestSubSurface::testPosition()
0285 {
0286     using namespace KWin;
0287     // create two Surface
0288     std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
0289     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0290 
0291     QSignalSpy subSurfaceCreatedSpy(m_subcompositorInterface, &KWin::SubCompositorInterface::subSurfaceCreated);
0292 
0293     // create the SubSurface for surface of parent
0294     std::unique_ptr<KWayland::Client::SubSurface> subSurface(m_subCompositor->createSubSurface(surface.get(), parent.get()));
0295     QVERIFY(subSurfaceCreatedSpy.wait());
0296     SubSurfaceInterface *serverSubSurface = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0297     QVERIFY(serverSubSurface);
0298 
0299     // put the subsurface in the desired commit mode
0300     QFETCH(KWayland::Client::SubSurface::Mode, commitMode);
0301     subSurface->setMode(commitMode);
0302 
0303     // both client and server should have a default position
0304     QCOMPARE(subSurface->position(), QPoint());
0305     QCOMPARE(serverSubSurface->position(), QPoint());
0306 
0307     QSignalSpy positionChangedSpy(serverSubSurface, &KWin::SubSurfaceInterface::positionChanged);
0308 
0309     // changing the position should not trigger a direct update on server side
0310     subSurface->setPosition(QPoint(10, 20));
0311     QCOMPARE(subSurface->position(), QPoint(10, 20));
0312     // ensure it's processed on server side
0313     wl_display_flush(m_connection->display());
0314     QCoreApplication::processEvents();
0315     QCOMPARE(serverSubSurface->position(), QPoint());
0316     // changing once more
0317     subSurface->setPosition(QPoint(20, 30));
0318     QCOMPARE(subSurface->position(), QPoint(20, 30));
0319     // ensure it's processed on server side
0320     wl_display_flush(m_connection->display());
0321     QCoreApplication::processEvents();
0322     QCOMPARE(serverSubSurface->position(), QPoint());
0323 
0324     // committing the parent surface should update the position
0325     QSignalSpy parentCommittedSpy(serverSubSurface->parentSurface(), &SurfaceInterface::committed);
0326     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0327     QVERIFY(parentCommittedSpy.wait());
0328     QCOMPARE(positionChangedSpy.count(), 1);
0329     QCOMPARE(positionChangedSpy.first().first().toPoint(), QPoint(20, 30));
0330     QCOMPARE(serverSubSurface->position(), QPoint(20, 30));
0331 }
0332 
0333 void TestSubSurface::testPlaceAbove()
0334 {
0335     using namespace KWin;
0336     // create needed Surfaces (one parent, three client
0337     std::unique_ptr<KWayland::Client::Surface> surface1(m_compositor->createSurface());
0338     std::unique_ptr<KWayland::Client::Surface> surface2(m_compositor->createSurface());
0339     std::unique_ptr<KWayland::Client::Surface> surface3(m_compositor->createSurface());
0340     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0341 
0342     QSignalSpy subSurfaceCreatedSpy(m_subcompositorInterface, &KWin::SubCompositorInterface::subSurfaceCreated);
0343 
0344     // create the SubSurfaces for surface of parent
0345     std::unique_ptr<KWayland::Client::SubSurface> subSurface1(m_subCompositor->createSubSurface(surface1.get(), parent.get()));
0346     QVERIFY(subSurfaceCreatedSpy.wait());
0347     SubSurfaceInterface *serverSubSurface1 = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0348     QVERIFY(serverSubSurface1);
0349     subSurfaceCreatedSpy.clear();
0350     std::unique_ptr<KWayland::Client::SubSurface> subSurface2(m_subCompositor->createSubSurface(surface2.get(), parent.get()));
0351     QVERIFY(subSurfaceCreatedSpy.wait());
0352     SubSurfaceInterface *serverSubSurface2 = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0353     QVERIFY(serverSubSurface2);
0354     subSurfaceCreatedSpy.clear();
0355     std::unique_ptr<KWayland::Client::SubSurface> subSurface3(m_subCompositor->createSubSurface(surface3.get(), parent.get()));
0356     QVERIFY(subSurfaceCreatedSpy.wait());
0357     SubSurfaceInterface *serverSubSurface3 = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0358     QVERIFY(serverSubSurface3);
0359     subSurfaceCreatedSpy.clear();
0360 
0361     // so far the stacking order should still be empty
0362     QVERIFY(serverSubSurface1->parentSurface()->below().isEmpty());
0363     QEXPECT_FAIL("", "Incorrect adding of child windows to workaround QtWayland behavior", Continue);
0364     QVERIFY(serverSubSurface1->parentSurface()->above().isEmpty());
0365 
0366     // committing the parent should create the stacking order
0367     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0368     // ensure it's processed on server side
0369     wl_display_flush(m_connection->display());
0370     QCoreApplication::processEvents();
0371     QCOMPARE(serverSubSurface1->parentSurface()->below().count(), 0);
0372     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 3);
0373     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface1);
0374     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface2);
0375     QCOMPARE(serverSubSurface1->parentSurface()->above().at(2), serverSubSurface3);
0376 
0377     // raising subsurface1 should place it to top of stack
0378     subSurface1->placeAbove(subSurface3.get());
0379     // ensure it's processed on server side
0380     wl_display_flush(m_connection->display());
0381     QCoreApplication::processEvents();
0382     // but as long as parent is not committed it shouldn't change on server side
0383     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface1);
0384     // after commit it's changed
0385     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0386     wl_display_flush(m_connection->display());
0387     QCoreApplication::processEvents();
0388     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 3);
0389     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface2);
0390     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface3);
0391     QCOMPARE(serverSubSurface1->parentSurface()->above().at(2), serverSubSurface1);
0392 
0393     // try placing 3 above 1, should result in 2, 1, 3
0394     subSurface3->placeAbove(subSurface1.get());
0395     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0396     wl_display_flush(m_connection->display());
0397     QCoreApplication::processEvents();
0398     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 3);
0399     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface2);
0400     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface1);
0401     QCOMPARE(serverSubSurface1->parentSurface()->above().at(2), serverSubSurface3);
0402 
0403     // try placing 3 above 2, should result in 2, 3, 1
0404     subSurface3->placeAbove(subSurface2.get());
0405     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0406     wl_display_flush(m_connection->display());
0407     QCoreApplication::processEvents();
0408     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 3);
0409     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface2);
0410     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface3);
0411     QCOMPARE(serverSubSurface1->parentSurface()->above().at(2), serverSubSurface1);
0412 
0413     // try placing 1 above 3 - shouldn't change
0414     subSurface1->placeAbove(subSurface3.get());
0415     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0416     wl_display_flush(m_connection->display());
0417     QCoreApplication::processEvents();
0418     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 3);
0419     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface2);
0420     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface3);
0421     QCOMPARE(serverSubSurface1->parentSurface()->above().at(2), serverSubSurface1);
0422 
0423     // and 2 above 3 - > 3, 2, 1
0424     subSurface2->placeAbove(subSurface3.get());
0425     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0426     wl_display_flush(m_connection->display());
0427     QCoreApplication::processEvents();
0428     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 3);
0429     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface3);
0430     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface2);
0431     QCOMPARE(serverSubSurface1->parentSurface()->above().at(2), serverSubSurface1);
0432 }
0433 
0434 void TestSubSurface::testPlaceBelow()
0435 {
0436     using namespace KWin;
0437     // create needed Surfaces (one parent, three client
0438     std::unique_ptr<KWayland::Client::Surface> surface1(m_compositor->createSurface());
0439     std::unique_ptr<KWayland::Client::Surface> surface2(m_compositor->createSurface());
0440     std::unique_ptr<KWayland::Client::Surface> surface3(m_compositor->createSurface());
0441     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0442 
0443     QSignalSpy subSurfaceCreatedSpy(m_subcompositorInterface, &KWin::SubCompositorInterface::subSurfaceCreated);
0444 
0445     // create the SubSurfaces for surface of parent
0446     std::unique_ptr<KWayland::Client::SubSurface> subSurface1(m_subCompositor->createSubSurface(surface1.get(), parent.get()));
0447     QVERIFY(subSurfaceCreatedSpy.wait());
0448     SubSurfaceInterface *serverSubSurface1 = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0449     QVERIFY(serverSubSurface1);
0450     subSurfaceCreatedSpy.clear();
0451     std::unique_ptr<KWayland::Client::SubSurface> subSurface2(m_subCompositor->createSubSurface(surface2.get(), parent.get()));
0452     QVERIFY(subSurfaceCreatedSpy.wait());
0453     SubSurfaceInterface *serverSubSurface2 = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0454     QVERIFY(serverSubSurface2);
0455     subSurfaceCreatedSpy.clear();
0456     std::unique_ptr<KWayland::Client::SubSurface> subSurface3(m_subCompositor->createSubSurface(surface3.get(), parent.get()));
0457     QVERIFY(subSurfaceCreatedSpy.wait());
0458     SubSurfaceInterface *serverSubSurface3 = subSurfaceCreatedSpy.first().first().value<KWin::SubSurfaceInterface *>();
0459     QVERIFY(serverSubSurface3);
0460     subSurfaceCreatedSpy.clear();
0461 
0462     // so far the stacking order should still be empty
0463     QVERIFY(serverSubSurface1->parentSurface()->below().isEmpty());
0464     QEXPECT_FAIL("", "Incorrect adding of child windows to workaround QtWayland behavior", Continue);
0465     QVERIFY(serverSubSurface1->parentSurface()->above().isEmpty());
0466 
0467     // committing the parent should create the stacking order
0468     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0469     // ensure it's processed on server side
0470     wl_display_flush(m_connection->display());
0471     QCoreApplication::processEvents();
0472     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 3);
0473     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface1);
0474     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface2);
0475     QCOMPARE(serverSubSurface1->parentSurface()->above().at(2), serverSubSurface3);
0476 
0477     // lowering subsurface3 should place it to the bottom of stack
0478     subSurface3->lower();
0479     // ensure it's processed on server side
0480     wl_display_flush(m_connection->display());
0481     QCoreApplication::processEvents();
0482     // but as long as parent is not committed it shouldn't change on server side
0483     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface1);
0484     // after commit it's changed
0485     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0486     wl_display_flush(m_connection->display());
0487     QCoreApplication::processEvents();
0488     QCOMPARE(serverSubSurface1->parentSurface()->below().count(), 1);
0489     QCOMPARE(serverSubSurface1->parentSurface()->below().at(0), serverSubSurface3);
0490     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 2);
0491     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface1);
0492     QCOMPARE(serverSubSurface1->parentSurface()->above().at(1), serverSubSurface2);
0493 
0494     // place 1 below 3 -> 1, 3, 2
0495     subSurface1->placeBelow(subSurface3.get());
0496     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0497     wl_display_flush(m_connection->display());
0498     QCoreApplication::processEvents();
0499     QCOMPARE(serverSubSurface1->parentSurface()->below().count(), 2);
0500     QCOMPARE(serverSubSurface1->parentSurface()->below().at(0), serverSubSurface1);
0501     QCOMPARE(serverSubSurface1->parentSurface()->below().at(1), serverSubSurface3);
0502     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 1);
0503     QCOMPARE(serverSubSurface1->parentSurface()->above().at(0), serverSubSurface2);
0504 
0505     // 2 below 3 -> 1, 2, 3
0506     subSurface2->placeBelow(subSurface3.get());
0507     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0508     wl_display_flush(m_connection->display());
0509     QCoreApplication::processEvents();
0510     QCOMPARE(serverSubSurface1->parentSurface()->below().count(), 3);
0511     QCOMPARE(serverSubSurface1->parentSurface()->below().at(0), serverSubSurface1);
0512     QCOMPARE(serverSubSurface1->parentSurface()->below().at(1), serverSubSurface2);
0513     QCOMPARE(serverSubSurface1->parentSurface()->below().at(2), serverSubSurface3);
0514     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 0);
0515 
0516     // 1 below 2 -> shouldn't change
0517     subSurface1->placeBelow(subSurface2.get());
0518     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0519     wl_display_flush(m_connection->display());
0520     QCoreApplication::processEvents();
0521     QCOMPARE(serverSubSurface1->parentSurface()->below().count(), 3);
0522     QCOMPARE(serverSubSurface1->parentSurface()->below().at(0), serverSubSurface1);
0523     QCOMPARE(serverSubSurface1->parentSurface()->below().at(1), serverSubSurface2);
0524     QCOMPARE(serverSubSurface1->parentSurface()->below().at(2), serverSubSurface3);
0525     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 0);
0526 
0527     // and 3 below 1 -> 3, 1, 2
0528     subSurface3->placeBelow(subSurface1.get());
0529     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0530     wl_display_flush(m_connection->display());
0531     QCoreApplication::processEvents();
0532     QCOMPARE(serverSubSurface1->parentSurface()->below().count(), 3);
0533     QCOMPARE(serverSubSurface1->parentSurface()->below().at(0), serverSubSurface3);
0534     QCOMPARE(serverSubSurface1->parentSurface()->below().at(1), serverSubSurface1);
0535     QCOMPARE(serverSubSurface1->parentSurface()->below().at(2), serverSubSurface2);
0536     QCOMPARE(serverSubSurface1->parentSurface()->above().count(), 0);
0537 }
0538 
0539 void TestSubSurface::testSyncMode()
0540 {
0541     // this test verifies that state is only applied when the parent surface commits its pending state
0542     using namespace KWin;
0543 
0544     QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
0545 
0546     std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
0547     QVERIFY(surfaceCreatedSpy.wait());
0548     auto childSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0549     QVERIFY(childSurface);
0550 
0551     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0552     QVERIFY(surfaceCreatedSpy.wait());
0553     auto parentSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0554     QVERIFY(parentSurface);
0555     // create subSurface for surface of parent
0556     std::unique_ptr<KWayland::Client::SubSurface> subSurface(m_subCompositor->createSubSurface(surface.get(), parent.get()));
0557 
0558     // let's damage the child surface
0559     QSignalSpy childDamagedSpy(childSurface, &SurfaceInterface::damaged);
0560 
0561     QImage image(QSize(200, 200), QImage::Format_ARGB32_Premultiplied);
0562     image.fill(Qt::black);
0563     surface->attachBuffer(m_shm->createBuffer(image));
0564     surface->damage(QRect(0, 0, 200, 200));
0565     surface->commit();
0566 
0567     // state should be applied when the parent surface's state gets applied
0568     QVERIFY(!childDamagedSpy.wait(100));
0569     QVERIFY(!childSurface->buffer());
0570 
0571     QVERIFY(!childSurface->isMapped());
0572     QVERIFY(!parentSurface->isMapped());
0573 
0574     QImage image2(QSize(400, 400), QImage::Format_ARGB32_Premultiplied);
0575     image2.fill(Qt::red);
0576     parent->attachBuffer(m_shm->createBuffer(image2));
0577     parent->damage(QRect(0, 0, 400, 400));
0578     parent->commit();
0579     QVERIFY(childDamagedSpy.wait());
0580     QCOMPARE(childDamagedSpy.count(), 1);
0581     QVERIFY(childSurface->isMapped());
0582     QVERIFY(parentSurface->isMapped());
0583 }
0584 
0585 void TestSubSurface::testDeSyncMode()
0586 {
0587     // this test verifies that state gets applied immediately in desync mode
0588     using namespace KWin;
0589 
0590     QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
0591 
0592     std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
0593     QVERIFY(surfaceCreatedSpy.wait());
0594     auto childSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0595     QVERIFY(childSurface);
0596 
0597     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0598     QVERIFY(surfaceCreatedSpy.wait());
0599     auto parentSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0600     QVERIFY(parentSurface);
0601     // create subSurface for surface of parent
0602     std::unique_ptr<KWayland::Client::SubSurface> subSurface(m_subCompositor->createSubSurface(surface.get(), parent.get()));
0603 
0604     // let's damage the child surface
0605     QSignalSpy childDamagedSpy(childSurface, &SurfaceInterface::damaged);
0606 
0607     QImage image(QSize(200, 200), QImage::Format_ARGB32_Premultiplied);
0608     image.fill(Qt::black);
0609     surface->attachBuffer(m_shm->createBuffer(image));
0610     surface->damage(QRect(0, 0, 200, 200));
0611     surface->commit(KWayland::Client::Surface::CommitFlag::None);
0612 
0613     // state should be applied when the parent surface's state gets applied or when the subsurface switches to desync
0614     QVERIFY(!childDamagedSpy.wait(100));
0615     QVERIFY(!childSurface->isMapped());
0616     QVERIFY(!parentSurface->isMapped());
0617 
0618     // setting to desync should apply the state directly
0619     subSurface->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0620     QVERIFY(childDamagedSpy.wait());
0621     QVERIFY(!childSurface->isMapped());
0622     QVERIFY(!parentSurface->isMapped());
0623 
0624     // and damaging again, should directly be applied
0625     image.fill(Qt::red);
0626     surface->attachBuffer(m_shm->createBuffer(image));
0627     surface->damage(QRect(0, 0, 200, 200));
0628     surface->commit(KWayland::Client::Surface::CommitFlag::None);
0629     QVERIFY(childDamagedSpy.wait());
0630 }
0631 
0632 void TestSubSurface::testMainSurfaceFromTree()
0633 {
0634     // this test verifies that in a tree of surfaces every surface has the same main surface
0635     using namespace KWin;
0636     QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
0637 
0638     std::unique_ptr<KWayland::Client::Surface> parentSurface(m_compositor->createSurface());
0639     QVERIFY(surfaceCreatedSpy.wait());
0640     auto parentServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0641     QVERIFY(parentServerSurface);
0642     std::unique_ptr<KWayland::Client::Surface> childLevel1Surface(m_compositor->createSurface());
0643     QVERIFY(surfaceCreatedSpy.wait());
0644     auto childLevel1ServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0645     QVERIFY(childLevel1ServerSurface);
0646     std::unique_ptr<KWayland::Client::Surface> childLevel2Surface(m_compositor->createSurface());
0647     QVERIFY(surfaceCreatedSpy.wait());
0648     auto childLevel2ServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0649     QVERIFY(childLevel2ServerSurface);
0650     std::unique_ptr<KWayland::Client::Surface> childLevel3Surface(m_compositor->createSurface());
0651     QVERIFY(surfaceCreatedSpy.wait());
0652     auto childLevel3ServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0653     QVERIFY(childLevel3ServerSurface);
0654 
0655     m_subCompositor->createSubSurface(childLevel1Surface.get(), parentSurface.get());
0656     m_subCompositor->createSubSurface(childLevel2Surface.get(), childLevel1Surface.get());
0657     m_subCompositor->createSubSurface(childLevel3Surface.get(), childLevel2Surface.get());
0658 
0659     QSignalSpy parentCommittedSpy(parentServerSurface, &SurfaceInterface::committed);
0660     parentSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0661     QVERIFY(parentCommittedSpy.wait());
0662 
0663     QCOMPARE(parentServerSurface->below().count(), 0);
0664     QCOMPARE(parentServerSurface->above().count(), 1);
0665     auto child = parentServerSurface->above().constFirst();
0666     QCOMPARE(child->parentSurface(), parentServerSurface);
0667     QCOMPARE(child->mainSurface(), parentServerSurface);
0668     QCOMPARE(child->surface()->below().count(), 0);
0669     QCOMPARE(child->surface()->above().count(), 1);
0670     auto child2 = child->surface()->above().constFirst();
0671     QCOMPARE(child2->parentSurface(), child->surface());
0672     QCOMPARE(child2->mainSurface(), parentServerSurface);
0673     QCOMPARE(child2->surface()->below().count(), 0);
0674     QCOMPARE(child2->surface()->above().count(), 1);
0675     auto child3 = child2->surface()->above().constFirst();
0676     QCOMPARE(child3->parentSurface(), child2->surface());
0677     QCOMPARE(child3->mainSurface(), parentServerSurface);
0678     QCOMPARE(child3->surface()->below().count(), 0);
0679     QCOMPARE(child3->surface()->above().count(), 0);
0680 }
0681 
0682 void TestSubSurface::testRemoveSurface()
0683 {
0684     // this test verifies that removing the surface also removes the sub-surface from the parent
0685     using namespace KWin;
0686 
0687     QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
0688 
0689     std::unique_ptr<KWayland::Client::Surface> parentSurface(m_compositor->createSurface());
0690     QVERIFY(surfaceCreatedSpy.wait());
0691     auto parentServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0692     QVERIFY(parentServerSurface);
0693     std::unique_ptr<KWayland::Client::Surface> childSurface(m_compositor->createSurface());
0694     QVERIFY(surfaceCreatedSpy.wait());
0695     auto childServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0696     QVERIFY(childServerSurface);
0697 
0698     QSignalSpy childrenChangedSpy(parentServerSurface, &SurfaceInterface::childSubSurfacesChanged);
0699 
0700     m_subCompositor->createSubSurface(childSurface.get(), parentSurface.get());
0701     parentSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0702     QVERIFY(childrenChangedSpy.wait());
0703 
0704     QCOMPARE(parentServerSurface->below().count(), 0);
0705     QCOMPARE(parentServerSurface->above().count(), 1);
0706 
0707     // destroy surface, takes place immediately
0708     childSurface.reset();
0709     QVERIFY(childrenChangedSpy.wait());
0710     QCOMPARE(parentServerSurface->below().count(), 0);
0711     QCOMPARE(parentServerSurface->above().count(), 0);
0712 }
0713 
0714 void TestSubSurface::testMappingOfSurfaceTree()
0715 {
0716     // this test verifies mapping and unmapping of a sub-surface tree
0717     using namespace KWin;
0718     QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
0719 
0720     std::unique_ptr<KWayland::Client::Surface> parentSurface(m_compositor->createSurface());
0721     QVERIFY(surfaceCreatedSpy.wait());
0722     auto parentServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0723     QVERIFY(parentServerSurface);
0724     std::unique_ptr<KWayland::Client::Surface> childLevel1Surface(m_compositor->createSurface());
0725     QVERIFY(surfaceCreatedSpy.wait());
0726     auto childLevel1ServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0727     QVERIFY(childLevel1ServerSurface);
0728     std::unique_ptr<KWayland::Client::Surface> childLevel2Surface(m_compositor->createSurface());
0729     QVERIFY(surfaceCreatedSpy.wait());
0730     auto childLevel2ServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0731     QVERIFY(childLevel2ServerSurface);
0732     std::unique_ptr<KWayland::Client::Surface> childLevel3Surface(m_compositor->createSurface());
0733     QVERIFY(surfaceCreatedSpy.wait());
0734     auto childLevel3ServerSurface = surfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0735     QVERIFY(childLevel3ServerSurface);
0736 
0737     auto subSurfaceLevel1 = m_subCompositor->createSubSurface(childLevel1Surface.get(), parentSurface.get());
0738     auto subSurfaceLevel2 = m_subCompositor->createSubSurface(childLevel2Surface.get(), childLevel1Surface.get());
0739     auto subSurfaceLevel3 = m_subCompositor->createSubSurface(childLevel3Surface.get(), childLevel2Surface.get());
0740 
0741     QSignalSpy parentCommittedSpy(parentServerSurface, &SurfaceInterface::committed);
0742     parentSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0743     QVERIFY(parentCommittedSpy.wait());
0744 
0745     QCOMPARE(parentServerSurface->below().count(), 0);
0746     QCOMPARE(parentServerSurface->above().count(), 1);
0747     auto child = parentServerSurface->above().constFirst();
0748     QCOMPARE(child->surface()->below().count(), 0);
0749     QCOMPARE(child->surface()->above().count(), 1);
0750     auto child2 = child->surface()->above().constFirst();
0751     QCOMPARE(child2->surface()->below().count(), 0);
0752     QCOMPARE(child2->surface()->above().count(), 1);
0753     auto child3 = child2->surface()->above().constFirst();
0754     QCOMPARE(child3->parentSurface(), child2->surface());
0755     QCOMPARE(child3->mainSurface(), parentServerSurface);
0756     QCOMPARE(child3->surface()->below().count(), 0);
0757     QCOMPARE(child3->surface()->above().count(), 0);
0758 
0759     // so far no surface is mapped
0760     QVERIFY(!parentServerSurface->isMapped());
0761     QVERIFY(!child->surface()->isMapped());
0762     QVERIFY(!child2->surface()->isMapped());
0763     QVERIFY(!child3->surface()->isMapped());
0764 
0765     // first set all subsurfaces to desync, to simplify
0766     subSurfaceLevel1->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0767     subSurfaceLevel2->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0768     subSurfaceLevel3->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0769 
0770     // first map the child, should not map it
0771     QSignalSpy child3DamageSpy(child3->surface(), &SurfaceInterface::damaged);
0772     QImage image(QSize(200, 200), QImage::Format_ARGB32_Premultiplied);
0773     image.fill(Qt::black);
0774     childLevel3Surface->attachBuffer(m_shm->createBuffer(image));
0775     childLevel3Surface->damage(QRect(0, 0, 200, 200));
0776     childLevel3Surface->commit(KWayland::Client::Surface::CommitFlag::None);
0777     QVERIFY(child3DamageSpy.wait());
0778     QVERIFY(child3->surface()->buffer());
0779     QVERIFY(!child3->surface()->isMapped());
0780 
0781     // let's map the top level
0782     QSignalSpy parentSpy(parentServerSurface, &SurfaceInterface::damaged);
0783     parentSurface->attachBuffer(m_shm->createBuffer(image));
0784     parentSurface->damage(QRect(0, 0, 200, 200));
0785     parentSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0786     QVERIFY(parentSpy.wait());
0787     QVERIFY(parentServerSurface->isMapped());
0788     // children should not yet be mapped
0789     QVERIFY(!child->surface()->isMapped());
0790     QVERIFY(!child2->surface()->isMapped());
0791     QVERIFY(!child3->surface()->isMapped());
0792 
0793     // next level
0794     QSignalSpy child2DamageSpy(child2->surface(), &SurfaceInterface::damaged);
0795     childLevel2Surface->attachBuffer(m_shm->createBuffer(image));
0796     childLevel2Surface->damage(QRect(0, 0, 200, 200));
0797     childLevel2Surface->commit(KWayland::Client::Surface::CommitFlag::None);
0798     QVERIFY(child2DamageSpy.wait());
0799     QVERIFY(parentServerSurface->isMapped());
0800     // children should not yet be mapped
0801     QVERIFY(!child->surface()->isMapped());
0802     QVERIFY(!child2->surface()->isMapped());
0803     QVERIFY(!child3->surface()->isMapped());
0804 
0805     // last but not least the first child level, which should map all our subsurfaces
0806     QSignalSpy child1DamageSpy(child->surface(), &SurfaceInterface::damaged);
0807     childLevel1Surface->attachBuffer(m_shm->createBuffer(image));
0808     childLevel1Surface->damage(QRect(0, 0, 200, 200));
0809     childLevel1Surface->commit(KWayland::Client::Surface::CommitFlag::None);
0810     QVERIFY(child1DamageSpy.wait());
0811 
0812     // everything is mapped
0813     QVERIFY(parentServerSurface->isMapped());
0814     QVERIFY(child->surface()->isMapped());
0815     QVERIFY(child2->surface()->isMapped());
0816     QVERIFY(child3->surface()->isMapped());
0817 
0818     // unmapping a parent should unmap the complete tree
0819     QSignalSpy unmappedSpy(child->surface(), &SurfaceInterface::unmapped);
0820     childLevel1Surface->attachBuffer(KWayland::Client::Buffer::Ptr());
0821     childLevel1Surface->damage(QRect(0, 0, 200, 200));
0822     childLevel1Surface->commit(KWayland::Client::Surface::CommitFlag::None);
0823     QVERIFY(unmappedSpy.wait());
0824 
0825     QVERIFY(parentServerSurface->isMapped());
0826     QVERIFY(!child->surface()->isMapped());
0827     QVERIFY(!child2->surface()->isMapped());
0828     QVERIFY(!child3->surface()->isMapped());
0829 }
0830 
0831 void TestSubSurface::testSurfaceAt()
0832 {
0833     // this test verifies that the correct surface is picked in a sub-surface tree
0834     using namespace KWin;
0835     // first create a parent surface and map it
0836     QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated);
0837     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0838     QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied);
0839     image.fill(Qt::red);
0840     parent->attachBuffer(m_shm->createBuffer(image));
0841     parent->damage(QRect(0, 0, 100, 100));
0842     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0843     QVERIFY(serverSurfaceCreated.wait());
0844     SurfaceInterface *parentServerSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0845 
0846     // directChild1 occupies the top-left quarter of the parent surface
0847     QImage directImage(QSize(50, 50), QImage::Format_ARGB32_Premultiplied);
0848     std::unique_ptr<KWayland::Client::Surface> directChild1(m_compositor->createSurface());
0849     directChild1->attachBuffer(m_shm->createBuffer(directImage));
0850     directChild1->damage(QRect(0, 0, 50, 50));
0851     directChild1->commit(KWayland::Client::Surface::CommitFlag::None);
0852     QVERIFY(serverSurfaceCreated.wait());
0853     SurfaceInterface *directChild1ServerSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0854     QVERIFY(directChild1ServerSurface);
0855 
0856     // directChild2 occupies the bottom-right quarter of the parent surface
0857     std::unique_ptr<KWayland::Client::Surface> directChild2(m_compositor->createSurface());
0858     directChild2->attachBuffer(m_shm->createBuffer(directImage));
0859     directChild2->damage(QRect(0, 0, 50, 50));
0860     directChild2->commit(KWayland::Client::Surface::CommitFlag::None);
0861     QVERIFY(serverSurfaceCreated.wait());
0862     SurfaceInterface *directChild2ServerSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0863     QVERIFY(directChild2ServerSurface);
0864 
0865     // create the sub surfaces for them
0866     std::unique_ptr<KWayland::Client::SubSurface> directChild1SubSurface(m_subCompositor->createSubSurface(directChild1.get(), parent.get()));
0867     directChild1SubSurface->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0868     std::unique_ptr<KWayland::Client::SubSurface> directChild2SubSurface(m_subCompositor->createSubSurface(directChild2.get(), parent.get()));
0869     directChild2SubSurface->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0870     directChild2SubSurface->setPosition(QPoint(50, 50));
0871 
0872     // unset input regions for direct children
0873     QSignalSpy directChild1CommittedSpy(directChild1ServerSurface, &SurfaceInterface::committed);
0874     directChild1->setInputRegion(m_compositor->createRegion(QRegion()).get());
0875     directChild1->commit(KWayland::Client::Surface::CommitFlag::None);
0876     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0877     QVERIFY(directChild1CommittedSpy.wait());
0878 
0879     QSignalSpy directChild2CommittedSpy(directChild2ServerSurface, &SurfaceInterface::committed);
0880     directChild2->setInputRegion(m_compositor->createRegion(QRegion()).get());
0881     directChild2->commit(KWayland::Client::Surface::CommitFlag::None);
0882     parent->commit(KWayland::Client::Surface::CommitFlag::None);
0883     QVERIFY(directChild2CommittedSpy.wait());
0884 
0885     // each of the children gets a child
0886     std::unique_ptr<KWayland::Client::Surface> childFor1(m_compositor->createSurface());
0887     QVERIFY(serverSurfaceCreated.wait());
0888     SurfaceInterface *childFor1ServerSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0889     std::unique_ptr<KWayland::Client::Surface> childFor2(m_compositor->createSurface());
0890     QVERIFY(serverSurfaceCreated.wait());
0891     SurfaceInterface *childFor2ServerSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0892 
0893     // create sub surfaces for them
0894     std::unique_ptr<KWayland::Client::SubSurface> childFor1SubSurface(m_subCompositor->createSubSurface(childFor1.get(), directChild1.get()));
0895     childFor1SubSurface->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0896     std::unique_ptr<KWayland::Client::SubSurface> childFor2SubSurface(m_subCompositor->createSubSurface(childFor2.get(), directChild2.get()));
0897     childFor2SubSurface->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
0898 
0899     // now let's render both grand children
0900     QImage partImage(QSize(50, 50), QImage::Format_ARGB32_Premultiplied);
0901     partImage.fill(Qt::green);
0902     childFor1->attachBuffer(m_shm->createBuffer(partImage));
0903     childFor1->damage(QRect(0, 0, 50, 50));
0904     childFor1->commit(KWayland::Client::Surface::CommitFlag::None);
0905     partImage.fill(Qt::blue);
0906 
0907     QSignalSpy childFor2CommittedSpy(childFor2ServerSurface, &SurfaceInterface::committed);
0908     childFor2->attachBuffer(m_shm->createBuffer(partImage));
0909     // child for 2's input region is subdivided into quadrants, with input mask on the top left and bottom right
0910     QRegion region;
0911     region += QRect(0, 0, 25, 25);
0912     region += QRect(25, 25, 25, 25);
0913     childFor2->setInputRegion(m_compositor->createRegion(region).get());
0914     childFor2->damage(QRect(0, 0, 50, 50));
0915     childFor2->commit(KWayland::Client::Surface::CommitFlag::None);
0916     QVERIFY(childFor2CommittedSpy.wait());
0917 
0918     QCOMPARE(directChild1ServerSurface->subSurface()->parentSurface(), parentServerSurface);
0919     QCOMPARE(directChild2ServerSurface->subSurface()->parentSurface(), parentServerSurface);
0920     QCOMPARE(childFor1ServerSurface->subSurface()->parentSurface(), directChild1ServerSurface);
0921     QCOMPARE(childFor2ServerSurface->subSurface()->parentSurface(), directChild2ServerSurface);
0922 
0923     // now let's test a few positions
0924     QCOMPARE(parentServerSurface->surfaceAt(QPointF(0, 0)), childFor1ServerSurface);
0925     QCOMPARE(parentServerSurface->surfaceAt(QPointF(49, 49)), childFor1ServerSurface);
0926     QCOMPARE(parentServerSurface->surfaceAt(QPointF(50, 50)), childFor2ServerSurface);
0927     QCOMPARE(parentServerSurface->surfaceAt(QPointF(99, 99)), childFor2ServerSurface);
0928     QCOMPARE(parentServerSurface->surfaceAt(QPointF(99, 50)), childFor2ServerSurface);
0929     QCOMPARE(parentServerSurface->surfaceAt(QPointF(50, 99)), childFor2ServerSurface);
0930     QCOMPARE(parentServerSurface->surfaceAt(QPointF(25, 75)), parentServerSurface);
0931     QCOMPARE(parentServerSurface->surfaceAt(QPointF(75, 25)), parentServerSurface);
0932 
0933     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(0, 0)), childFor1ServerSurface);
0934     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(49, 49)), childFor1ServerSurface);
0935     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(50, 50)), childFor2ServerSurface);
0936     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(99, 99)), childFor2ServerSurface);
0937     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(99, 50)), parentServerSurface);
0938     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(50, 99)), parentServerSurface);
0939     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(25, 75)), parentServerSurface);
0940     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(75, 25)), parentServerSurface);
0941 
0942     // outside the geometries should be no surface
0943     QVERIFY(!parentServerSurface->surfaceAt(QPointF(-1, -1)));
0944     QVERIFY(!parentServerSurface->surfaceAt(QPointF(101, 101)));
0945 
0946     // on the surface edge right/bottom edges should not trigger as contained
0947     QCOMPARE(parentServerSurface->surfaceAt(QPointF(50, 25)), parentServerSurface);
0948     QCOMPARE(parentServerSurface->surfaceAt(QPointF(25, 50)), parentServerSurface);
0949     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(50, 25)), parentServerSurface);
0950     QCOMPARE(parentServerSurface->inputSurfaceAt(QPointF(25, 50)), parentServerSurface);
0951 }
0952 
0953 void TestSubSurface::testDestroyAttachedBuffer()
0954 {
0955     // this test verifies that destroying of a buffer attached to a sub-surface works
0956     using namespace KWin;
0957     // create surface
0958     QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated);
0959     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0960     QVERIFY(serverSurfaceCreated.wait());
0961     std::unique_ptr<KWayland::Client::Surface> child(m_compositor->createSurface());
0962     QVERIFY(serverSurfaceCreated.wait());
0963     SurfaceInterface *serverChildSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0964     // create sub-surface
0965     m_subCompositor->createSubSurface(child.get(), parent.get());
0966 
0967     // let's damage this surface, will be in sub-surface pending state
0968     QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied);
0969     image.fill(Qt::red);
0970     child->attachBuffer(m_shm->createBuffer(image));
0971     child->damage(QRect(0, 0, 100, 100));
0972     child->commit(KWayland::Client::Surface::CommitFlag::None);
0973     m_connection->flush();
0974 
0975     // Let's try to destroy it
0976     QSignalSpy destroySpy(serverChildSurface, &QObject::destroyed);
0977     delete m_shm;
0978     m_shm = nullptr;
0979     child.reset();
0980     QVERIFY(destroySpy.wait());
0981 }
0982 
0983 void TestSubSurface::testDestroyParentSurface()
0984 {
0985     // this test verifies that destroying a parent surface does not create problems
0986     // see BUG 389231
0987     using namespace KWin;
0988     // create surface
0989     QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated);
0990     std::unique_ptr<KWayland::Client::Surface> parent(m_compositor->createSurface());
0991     QVERIFY(serverSurfaceCreated.wait());
0992     SurfaceInterface *serverParentSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0993     std::unique_ptr<KWayland::Client::Surface> child(m_compositor->createSurface());
0994     QVERIFY(serverSurfaceCreated.wait());
0995     SurfaceInterface *serverChildSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0996     std::unique_ptr<KWayland::Client::Surface> grandChild(m_compositor->createSurface());
0997     QVERIFY(serverSurfaceCreated.wait());
0998     SurfaceInterface *serverGrandChildSurface = serverSurfaceCreated.last().first().value<KWin::SurfaceInterface *>();
0999     // create sub-surface in desynchronized mode as Qt uses them
1000     auto sub1 = m_subCompositor->createSubSurface(child.get(), parent.get());
1001     sub1->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
1002     auto sub2 = m_subCompositor->createSubSurface(grandChild.get(), child.get());
1003     sub2->setMode(KWayland::Client::SubSurface::Mode::Desynchronized);
1004 
1005     // let's damage this surface
1006     // and at the same time delete the parent surface
1007     parent.reset();
1008     QSignalSpy parentDestroyedSpy(serverParentSurface, &QObject::destroyed);
1009     QVERIFY(parentDestroyedSpy.wait());
1010     QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied);
1011     image.fill(Qt::red);
1012     grandChild->attachBuffer(m_shm->createBuffer(image));
1013     grandChild->damage(QRect(0, 0, 100, 100));
1014     grandChild->commit(KWayland::Client::Surface::CommitFlag::None);
1015     QSignalSpy damagedSpy(serverGrandChildSurface, &SurfaceInterface::damaged);
1016     QVERIFY(damagedSpy.wait());
1017 
1018     // Let's try to destroy it
1019     QSignalSpy destroySpy(serverChildSurface, &QObject::destroyed);
1020     child.reset();
1021     QVERIFY(destroySpy.wait());
1022 }
1023 
1024 QTEST_GUILESS_MAIN(TestSubSurface)
1025 #include "test_wayland_subsurface.moc"