File indexing completed on 2024-06-16 05:05:04

0001 /*
0002     SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include <QSignalSpy>
0008 #include <QTest>
0009 #include <QThread>
0010 
0011 #include "wayland/compositor.h"
0012 #include "wayland/display.h"
0013 #include "wayland/layershell_v1.h"
0014 #include "wayland/surface.h"
0015 #include "wayland/xdgshell.h"
0016 
0017 #include "KWayland/Client/compositor.h"
0018 #include "KWayland/Client/connection_thread.h"
0019 #include "KWayland/Client/event_queue.h"
0020 #include "KWayland/Client/registry.h"
0021 #include "KWayland/Client/surface.h"
0022 
0023 #include "qwayland-wlr-layer-shell-unstable-v1.h"
0024 #include "qwayland-xdg-shell.h"
0025 
0026 Q_DECLARE_METATYPE(KWin::LayerSurfaceV1Interface::Layer)
0027 Q_DECLARE_METATYPE(KWin::LayerSurfaceV1Interface *)
0028 
0029 using namespace KWin;
0030 
0031 class LayerShellV1 : public QtWayland::zwlr_layer_shell_v1
0032 {
0033 public:
0034     ~LayerShellV1() override
0035     {
0036         destroy();
0037     }
0038 };
0039 
0040 class LayerSurfaceV1 : public QtWayland::zwlr_layer_surface_v1
0041 {
0042 public:
0043     ~LayerSurfaceV1() override
0044     {
0045         destroy();
0046     }
0047 };
0048 
0049 class XdgShell : public QtWayland::xdg_wm_base
0050 {
0051 public:
0052     ~XdgShell()
0053     {
0054         destroy();
0055     }
0056 };
0057 
0058 class XdgSurface : public QtWayland::xdg_surface
0059 {
0060 public:
0061     ~XdgSurface()
0062     {
0063         destroy();
0064     }
0065 };
0066 
0067 class XdgPositioner : public QtWayland::xdg_positioner
0068 {
0069 public:
0070     ~XdgPositioner()
0071     {
0072         destroy();
0073     }
0074 };
0075 
0076 class XdgPopup : public QtWayland::xdg_popup
0077 {
0078 public:
0079     ~XdgPopup()
0080     {
0081         destroy();
0082     }
0083 };
0084 
0085 class TestLayerShellV1Interface : public QObject
0086 {
0087     Q_OBJECT
0088 
0089 public:
0090     ~TestLayerShellV1Interface() override;
0091 
0092 private Q_SLOTS:
0093     void initTestCase();
0094     void testDesiredSize();
0095     void testScope();
0096     void testAnchor_data();
0097     void testAnchor();
0098     void testMargins();
0099     void testExclusiveZone();
0100     void testExclusiveEdge_data();
0101     void testExclusiveEdge();
0102     void testLayer_data();
0103     void testLayer();
0104     void testPopup();
0105 
0106 private:
0107     KWayland::Client::ConnectionThread *m_connection;
0108     KWayland::Client::EventQueue *m_queue;
0109     KWayland::Client::Compositor *m_clientCompositor;
0110 
0111     QThread *m_thread;
0112     KWin::Display m_display;
0113     CompositorInterface *m_serverCompositor;
0114     LayerShellV1 *m_clientLayerShell = nullptr;
0115     LayerShellV1Interface *m_serverLayerShell = nullptr;
0116     XdgShell *m_clientXdgShell = nullptr;
0117     XdgShellInterface *m_serverXdgShell = nullptr;
0118 };
0119 
0120 static const QString s_socketName = QStringLiteral("kwin-wayland-server-layer-shell-v1-test-0");
0121 
0122 void TestLayerShellV1Interface::initTestCase()
0123 {
0124     m_display.addSocketName(s_socketName);
0125     m_display.start();
0126     QVERIFY(m_display.isRunning());
0127 
0128     m_serverLayerShell = new LayerShellV1Interface(&m_display, this);
0129     m_serverXdgShell = new XdgShellInterface(&m_display, this);
0130     m_serverCompositor = new CompositorInterface(&m_display, this);
0131 
0132     m_connection = new KWayland::Client::ConnectionThread;
0133     QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
0134     m_connection->setSocketName(s_socketName);
0135 
0136     m_thread = new QThread(this);
0137     m_connection->moveToThread(m_thread);
0138     m_thread->start();
0139 
0140     m_connection->initConnection();
0141     QVERIFY(connectedSpy.wait());
0142     QVERIFY(!m_connection->connections().isEmpty());
0143 
0144     m_queue = new KWayland::Client::EventQueue(this);
0145     QVERIFY(!m_queue->isValid());
0146     m_queue->setup(m_connection);
0147     QVERIFY(m_queue->isValid());
0148 
0149     auto registry = new KWayland::Client::Registry(this);
0150     connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry](const QByteArray &interface, quint32 id, quint32 version) {
0151         if (interface == QByteArrayLiteral("zwlr_layer_shell_v1")) {
0152             m_clientLayerShell = new LayerShellV1();
0153             m_clientLayerShell->init(*registry, id, version);
0154         }
0155         if (interface == QByteArrayLiteral("xdg_wm_base")) {
0156             m_clientXdgShell = new XdgShell();
0157             m_clientXdgShell->init(*registry, id, version);
0158         }
0159     });
0160     QSignalSpy allAnnouncedSpy(registry, &KWayland::Client::Registry::interfaceAnnounced);
0161     QSignalSpy compositorSpy(registry, &KWayland::Client::Registry::compositorAnnounced);
0162     QSignalSpy shmSpy(registry, &KWayland::Client::Registry::shmAnnounced);
0163     registry->setEventQueue(m_queue);
0164     registry->create(m_connection->display());
0165     QVERIFY(registry->isValid());
0166     registry->setup();
0167     QVERIFY(allAnnouncedSpy.wait());
0168 
0169     m_clientCompositor = registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
0170     QVERIFY(m_clientCompositor->isValid());
0171 }
0172 
0173 TestLayerShellV1Interface::~TestLayerShellV1Interface()
0174 {
0175     if (m_clientXdgShell) {
0176         delete m_clientXdgShell;
0177         m_clientXdgShell = nullptr;
0178     }
0179     if (m_clientLayerShell) {
0180         delete m_clientLayerShell;
0181         m_clientLayerShell = nullptr;
0182     }
0183     if (m_queue) {
0184         delete m_queue;
0185         m_queue = nullptr;
0186     }
0187     if (m_thread) {
0188         m_thread->quit();
0189         m_thread->wait();
0190         delete m_thread;
0191         m_thread = nullptr;
0192     }
0193     m_connection->deleteLater();
0194     m_connection = nullptr;
0195 }
0196 
0197 void TestLayerShellV1Interface::testDesiredSize()
0198 {
0199     // Create a test wl_surface object.
0200     QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0201     std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
0202     QVERIFY(serverSurfaceCreatedSpy.wait());
0203     SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0204     QVERIFY(serverSurface);
0205 
0206     // Create a test wlr_layer_surface_v1 object.
0207     std::unique_ptr<LayerSurfaceV1> clientShellSurface(new LayerSurfaceV1);
0208     clientShellSurface->init(m_clientLayerShell->get_layer_surface(*clientSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("test")));
0209     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0210     QVERIFY(layerSurfaceCreatedSpy.wait());
0211     auto serverShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0212     QVERIFY(serverShellSurface);
0213 
0214     clientShellSurface->set_size(10, 20);
0215     clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0216 
0217     QSignalSpy desiredSizeChangedSpy(serverShellSurface, &LayerSurfaceV1Interface::desiredSizeChanged);
0218     QVERIFY(desiredSizeChangedSpy.wait());
0219 
0220     QCOMPARE(serverShellSurface->desiredSize(), QSize(10, 20));
0221 }
0222 
0223 void TestLayerShellV1Interface::testScope()
0224 {
0225     // Create a test wl_surface object.
0226     QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0227     std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
0228     QVERIFY(serverSurfaceCreatedSpy.wait());
0229     SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0230     QVERIFY(serverSurface);
0231 
0232     // Create a test wlr_layer_surface_v1 object.
0233     std::unique_ptr<LayerSurfaceV1> clientShellSurface(new LayerSurfaceV1);
0234     clientShellSurface->init(m_clientLayerShell->get_layer_surface(*clientSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("foobar")));
0235     clientShellSurface->set_size(100, 50);
0236     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0237     QVERIFY(layerSurfaceCreatedSpy.wait());
0238     auto serverShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0239     QVERIFY(serverShellSurface);
0240 
0241     QCOMPARE(serverShellSurface->scope(), QStringLiteral("foobar"));
0242 }
0243 
0244 void TestLayerShellV1Interface::testAnchor_data()
0245 {
0246     QTest::addColumn<int>("anchor");
0247     QTest::addColumn<Qt::Edge>("expected");
0248 
0249     QTest::addRow("left") << int(QtWayland::zwlr_layer_surface_v1::anchor_left) << Qt::LeftEdge;
0250     QTest::addRow("right") << int(QtWayland::zwlr_layer_surface_v1::anchor_right) << Qt::RightEdge;
0251     QTest::addRow("top") << int(QtWayland::zwlr_layer_surface_v1::anchor_top) << Qt::TopEdge;
0252     QTest::addRow("bottom") << int(QtWayland::zwlr_layer_surface_v1::anchor_bottom) << Qt::BottomEdge;
0253 }
0254 
0255 void TestLayerShellV1Interface::testAnchor()
0256 {
0257     // Create a test wl_surface object.
0258     QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0259     std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
0260     QVERIFY(serverSurfaceCreatedSpy.wait());
0261     SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0262     QVERIFY(serverSurface);
0263 
0264     // Create a test wlr_layer_surface_v1 object.
0265     std::unique_ptr<LayerSurfaceV1> clientShellSurface(new LayerSurfaceV1);
0266     clientShellSurface->init(m_clientLayerShell->get_layer_surface(*clientSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("test")));
0267     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0268     QVERIFY(layerSurfaceCreatedSpy.wait());
0269     auto serverShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0270     QVERIFY(serverShellSurface);
0271 
0272     QFETCH(int, anchor);
0273     QFETCH(Qt::Edge, expected);
0274 
0275     clientShellSurface->set_anchor(anchor);
0276     clientShellSurface->set_size(100, 50);
0277     clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0278 
0279     QSignalSpy anchorChangedSpy(serverShellSurface, &LayerSurfaceV1Interface::anchorChanged);
0280     QVERIFY(anchorChangedSpy.wait());
0281 
0282     QCOMPARE(serverShellSurface->anchor(), expected);
0283 }
0284 
0285 void TestLayerShellV1Interface::testMargins()
0286 {
0287     // Create a test wl_surface object.
0288     QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0289     std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
0290     QVERIFY(serverSurfaceCreatedSpy.wait());
0291     SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0292     QVERIFY(serverSurface);
0293 
0294     // Create a test wlr_layer_surface_v1 object.
0295     std::unique_ptr<LayerSurfaceV1> clientShellSurface(new LayerSurfaceV1);
0296     clientShellSurface->init(m_clientLayerShell->get_layer_surface(*clientSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("test")));
0297     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0298     QVERIFY(layerSurfaceCreatedSpy.wait());
0299     auto serverShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0300     QVERIFY(serverShellSurface);
0301 
0302     clientShellSurface->set_margin(10, 20, 30, 40);
0303     clientShellSurface->set_size(100, 50);
0304     clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0305 
0306     QSignalSpy marginsChangedSpy(serverShellSurface, &LayerSurfaceV1Interface::marginsChanged);
0307     QVERIFY(marginsChangedSpy.wait());
0308 
0309     QCOMPARE(serverShellSurface->margins(), QMargins(40, 10, 20, 30));
0310 }
0311 
0312 void TestLayerShellV1Interface::testExclusiveZone()
0313 {
0314     // Create a test wl_surface object.
0315     QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0316     std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
0317     QVERIFY(serverSurfaceCreatedSpy.wait());
0318     SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0319     QVERIFY(serverSurface);
0320 
0321     // Create a test wlr_layer_surface_v1 object.
0322     std::unique_ptr<LayerSurfaceV1> clientShellSurface(new LayerSurfaceV1);
0323     clientShellSurface->init(m_clientLayerShell->get_layer_surface(*clientSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("test")));
0324     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0325     QVERIFY(layerSurfaceCreatedSpy.wait());
0326     auto serverShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0327     QVERIFY(serverShellSurface);
0328 
0329     clientShellSurface->set_exclusive_zone(10);
0330     clientShellSurface->set_size(100, 50);
0331     clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0332 
0333     QSignalSpy exclusiveZoneChangedSpy(serverShellSurface, &LayerSurfaceV1Interface::exclusiveZoneChanged);
0334     QVERIFY(exclusiveZoneChangedSpy.wait());
0335 
0336     QCOMPARE(serverShellSurface->exclusiveZone(), 10);
0337 }
0338 
0339 void TestLayerShellV1Interface::testExclusiveEdge_data()
0340 {
0341     QTest::addColumn<int>("anchor");
0342     QTest::addColumn<Qt::Edge>("expected");
0343 
0344     QTest::addRow("left (singular)") << int(QtWayland::zwlr_layer_surface_v1::anchor_left) << Qt::LeftEdge;
0345 
0346     QTest::addRow("left (triplet)") << (QtWayland::zwlr_layer_surface_v1::anchor_bottom | QtWayland::zwlr_layer_surface_v1::anchor_left
0347                                         | QtWayland::zwlr_layer_surface_v1::anchor_top)
0348                                     << Qt::LeftEdge;
0349 
0350     QTest::addRow("right (singular)") << int(QtWayland::zwlr_layer_surface_v1::anchor_right) << Qt::RightEdge;
0351 
0352     QTest::addRow("right (triplet)") << (QtWayland::zwlr_layer_surface_v1::anchor_top | QtWayland::zwlr_layer_surface_v1::anchor_right
0353                                          | QtWayland::zwlr_layer_surface_v1::anchor_bottom)
0354                                      << Qt::RightEdge;
0355 
0356     QTest::addRow("top (singular)") << int(QtWayland::zwlr_layer_surface_v1::anchor_top) << Qt::TopEdge;
0357 
0358     QTest::addRow("top (triplet)") << (QtWayland::zwlr_layer_surface_v1::anchor_left | QtWayland::zwlr_layer_surface_v1::anchor_top
0359                                        | QtWayland::zwlr_layer_surface_v1::anchor_right)
0360                                    << Qt::TopEdge;
0361 
0362     QTest::addRow("bottom (singular)") << int(QtWayland::zwlr_layer_surface_v1::anchor_bottom) << Qt::BottomEdge;
0363 
0364     QTest::addRow("bottom (triplet)") << (QtWayland::zwlr_layer_surface_v1::anchor_right | QtWayland::zwlr_layer_surface_v1::anchor_bottom
0365                                           | QtWayland::zwlr_layer_surface_v1::anchor_left)
0366                                       << Qt::BottomEdge;
0367 
0368     QTest::addRow("all") << (QtWayland::zwlr_layer_surface_v1::anchor_left | QtWayland::zwlr_layer_surface_v1::anchor_right
0369                              | QtWayland::zwlr_layer_surface_v1::anchor_top | QtWayland::zwlr_layer_surface_v1::anchor_bottom)
0370                          << Qt::Edge();
0371 }
0372 
0373 void TestLayerShellV1Interface::testExclusiveEdge()
0374 {
0375     // Create a test wl_surface object.
0376     QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0377     std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
0378     QVERIFY(serverSurfaceCreatedSpy.wait());
0379     SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0380     QVERIFY(serverSurface);
0381 
0382     // Create a test wlr_layer_surface_v1 object.
0383     std::unique_ptr<LayerSurfaceV1> clientShellSurface(new LayerSurfaceV1);
0384     clientShellSurface->init(m_clientLayerShell->get_layer_surface(*clientSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("test")));
0385     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0386     QVERIFY(layerSurfaceCreatedSpy.wait());
0387     auto serverShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0388     QVERIFY(serverShellSurface);
0389 
0390     QFETCH(int, anchor);
0391     QFETCH(Qt::Edge, expected);
0392 
0393     clientShellSurface->set_exclusive_zone(10);
0394     clientShellSurface->set_size(100, 50);
0395     clientShellSurface->set_anchor(anchor);
0396     clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0397 
0398     QSignalSpy anchorChangedSpy(serverShellSurface, &LayerSurfaceV1Interface::anchorChanged);
0399     QVERIFY(anchorChangedSpy.wait());
0400 
0401     QCOMPARE(serverShellSurface->exclusiveEdge(), expected);
0402 }
0403 
0404 void TestLayerShellV1Interface::testLayer_data()
0405 {
0406     QTest::addColumn<int>("layer");
0407     QTest::addColumn<LayerSurfaceV1Interface::Layer>("expected");
0408 
0409     QTest::addRow("overlay") << int(QtWayland::zwlr_layer_shell_v1::layer_overlay) << LayerSurfaceV1Interface::OverlayLayer;
0410     QTest::addRow("top") << int(QtWayland::zwlr_layer_shell_v1::layer_top) << LayerSurfaceV1Interface::TopLayer;
0411     QTest::addRow("bottom") << int(QtWayland::zwlr_layer_shell_v1::layer_bottom) << LayerSurfaceV1Interface::BottomLayer;
0412     QTest::addRow("background") << int(QtWayland::zwlr_layer_shell_v1::layer_background) << LayerSurfaceV1Interface::BackgroundLayer;
0413 }
0414 
0415 void TestLayerShellV1Interface::testLayer()
0416 {
0417     // Create a test wl_surface object.
0418     QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0419     std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this));
0420     QVERIFY(serverSurfaceCreatedSpy.wait());
0421     SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>();
0422     QVERIFY(serverSurface);
0423 
0424     // Create a test wlr_layer_surface_v1 object.
0425     std::unique_ptr<LayerSurfaceV1> clientShellSurface(new LayerSurfaceV1);
0426     clientShellSurface->init(m_clientLayerShell->get_layer_surface(*clientSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("test")));
0427     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0428     QVERIFY(layerSurfaceCreatedSpy.wait());
0429     auto serverShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0430     QVERIFY(serverShellSurface);
0431 
0432     QFETCH(int, layer);
0433     QFETCH(LayerSurfaceV1Interface::Layer, expected);
0434 
0435     clientShellSurface->set_layer(layer);
0436     clientShellSurface->set_size(100, 50);
0437     clientSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0438 
0439     QSignalSpy committedSpy(serverSurface, &SurfaceInterface::committed);
0440     QVERIFY(committedSpy.wait());
0441 
0442     QCOMPARE(serverShellSurface->layer(), expected);
0443 }
0444 
0445 void TestLayerShellV1Interface::testPopup()
0446 {
0447     // Create a test wl_surface object for the panel.
0448     QSignalSpy serverPanelSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated);
0449     std::unique_ptr<KWayland::Client::Surface> clientPanelSurface(m_clientCompositor->createSurface(this));
0450     QVERIFY(serverPanelSurfaceCreatedSpy.wait());
0451     SurfaceInterface *serverPanelSurface = serverPanelSurfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0452     QVERIFY(serverPanelSurface);
0453 
0454     // Create a test wlr_layer_surface_v1 object for the panel..
0455     std::unique_ptr<LayerSurfaceV1> clientPanelShellSurface(new LayerSurfaceV1);
0456     clientPanelShellSurface->init(m_clientLayerShell->get_layer_surface(*clientPanelSurface, nullptr, LayerShellV1::layer_top, QStringLiteral("panel")));
0457     clientPanelShellSurface->set_size(100, 50);
0458     QSignalSpy layerSurfaceCreatedSpy(m_serverLayerShell, &LayerShellV1Interface::surfaceCreated);
0459     QVERIFY(layerSurfaceCreatedSpy.wait());
0460     auto serverPanelShellSurface = layerSurfaceCreatedSpy.last().first().value<LayerSurfaceV1Interface *>();
0461     QVERIFY(serverPanelShellSurface);
0462 
0463     // Create a wl_surface object for the popup.
0464     std::unique_ptr<KWayland::Client::Surface> clientPopupSurface(m_clientCompositor->createSurface(this));
0465     QVERIFY(serverPanelSurfaceCreatedSpy.wait());
0466     SurfaceInterface *serverPopupSurface = serverPanelSurfaceCreatedSpy.last().first().value<SurfaceInterface *>();
0467     QVERIFY(serverPopupSurface);
0468 
0469     // Create an xdg_surface object for the popup.
0470     std::unique_ptr<XdgSurface> clientXdgSurface(new XdgSurface);
0471     clientXdgSurface->init(m_clientXdgShell->get_xdg_surface(*clientPopupSurface));
0472 
0473     // Create an xdg_positioner object for the popup.
0474     std::unique_ptr<::XdgPositioner> positioner(new ::XdgPositioner);
0475     positioner->init(m_clientXdgShell->create_positioner());
0476     positioner->set_size(100, 100);
0477     positioner->set_anchor_rect(0, 0, 10, 10);
0478 
0479     // Create an xdg_popup surface.
0480     std::unique_ptr<XdgPopup> clientXdgPopup(new XdgPopup);
0481     clientXdgPopup->init(clientXdgSurface->get_popup(nullptr, positioner->object()));
0482 
0483     // Wait for the server side to catch up.
0484     QSignalSpy popupCreatedSpy(m_serverXdgShell, &XdgShellInterface::popupCreated);
0485     QVERIFY(popupCreatedSpy.wait());
0486     XdgPopupInterface *serverPopupShellSurface = popupCreatedSpy.last().first().value<XdgPopupInterface *>();
0487     QVERIFY(serverPopupShellSurface);
0488     QCOMPARE(serverPopupShellSurface->parentSurface(), nullptr);
0489 
0490     // Make the xdg_popup surface a child of the panel.
0491     clientPanelShellSurface->get_popup(clientXdgPopup->object());
0492 
0493     // Commit the initial state of the xdg_popup surface.
0494     clientPopupSurface->commit(KWayland::Client::Surface::CommitFlag::None);
0495     QSignalSpy initializeRequestedSpy(serverPopupShellSurface, &XdgPopupInterface::initializeRequested);
0496     QVERIFY(initializeRequestedSpy.wait());
0497 
0498     // The popup should be a transient for the panel.
0499     QCOMPARE(serverPopupShellSurface->parentSurface(), serverPanelSurface);
0500 }
0501 
0502 QTEST_GUILESS_MAIN(TestLayerShellV1Interface)
0503 
0504 #include "test_layershellv1_interface.moc"