File indexing completed on 2024-11-10 04:56:20
0001 /* 0002 SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@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/xdgdecoration_v1.h" 0013 #include "wayland/xdgshell.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/registry.h" 0019 #include "KWayland/Client/surface.h" 0020 #include "KWayland/Client/xdgdecoration.h" 0021 #include "KWayland/Client/xdgshell.h" 0022 0023 class TestXdgDecoration : public QObject 0024 { 0025 Q_OBJECT 0026 public: 0027 explicit TestXdgDecoration(QObject *parent = nullptr); 0028 private Q_SLOTS: 0029 void init(); 0030 void cleanup(); 0031 0032 void testDecoration_data(); 0033 void testDecoration(); 0034 0035 private: 0036 KWin::Display *m_display = nullptr; 0037 KWin::CompositorInterface *m_compositorInterface = nullptr; 0038 KWin::XdgShellInterface *m_xdgShellInterface = nullptr; 0039 KWin::XdgDecorationManagerV1Interface *m_xdgDecorationManagerInterface = nullptr; 0040 0041 KWayland::Client::ConnectionThread *m_connection = nullptr; 0042 KWayland::Client::Compositor *m_compositor = nullptr; 0043 KWayland::Client::EventQueue *m_queue = nullptr; 0044 KWayland::Client::XdgShell *m_xdgShell = nullptr; 0045 KWayland::Client::XdgDecorationManager *m_xdgDecorationManager = nullptr; 0046 0047 QThread *m_thread = nullptr; 0048 KWayland::Client::Registry *m_registry = nullptr; 0049 }; 0050 0051 static const QString s_socketName = QStringLiteral("kwayland-test-wayland-server-side-decoration-0"); 0052 0053 TestXdgDecoration::TestXdgDecoration(QObject *parent) 0054 : QObject(parent) 0055 { 0056 } 0057 0058 void TestXdgDecoration::init() 0059 { 0060 using namespace KWin; 0061 0062 qRegisterMetaType<KWayland::Client::XdgDecoration::Mode>(); 0063 qRegisterMetaType<XdgToplevelDecorationV1Interface::Mode>(); 0064 0065 delete m_display; 0066 m_display = new KWin::Display(this); 0067 m_display->addSocketName(s_socketName); 0068 m_display->start(); 0069 QVERIFY(m_display->isRunning()); 0070 0071 // setup connection 0072 m_connection = new KWayland::Client::ConnectionThread; 0073 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected); 0074 m_connection->setSocketName(s_socketName); 0075 0076 m_thread = new QThread(this); 0077 m_connection->moveToThread(m_thread); 0078 m_thread->start(); 0079 0080 m_connection->initConnection(); 0081 QVERIFY(connectedSpy.wait()); 0082 0083 m_queue = new KWayland::Client::EventQueue(this); 0084 QVERIFY(!m_queue->isValid()); 0085 m_queue->setup(m_connection); 0086 QVERIFY(m_queue->isValid()); 0087 0088 m_registry = new KWayland::Client::Registry(); 0089 QSignalSpy compositorSpy(m_registry, &KWayland::Client::Registry::compositorAnnounced); 0090 QSignalSpy xdgShellSpy(m_registry, &KWayland::Client::Registry::xdgShellStableAnnounced); 0091 QSignalSpy xdgDecorationManagerSpy(m_registry, &KWayland::Client::Registry::xdgDecorationAnnounced); 0092 0093 QVERIFY(!m_registry->eventQueue()); 0094 m_registry->setEventQueue(m_queue); 0095 QCOMPARE(m_registry->eventQueue(), m_queue); 0096 m_registry->create(m_connection); 0097 QVERIFY(m_registry->isValid()); 0098 m_registry->setup(); 0099 0100 m_compositorInterface = new CompositorInterface(m_display, m_display); 0101 QVERIFY(compositorSpy.wait()); 0102 m_compositor = m_registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this); 0103 0104 m_xdgShellInterface = new XdgShellInterface(m_display, m_display); 0105 QVERIFY(xdgShellSpy.wait()); 0106 m_xdgShell = m_registry->createXdgShell(xdgShellSpy.first().first().value<quint32>(), xdgShellSpy.first().last().value<quint32>(), this); 0107 0108 m_xdgDecorationManagerInterface = new XdgDecorationManagerV1Interface(m_display, m_display); 0109 0110 QVERIFY(xdgDecorationManagerSpy.wait()); 0111 m_xdgDecorationManager = m_registry->createXdgDecorationManager(xdgDecorationManagerSpy.first().first().value<quint32>(), 0112 xdgDecorationManagerSpy.first().last().value<quint32>(), 0113 this); 0114 } 0115 0116 void TestXdgDecoration::cleanup() 0117 { 0118 if (m_compositor) { 0119 delete m_compositor; 0120 m_compositor = nullptr; 0121 } 0122 if (m_xdgShell) { 0123 delete m_xdgShell; 0124 m_xdgShell = nullptr; 0125 } 0126 if (m_xdgDecorationManager) { 0127 delete m_xdgDecorationManager; 0128 m_xdgDecorationManager = nullptr; 0129 } 0130 if (m_queue) { 0131 delete m_queue; 0132 m_queue = nullptr; 0133 } 0134 if (m_registry) { 0135 delete m_registry; 0136 m_registry = nullptr; 0137 } 0138 if (m_thread) { 0139 m_thread->quit(); 0140 m_thread->wait(); 0141 delete m_thread; 0142 m_thread = nullptr; 0143 } 0144 delete m_connection; 0145 m_connection = nullptr; 0146 0147 delete m_display; 0148 m_display = nullptr; 0149 } 0150 0151 void TestXdgDecoration::testDecoration_data() 0152 { 0153 using namespace KWin; 0154 QTest::addColumn<KWin::XdgToplevelDecorationV1Interface::Mode>("configuredMode"); 0155 QTest::addColumn<KWayland::Client::XdgDecoration::Mode>("configuredModeExp"); 0156 QTest::addColumn<KWayland::Client::XdgDecoration::Mode>("setMode"); 0157 QTest::addColumn<KWin::XdgToplevelDecorationV1Interface::Mode>("setModeExp"); 0158 0159 const auto serverClient = XdgToplevelDecorationV1Interface::Mode::Client; 0160 const auto serverServer = XdgToplevelDecorationV1Interface::Mode::Server; 0161 const auto clientClient = KWayland::Client::XdgDecoration::Mode::ClientSide; 0162 const auto clientServer = KWayland::Client::XdgDecoration::Mode::ServerSide; 0163 0164 QTest::newRow("client->client") << serverClient << clientClient << clientClient << serverClient; 0165 QTest::newRow("client->server") << serverClient << clientClient << clientServer << serverServer; 0166 QTest::newRow("server->client") << serverServer << clientServer << clientClient << serverClient; 0167 QTest::newRow("server->server") << serverServer << clientServer << clientServer << serverServer; 0168 } 0169 0170 void TestXdgDecoration::testDecoration() 0171 { 0172 using namespace KWin; 0173 0174 QFETCH(KWin::XdgToplevelDecorationV1Interface::Mode, configuredMode); 0175 QFETCH(KWayland::Client::XdgDecoration::Mode, configuredModeExp); 0176 QFETCH(KWayland::Client::XdgDecoration::Mode, setMode); 0177 QFETCH(KWin::XdgToplevelDecorationV1Interface::Mode, setModeExp); 0178 0179 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0180 QSignalSpy shellSurfaceCreatedSpy(m_xdgShellInterface, &XdgShellInterface::toplevelCreated); 0181 QSignalSpy decorationCreatedSpy(m_xdgDecorationManagerInterface, &XdgDecorationManagerV1Interface::decorationCreated); 0182 0183 // create shell surface and deco object 0184 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface()); 0185 std::unique_ptr<KWayland::Client::XdgShellSurface> shellSurface(m_xdgShell->createSurface(surface.get())); 0186 std::unique_ptr<KWayland::Client::XdgDecoration> decoration(m_xdgDecorationManager->getToplevelDecoration(shellSurface.get())); 0187 0188 // and receive all these on the "server" 0189 QVERIFY(surfaceCreatedSpy.count() || surfaceCreatedSpy.wait()); 0190 QVERIFY(shellSurfaceCreatedSpy.count() || shellSurfaceCreatedSpy.wait()); 0191 QVERIFY(decorationCreatedSpy.count() || decorationCreatedSpy.wait()); 0192 0193 auto shellSurfaceIface = shellSurfaceCreatedSpy.first().first().value<XdgToplevelInterface *>(); 0194 auto decorationIface = decorationCreatedSpy.first().first().value<XdgToplevelDecorationV1Interface *>(); 0195 0196 QVERIFY(decorationIface); 0197 QVERIFY(shellSurfaceIface); 0198 QCOMPARE(decorationIface->toplevel(), shellSurfaceIface); 0199 QCOMPARE(decorationIface->preferredMode(), XdgToplevelDecorationV1Interface::Mode::Undefined); 0200 0201 QSignalSpy clientConfiguredSpy(decoration.get(), &KWayland::Client::XdgDecoration::modeChanged); 0202 QSignalSpy modeRequestedSpy(decorationIface, &XdgToplevelDecorationV1Interface::preferredModeChanged); 0203 0204 // server configuring a client 0205 decorationIface->sendConfigure(configuredMode); 0206 quint32 serial = shellSurfaceIface->sendConfigure(QSize(0, 0), {}); 0207 QVERIFY(clientConfiguredSpy.wait()); 0208 QCOMPARE(clientConfiguredSpy.first().first().value<KWayland::Client::XdgDecoration::Mode>(), configuredModeExp); 0209 0210 shellSurface->ackConfigure(serial); 0211 0212 // client requesting another mode 0213 decoration->setMode(setMode); 0214 QVERIFY(modeRequestedSpy.wait()); 0215 QCOMPARE(modeRequestedSpy.first().first().value<XdgToplevelDecorationV1Interface::Mode>(), setModeExp); 0216 QCOMPARE(decorationIface->preferredMode(), setModeExp); 0217 modeRequestedSpy.clear(); 0218 0219 decoration->unsetMode(); 0220 QVERIFY(modeRequestedSpy.wait()); 0221 QCOMPARE(modeRequestedSpy.first().first().value<XdgToplevelDecorationV1Interface::Mode>(), XdgToplevelDecorationV1Interface::Mode::Undefined); 0222 } 0223 0224 QTEST_GUILESS_MAIN(TestXdgDecoration) 0225 #include "test_xdg_decoration.moc"