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/compositor_interface.h"
10 #include "../../src/server/display.h"
11 #include "../../src/server/slide_interface.h"
12 #include "KWayland/Client/compositor.h"
13 #include "KWayland/Client/connection_thread.h"
14 #include "KWayland/Client/event_queue.h"
15 #include "KWayland/Client/region.h"
16 #include "KWayland/Client/registry.h"
17 #include "KWayland/Client/slide.h"
18 #include "KWayland/Client/surface.h"
19 
20 using namespace KWayland::Client;
21 
22 class TestSlide : public QObject
23 {
24     Q_OBJECT
25 public:
26     explicit TestSlide(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::SlideManagerInterface *m_slideManagerInterface;
38     KWayland::Client::ConnectionThread *m_connection;
39     KWayland::Client::Compositor *m_compositor;
40     KWayland::Client::SlideManager *m_slideManager;
41     KWayland::Client::EventQueue *m_queue;
42     QThread *m_thread;
43 };
44 
45 static const QString s_socketName = QStringLiteral("kwayland-test-wayland-slide-0");
46 
TestSlide(QObject * parent)47 TestSlide::TestSlide(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 TestSlide::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     m_connection->setSocketName(s_socketName);
71 
72     m_thread = new QThread(this);
73     m_connection->moveToThread(m_thread);
74     m_thread->start();
75 
76     m_connection->initConnection();
77     QVERIFY(connectedSpy.wait());
78 
79     m_queue = new KWayland::Client::EventQueue(this);
80     QVERIFY(!m_queue->isValid());
81     m_queue->setup(m_connection);
82     QVERIFY(m_queue->isValid());
83 
84     Registry registry;
85     QSignalSpy compositorSpy(&registry, &Registry::compositorAnnounced);
86     QVERIFY(compositorSpy.isValid());
87 
88     QSignalSpy slideSpy(&registry, &Registry::slideAnnounced);
89     QVERIFY(slideSpy.isValid());
90 
91     QVERIFY(!registry.eventQueue());
92     registry.setEventQueue(m_queue);
93     QCOMPARE(registry.eventQueue(), m_queue);
94     registry.create(m_connection->display());
95     QVERIFY(registry.isValid());
96     registry.setup();
97 
98     m_compositorInterface = new CompositorInterface(m_display, m_display);
99     QVERIFY(compositorSpy.wait());
100     m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this);
101 
102     m_slideManagerInterface = new SlideManagerInterface(m_display, m_display);
103 
104     QVERIFY(slideSpy.wait());
105     m_slideManager = registry.createSlideManager(slideSpy.first().first().value<quint32>(), slideSpy.first().last().value<quint32>(), this);
106 }
107 
cleanup()108 void TestSlide::cleanup()
109 {
110 #define CLEANUP(variable)                                                                                                                                      \
111     if (variable) {                                                                                                                                            \
112         delete variable;                                                                                                                                       \
113         variable = nullptr;                                                                                                                                    \
114     }
115     CLEANUP(m_compositor)
116     CLEANUP(m_slideManager)
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     // these are the children of the display
131     m_compositorInterface = nullptr;
132     m_slideManagerInterface = nullptr;
133 }
134 
testCreate()135 void TestSlide::testCreate()
136 {
137     QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWaylandServer::CompositorInterface::surfaceCreated);
138     QVERIFY(serverSurfaceCreated.isValid());
139 
140     QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
141     QVERIFY(serverSurfaceCreated.wait());
142 
143     auto serverSurface = serverSurfaceCreated.first().first().value<KWaylandServer::SurfaceInterface *>();
144     QSignalSpy slideChanged(serverSurface, &KWaylandServer::SurfaceInterface::slideOnShowHideChanged);
145 
146     auto slide = m_slideManager->createSlide(surface.data(), surface.data());
147     slide->setLocation(KWayland::Client::Slide::Location::Top);
148     slide->setOffset(15);
149     slide->commit();
150     surface->commit(KWayland::Client::Surface::CommitFlag::None);
151 
152     QVERIFY(slideChanged.wait());
153     QCOMPARE(serverSurface->slideOnShowHide()->location(), KWaylandServer::SlideInterface::Location::Top);
154     QCOMPARE(serverSurface->slideOnShowHide()->offset(), 15);
155 
156     // and destroy
157     QSignalSpy destroyedSpy(serverSurface->slideOnShowHide().data(), &QObject::destroyed);
158     QVERIFY(destroyedSpy.isValid());
159     delete slide;
160     QVERIFY(destroyedSpy.wait());
161 }
162 
testSurfaceDestroy()163 void TestSlide::testSurfaceDestroy()
164 {
165     using namespace KWaylandServer;
166     QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated);
167     QVERIFY(serverSurfaceCreated.isValid());
168 
169     QScopedPointer<KWayland::Client::Surface> surface(m_compositor->createSurface());
170     QVERIFY(serverSurfaceCreated.wait());
171 
172     auto serverSurface = serverSurfaceCreated.first().first().value<SurfaceInterface *>();
173     QSignalSpy slideChanged(serverSurface, &SurfaceInterface::slideOnShowHideChanged);
174     QVERIFY(slideChanged.isValid());
175 
176     QScopedPointer<Slide> slide(m_slideManager->createSlide(surface.data()));
177     slide->commit();
178     surface->commit(KWayland::Client::Surface::CommitFlag::None);
179     QVERIFY(slideChanged.wait());
180     auto serverSlide = serverSurface->slideOnShowHide();
181     QVERIFY(!serverSlide.isNull());
182 
183     // destroy the parent surface
184     QSignalSpy surfaceDestroyedSpy(serverSurface, &QObject::destroyed);
185     QVERIFY(surfaceDestroyedSpy.isValid());
186     QSignalSpy slideDestroyedSpy(serverSlide.data(), &QObject::destroyed);
187     QVERIFY(slideDestroyedSpy.isValid());
188     surface.reset();
189     QVERIFY(surfaceDestroyedSpy.wait());
190     QVERIFY(slideDestroyedSpy.isEmpty());
191     // destroy the slide
192     slide.reset();
193     QVERIFY(slideDestroyedSpy.wait());
194 }
195 
196 QTEST_GUILESS_MAIN(TestSlide)
197 #include "test_wayland_slide.moc"
198