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