KWin
Loading...
Searching...
No Matches
test_xdg_decoration.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6// Qt
7#include <QSignalSpy>
8#include <QTest>
9// KWin
10#include "wayland/compositor.h"
11#include "wayland/display.h"
13#include "wayland/xdgshell.h"
14
15#include "KWayland/Client/compositor.h"
16#include "KWayland/Client/connection_thread.h"
17#include "KWayland/Client/event_queue.h"
18#include "KWayland/Client/registry.h"
19#include "KWayland/Client/surface.h"
20#include "KWayland/Client/xdgdecoration.h"
21#include "KWayland/Client/xdgshell.h"
22
23class TestXdgDecoration : public QObject
24{
25 Q_OBJECT
26public:
27 explicit TestXdgDecoration(QObject *parent = nullptr);
28private Q_SLOTS:
29 void init();
30 void cleanup();
31
32 void testDecoration_data();
33 void testDecoration();
34
35private:
36 KWin::Display *m_display = nullptr;
37 KWin::CompositorInterface *m_compositorInterface = nullptr;
38 KWin::XdgShellInterface *m_xdgShellInterface = nullptr;
39 KWin::XdgDecorationManagerV1Interface *m_xdgDecorationManagerInterface = nullptr;
40
41 KWayland::Client::ConnectionThread *m_connection = nullptr;
42 KWayland::Client::Compositor *m_compositor = nullptr;
43 KWayland::Client::EventQueue *m_queue = nullptr;
44 KWayland::Client::XdgShell *m_xdgShell = nullptr;
45 KWayland::Client::XdgDecorationManager *m_xdgDecorationManager = nullptr;
46
47 QThread *m_thread = nullptr;
48 KWayland::Client::Registry *m_registry = nullptr;
49};
50
51static const QString s_socketName = QStringLiteral("kwayland-test-wayland-server-side-decoration-0");
52
54 : QObject(parent)
55{
56}
57
58void TestXdgDecoration::init()
59{
60 using namespace KWin;
61
62 qRegisterMetaType<KWayland::Client::XdgDecoration::Mode>();
63 qRegisterMetaType<XdgToplevelDecorationV1Interface::Mode>();
64
65 delete m_display;
66 m_display = new KWin::Display(this);
67 m_display->addSocketName(s_socketName);
68 m_display->start();
69 QVERIFY(m_display->isRunning());
70
71 // setup connection
72 m_connection = new KWayland::Client::ConnectionThread;
73 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected);
74 m_connection->setSocketName(s_socketName);
75
76 m_thread = new QThread(this);
77 m_connection->moveToThread(m_thread);
78 m_thread->start();
79
80 m_connection->initConnection();
81 QVERIFY(connectedSpy.wait());
82
83 m_queue = new KWayland::Client::EventQueue(this);
84 QVERIFY(!m_queue->isValid());
85 m_queue->setup(m_connection);
86 QVERIFY(m_queue->isValid());
87
88 m_registry = new KWayland::Client::Registry();
89 QSignalSpy compositorSpy(m_registry, &KWayland::Client::Registry::compositorAnnounced);
90 QSignalSpy xdgShellSpy(m_registry, &KWayland::Client::Registry::xdgShellStableAnnounced);
91 QSignalSpy xdgDecorationManagerSpy(m_registry, &KWayland::Client::Registry::xdgDecorationAnnounced);
92
93 QVERIFY(!m_registry->eventQueue());
94 m_registry->setEventQueue(m_queue);
95 QCOMPARE(m_registry->eventQueue(), m_queue);
96 m_registry->create(m_connection);
97 QVERIFY(m_registry->isValid());
98 m_registry->setup();
99
100 m_compositorInterface = new CompositorInterface(m_display, m_display);
101 QVERIFY(compositorSpy.wait());
102 m_compositor = m_registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
103
104 m_xdgShellInterface = new XdgShellInterface(m_display, m_display);
105 QVERIFY(xdgShellSpy.wait());
106 m_xdgShell = m_registry->createXdgShell(xdgShellSpy.first().first().value<quint32>(), xdgShellSpy.first().last().value<quint32>(), this);
107
108 m_xdgDecorationManagerInterface = new XdgDecorationManagerV1Interface(m_display, m_display);
109
110 QVERIFY(xdgDecorationManagerSpy.wait());
111 m_xdgDecorationManager = m_registry->createXdgDecorationManager(xdgDecorationManagerSpy.first().first().value<quint32>(),
112 xdgDecorationManagerSpy.first().last().value<quint32>(),
113 this);
114}
115
116void TestXdgDecoration::cleanup()
117{
118 if (m_compositor) {
119 delete m_compositor;
120 m_compositor = nullptr;
121 }
122 if (m_xdgShell) {
123 delete m_xdgShell;
124 m_xdgShell = nullptr;
125 }
126 if (m_xdgDecorationManager) {
127 delete m_xdgDecorationManager;
128 m_xdgDecorationManager = nullptr;
129 }
130 if (m_queue) {
131 delete m_queue;
132 m_queue = nullptr;
133 }
134 if (m_registry) {
135 delete m_registry;
136 m_registry = nullptr;
137 }
138 if (m_thread) {
139 m_thread->quit();
140 m_thread->wait();
141 delete m_thread;
142 m_thread = nullptr;
143 }
144 delete m_connection;
145 m_connection = nullptr;
146
147 delete m_display;
148 m_display = nullptr;
149}
150
151void TestXdgDecoration::testDecoration_data()
152{
153 using namespace KWin;
154 QTest::addColumn<KWin::XdgToplevelDecorationV1Interface::Mode>("configuredMode");
155 QTest::addColumn<KWayland::Client::XdgDecoration::Mode>("configuredModeExp");
156 QTest::addColumn<KWayland::Client::XdgDecoration::Mode>("setMode");
157 QTest::addColumn<KWin::XdgToplevelDecorationV1Interface::Mode>("setModeExp");
158
159 const auto serverClient = XdgToplevelDecorationV1Interface::Mode::Client;
160 const auto serverServer = XdgToplevelDecorationV1Interface::Mode::Server;
161 const auto clientClient = KWayland::Client::XdgDecoration::Mode::ClientSide;
162 const auto clientServer = KWayland::Client::XdgDecoration::Mode::ServerSide;
163
164 QTest::newRow("client->client") << serverClient << clientClient << clientClient << serverClient;
165 QTest::newRow("client->server") << serverClient << clientClient << clientServer << serverServer;
166 QTest::newRow("server->client") << serverServer << clientServer << clientClient << serverClient;
167 QTest::newRow("server->server") << serverServer << clientServer << clientServer << serverServer;
168}
169
170void TestXdgDecoration::testDecoration()
171{
172 using namespace KWin;
173
174 QFETCH(KWin::XdgToplevelDecorationV1Interface::Mode, configuredMode);
175 QFETCH(KWayland::Client::XdgDecoration::Mode, configuredModeExp);
176 QFETCH(KWayland::Client::XdgDecoration::Mode, setMode);
178
179 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated);
180 QSignalSpy shellSurfaceCreatedSpy(m_xdgShellInterface, &XdgShellInterface::toplevelCreated);
181 QSignalSpy decorationCreatedSpy(m_xdgDecorationManagerInterface, &XdgDecorationManagerV1Interface::decorationCreated);
182
183 // create shell surface and deco object
184 std::unique_ptr<KWayland::Client::Surface> surface(m_compositor->createSurface());
185 std::unique_ptr<KWayland::Client::XdgShellSurface> shellSurface(m_xdgShell->createSurface(surface.get()));
186 std::unique_ptr<KWayland::Client::XdgDecoration> decoration(m_xdgDecorationManager->getToplevelDecoration(shellSurface.get()));
187
188 // and receive all these on the "server"
189 QVERIFY(surfaceCreatedSpy.count() || surfaceCreatedSpy.wait());
190 QVERIFY(shellSurfaceCreatedSpy.count() || shellSurfaceCreatedSpy.wait());
191 QVERIFY(decorationCreatedSpy.count() || decorationCreatedSpy.wait());
192
193 auto shellSurfaceIface = shellSurfaceCreatedSpy.first().first().value<XdgToplevelInterface *>();
194 auto decorationIface = decorationCreatedSpy.first().first().value<XdgToplevelDecorationV1Interface *>();
195
196 QVERIFY(decorationIface);
197 QVERIFY(shellSurfaceIface);
198 QCOMPARE(decorationIface->toplevel(), shellSurfaceIface);
199 QCOMPARE(decorationIface->preferredMode(), XdgToplevelDecorationV1Interface::Mode::Undefined);
200
201 QSignalSpy clientConfiguredSpy(decoration.get(), &KWayland::Client::XdgDecoration::modeChanged);
202 QSignalSpy modeRequestedSpy(decorationIface, &XdgToplevelDecorationV1Interface::preferredModeChanged);
203
204 // server configuring a client
205 decorationIface->sendConfigure(configuredMode);
206 quint32 serial = shellSurfaceIface->sendConfigure(QSize(0, 0), {});
207 QVERIFY(clientConfiguredSpy.wait());
208 QCOMPARE(clientConfiguredSpy.first().first().value<KWayland::Client::XdgDecoration::Mode>(), configuredModeExp);
209
210 shellSurface->ackConfigure(serial);
211
212 // client requesting another mode
213 decoration->setMode(setMode);
214 QVERIFY(modeRequestedSpy.wait());
215 QCOMPARE(modeRequestedSpy.first().first().value<XdgToplevelDecorationV1Interface::Mode>(), setModeExp);
216 QCOMPARE(decorationIface->preferredMode(), setModeExp);
217 modeRequestedSpy.clear();
218
219 decoration->unsetMode();
220 QVERIFY(modeRequestedSpy.wait());
221 QCOMPARE(modeRequestedSpy.first().first().value<XdgToplevelDecorationV1Interface::Mode>(), XdgToplevelDecorationV1Interface::Mode::Undefined);
222}
223
224QTEST_GUILESS_MAIN(TestXdgDecoration)
225#include "test_xdg_decoration.moc"
Class holding the Wayland server display loop.
Definition display.h:34
bool addSocketName(const QString &name=QString())
Definition display.cpp:68
bool isRunning() const
Definition display.cpp:144
bool start()
Definition display.cpp:92
quint32 sendConfigure(const QSize &size, const States &states)
Definition xdgshell.cpp:587
TestXdgDecoration(QObject *parent=nullptr)