1 /*
2     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@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 <QtTest>
8 // KWin
9 #include "../../src/server/blur_interface.h"
10 #include "../../src/server/compositor_interface.h"
11 #include "../../src/server/display.h"
12 #include "KWayland/Client/blur.h"
13 #include "KWayland/Client/compositor.h"
14 #include "KWayland/Client/connection_thread.h"
15 #include "KWayland/Client/event_queue.h"
16 #include "KWayland/Client/region.h"
17 #include "KWayland/Client/registry.h"
18 #include "KWayland/Client/surface.h"
19 
20 using namespace KWayland::Client;
21 
22 class TestBlur : public QObject
23 {
24     Q_OBJECT
25 public:
26     explicit TestBlur(QObject *parent = nullptr);
27 private Q_SLOTS:
28     void init();
29     void cleanup();
30 
31     void testCreate();
32     void testSurfaceDestroy();
33 
34 private:
35     KWaylandServer::Display *m_display;
36     KWaylandServer::CompositorInterface *m_compositorInterface;
37     KWaylandServer::BlurManagerInterface *m_blurManagerInterface;
38     KWayland::Client::ConnectionThread *m_connection;
39     KWayland::Client::Compositor *m_compositor;
40     KWayland::Client::BlurManager *m_blurManager;
41     KWayland::Client::EventQueue *m_queue;
42     QThread *m_thread;
43 };
44 
45 static const QString s_socketName = QStringLiteral("kwayland-test-wayland-blur-0");
46 
TestBlur(QObject * parent)47 TestBlur::TestBlur(QObject *parent)
48     : QObject(parent)
49     , m_display(nullptr)
50     , m_compositorInterface(nullptr)
51     , m_connection(nullptr)
52     , m_compositor(nullptr)
53     , m_queue(nullptr)
54     , m_thread(nullptr)
55 {
56 }
57 
init()58 void TestBlur::init()
59 {
60     using namespace KWaylandServer;
61     delete m_display;
62     m_display = new Display(this);
63     m_display->addSocketName(s_socketName);
64     m_display->start();
65     QVERIFY(m_display->isRunning());
66 
67     // setup connection
68     m_connection = new KWayland::Client::ConnectionThread;
69     QSignalSpy connectedSpy(m_connection, &ConnectionThread::connected);
70     QVERIFY(connectedSpy.isValid());
71     m_connection->setSocketName(s_socketName);
72 
73     m_thread = new QThread(this);
74     m_connection->moveToThread(m_thread);
75     m_thread->start();
76 
77     m_connection->initConnection();
78     QVERIFY(connectedSpy.wait());
79 
80     m_queue = new KWayland::Client::EventQueue(this);
81     QVERIFY(!m_queue->isValid());
82     m_queue->setup(m_connection);
83     QVERIFY(m_queue->isValid());
84 
85     Registry registry;
86     QSignalSpy compositorSpy(&registry, &Registry::compositorAnnounced);
87     QVERIFY(compositorSpy.isValid());
88 
89     QSignalSpy blurSpy(&registry, &Registry::blurAnnounced);
90     QVERIFY(blurSpy.isValid());
91 
92     QVERIFY(!registry.eventQueue());
93     registry.setEventQueue(m_queue);
94     QCOMPARE(registry.eventQueue(), m_queue);
95     registry.create(m_connection->display());
96     QVERIFY(registry.isValid());
97     registry.setup();
98 
99     m_compositorInterface = new CompositorInterface(m_display, m_display);
100     QVERIFY(compositorSpy.wait());
101     m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
102 
103     m_blurManagerInterface = new BlurManagerInterface(m_display, m_display);
104     QVERIFY(blurSpy.wait());
105     m_blurManager = registry.createBlurManager(blurSpy.first().first().value<quint32>(), blurSpy.first().last().value<quint32>(), this);
106 }
107 
cleanup()108 void TestBlur::cleanup()
109 {
110 #define CLEANUP(variable)                                                                                                                                      \
111     if (variable) {                                                                                                                                            \
112         delete variable;                                                                                                                                       \
113         variable = nullptr;                                                                                                                                    \
114     }
115     CLEANUP(m_compositor)
116     CLEANUP(m_blurManager)
117     CLEANUP(m_queue)
118     if (m_connection) {
119         m_connection->deleteLater();
120         m_connection = nullptr;
121     }
122     if (m_thread) {
123         m_thread->quit();
124         m_thread->wait();
125         delete m_thread;
126         m_thread = nullptr;
127     }
128     CLEANUP(m_display)
129 #undef CLEANUP
130 
131     // these are the children of the display
132     m_compositorInterface = nullptr;
133     m_blurManagerInterface = nullptr;
134 }
135 
testCreate()136 void TestBlur::testCreate()
137 {
138     QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWaylandServer::CompositorInterface::surfaceCreated);
139     QVERIFY(serverSurfaceCreated.isValid());
140 
141     QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
142     QVERIFY(serverSurfaceCreated.wait());
143 
144     auto serverSurface = serverSurfaceCreated.first().first().value<KWaylandServer::SurfaceInterface *>();
145     QSignalSpy blurChanged(serverSurface, &KWaylandServer::SurfaceInterface::blurChanged);
146 
147     auto blur = m_blurManager->createBlur(surface.data(), surface.data());
148     blur->setRegion(m_compositor->createRegion(QRegion(0, 0, 10, 20), nullptr));
149     blur->commit();
150     surface->commit(KWayland::Client::Surface::CommitFlag::None);
151 
152     QVERIFY(blurChanged.wait());
153     QCOMPARE(serverSurface->blur()->region(), QRegion(0, 0, 10, 20));
154 
155     // and destroy
156     QSignalSpy destroyedSpy(serverSurface->blur().data(), &QObject::destroyed);
157     QVERIFY(destroyedSpy.isValid());
158     delete blur;
159     QVERIFY(destroyedSpy.wait());
160 }
161 
testSurfaceDestroy()162 void TestBlur::testSurfaceDestroy()
163 {
164     QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWaylandServer::CompositorInterface::surfaceCreated);
165     QVERIFY(serverSurfaceCreated.isValid());
166 
167     QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
168     QVERIFY(serverSurfaceCreated.wait());
169 
170     auto serverSurface = serverSurfaceCreated.first().first().value<KWaylandServer::SurfaceInterface *>();
171     QSignalSpy blurChanged(serverSurface, &KWaylandServer::SurfaceInterface::blurChanged);
172     QVERIFY(blurChanged.isValid());
173 
174     QScopedPointer<KWayland::Client::Blur> blur(m_blurManager->createBlur(surface.data()));
175     blur->setRegion(m_compositor->createRegion(QRegion(0, 0, 10, 20), nullptr));
176     blur->commit();
177     surface->commit(KWayland::Client::Surface::CommitFlag::None);
178 
179     QVERIFY(blurChanged.wait());
180     QCOMPARE(serverSurface->blur()->region(), QRegion(0, 0, 10, 20));
181 
182     // destroy the parent surface
183     QSignalSpy surfaceDestroyedSpy(serverSurface, &QObject::destroyed);
184     QVERIFY(surfaceDestroyedSpy.isValid());
185     QSignalSpy blurDestroyedSpy(serverSurface->blur().data(), &QObject::destroyed);
186     QVERIFY(blurDestroyedSpy.isValid());
187     surface.reset();
188     QVERIFY(surfaceDestroyedSpy.wait());
189     QVERIFY(blurDestroyedSpy.isEmpty());
190     // destroy the blur
191     blur.reset();
192     QVERIFY(blurDestroyedSpy.wait());
193 }
194 
195 QTEST_GUILESS_MAIN(TestBlur)
196 #include "test_wayland_blur.moc"
197