Changeset View
Changeset View
Standalone View
Standalone View
autotests/client/test_viewporter.cpp
- This file was added.
1 | /******************************************************************** | ||||
---|---|---|---|---|---|
2 | Copyright © 2019 Roman Gilg <subdiff@gmail.com> | ||||
3 | | ||||
4 | This library is free software; you can redistribute it and/or | ||||
5 | modify it under the terms of the GNU Lesser General Public | ||||
6 | License as published by the Free Software Foundation; either | ||||
7 | version 2.1 of the License, or (at your option) version 3, or any | ||||
8 | later version accepted by the membership of KDE e.V. (or its | ||||
9 | successor approved by the membership of KDE e.V.), which shall | ||||
10 | act as a proxy defined in Section 6 of version 3 of the license. | ||||
11 | | ||||
12 | This library is distributed in the hope that it will be useful, | ||||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||||
15 | Lesser General Public License for more details. | ||||
16 | | ||||
17 | You should have received a copy of the GNU Lesser General Public | ||||
18 | License along with this library. If not, see <http://www.gnu.org/licenses/>. | ||||
19 | *********************************************************************/ | ||||
20 | #include "../../src/client/compositor.h" | ||||
21 | #include "../../src/client/connection_thread.h" | ||||
22 | #include "../../src/client/event_queue.h" | ||||
23 | #include "../../src/client/surface.h" | ||||
24 | #include "../../src/client/region.h" | ||||
25 | #include "../../src/client/registry.h" | ||||
26 | #include "../../src/client/shm_pool.h" | ||||
27 | #include "../../src/client/viewporter.h" | ||||
28 | #include "../../src/server/buffer_interface.h" | ||||
29 | #include "../../src/server/compositor_interface.h" | ||||
30 | #include "../../src/server/display.h" | ||||
31 | #include "../../src/server/surface_interface.h" | ||||
32 | #include "../../src/server/viewporter_interface.h" | ||||
33 | | ||||
34 | #include <wayland-client-protocol.h> | ||||
35 | #include <wayland-viewporter-client-protocol.h> | ||||
36 | | ||||
37 | #include <QtTest> | ||||
38 | #include <QImage> | ||||
39 | #include <QPainter> | ||||
40 | | ||||
41 | class TestViewporter : public QObject | ||||
42 | { | ||||
43 | Q_OBJECT | ||||
44 | public: | ||||
45 | explicit TestViewporter(QObject *parent = nullptr); | ||||
46 | private Q_SLOTS: | ||||
47 | void init(); | ||||
48 | void cleanup(); | ||||
49 | | ||||
50 | void testViewportExists(); | ||||
51 | void testWithoutBuffer(); | ||||
52 | void testDestinationSize(); | ||||
53 | void testSourceRectangle(); | ||||
54 | void testDestinationSizeAndSourceRectangle(); | ||||
55 | void testDataError_data(); | ||||
56 | void testDataError(); | ||||
57 | void testBufferSizeChange(); | ||||
58 | void testDestinationSizeChange(); | ||||
59 | void testNoSurface(); | ||||
60 | | ||||
61 | private: | ||||
62 | KWayland::Server::Display *m_display; | ||||
63 | KWayland::Server::CompositorInterface *m_compositorInterface; | ||||
64 | KWayland::Server::ViewporterInterface *m_viewporterInterface; | ||||
65 | KWayland::Client::ConnectionThread *m_connection; | ||||
66 | KWayland::Client::Compositor *m_compositor; | ||||
67 | KWayland::Client::ShmPool *m_shm; | ||||
68 | KWayland::Client::EventQueue *m_queue; | ||||
69 | KWayland::Client::Viewporter *m_viewporter; | ||||
70 | QThread *m_thread; | ||||
71 | }; | ||||
72 | | ||||
73 | static const QString s_socketName = QStringLiteral("kwin-test-viewporter-0"); | ||||
74 | | ||||
75 | TestViewporter::TestViewporter(QObject *parent) | ||||
76 | : QObject(parent) | ||||
77 | , m_display(nullptr) | ||||
78 | , m_compositorInterface(nullptr) | ||||
79 | , m_connection(nullptr) | ||||
80 | , m_compositor(nullptr) | ||||
81 | , m_thread(nullptr) | ||||
82 | { | ||||
83 | } | ||||
84 | | ||||
85 | void TestViewporter::init() | ||||
86 | { | ||||
87 | using namespace KWayland::Server; | ||||
88 | delete m_display; | ||||
89 | m_display = new Display(this); | ||||
90 | m_display->setSocketName(s_socketName); | ||||
91 | m_display->start(); | ||||
92 | QVERIFY(m_display->isRunning()); | ||||
93 | m_display->createShm(); | ||||
94 | | ||||
95 | m_compositorInterface = m_display->createCompositor(m_display); | ||||
96 | QVERIFY(m_compositorInterface); | ||||
97 | m_compositorInterface->create(); | ||||
98 | QVERIFY(m_compositorInterface->isValid()); | ||||
99 | | ||||
100 | m_viewporterInterface = m_display->createViewporterInterface(m_display); | ||||
101 | QVERIFY(m_viewporterInterface); | ||||
102 | m_viewporterInterface->create(); | ||||
103 | QVERIFY(m_viewporterInterface->isValid()); | ||||
104 | | ||||
105 | // setup connection | ||||
106 | m_connection = new KWayland::Client::ConnectionThread; | ||||
107 | QSignalSpy connectedSpy(m_connection, SIGNAL(connected())); | ||||
108 | m_connection->setSocketName(s_socketName); | ||||
109 | | ||||
110 | m_thread = new QThread(this); | ||||
111 | m_connection->moveToThread(m_thread); | ||||
112 | m_thread->start(); | ||||
113 | | ||||
114 | m_connection->initConnection(); | ||||
115 | QVERIFY(connectedSpy.wait()); | ||||
116 | | ||||
117 | m_queue = new KWayland::Client::EventQueue(this); | ||||
118 | QVERIFY(!m_queue->isValid()); | ||||
119 | m_queue->setup(m_connection); | ||||
120 | QVERIFY(m_queue->isValid()); | ||||
121 | | ||||
122 | KWayland::Client::Registry registry; | ||||
123 | registry.setEventQueue(m_queue); | ||||
124 | QSignalSpy compositorSpy(®istry, SIGNAL(compositorAnnounced(quint32,quint32))); | ||||
125 | QSignalSpy shmSpy(®istry, SIGNAL(shmAnnounced(quint32,quint32))); | ||||
126 | QSignalSpy viewporterSpy(®istry, SIGNAL(viewporterAnnounced(quint32,quint32))); | ||||
127 | QSignalSpy allAnnounced(®istry, SIGNAL(interfacesAnnounced())); | ||||
128 | QVERIFY(allAnnounced.isValid()); | ||||
129 | QVERIFY(shmSpy.isValid()); | ||||
130 | registry.create(m_connection->display()); | ||||
131 | QVERIFY(registry.isValid()); | ||||
132 | registry.setup(); | ||||
133 | QVERIFY(allAnnounced.wait()); | ||||
134 | QVERIFY(!compositorSpy.isEmpty()); | ||||
135 | QVERIFY(!shmSpy.isEmpty()); | ||||
136 | QVERIFY(!viewporterSpy.isEmpty()); | ||||
137 | | ||||
138 | m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), | ||||
139 | compositorSpy.first().last().value<quint32>(), this); | ||||
140 | QVERIFY(m_compositor->isValid()); | ||||
141 | m_shm = registry.createShmPool(shmSpy.first().first().value<quint32>(), | ||||
142 | shmSpy.first().last().value<quint32>(), this); | ||||
143 | QVERIFY(m_shm->isValid()); | ||||
144 | | ||||
145 | m_viewporter = registry.createViewporter( | ||||
146 | registry.interface(KWayland::Client::Registry::Interface::Viewporter).name, | ||||
147 | registry.interface(KWayland::Client::Registry::Interface::Viewporter).version, | ||||
148 | this); | ||||
149 | QVERIFY(m_viewporter->isValid()); | ||||
150 | } | ||||
151 | | ||||
152 | void TestViewporter::cleanup() | ||||
153 | { | ||||
154 | if (m_compositor) { | ||||
155 | delete m_compositor; | ||||
156 | m_compositor = nullptr; | ||||
157 | } | ||||
158 | if (m_viewporter) { | ||||
159 | delete m_viewporter; | ||||
160 | m_viewporter = nullptr; | ||||
161 | } | ||||
162 | if (m_shm) { | ||||
163 | delete m_shm; | ||||
164 | m_shm = nullptr; | ||||
165 | } | ||||
166 | if (m_queue) { | ||||
167 | delete m_queue; | ||||
168 | m_queue = nullptr; | ||||
169 | } | ||||
170 | if (m_thread) { | ||||
171 | m_thread->quit(); | ||||
172 | m_thread->wait(); | ||||
173 | delete m_thread; | ||||
174 | m_thread = nullptr; | ||||
175 | } | ||||
176 | delete m_connection; | ||||
177 | m_connection = nullptr; | ||||
178 | | ||||
179 | delete m_compositorInterface; | ||||
180 | m_compositorInterface = nullptr; | ||||
181 | | ||||
182 | delete m_viewporterInterface; | ||||
183 | m_viewporterInterface = nullptr; | ||||
184 | | ||||
185 | delete m_display; | ||||
186 | m_display = nullptr; | ||||
187 | } | ||||
188 | | ||||
189 | void TestViewporter::testViewportExists() | ||||
190 | { | ||||
191 | // This test verifies that setting the viewport for a surface twice results in a protocol error. | ||||
192 | using namespace KWayland::Client; | ||||
193 | using namespace KWayland::Server; | ||||
194 | | ||||
195 | // Create surface. | ||||
196 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
197 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
198 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
199 | | ||||
200 | QVERIFY(serverSurfaceCreated.wait()); | ||||
201 | SurfaceInterface *serverSurface | ||||
202 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
203 | QVERIFY(serverSurface); | ||||
204 | | ||||
205 | // Create viewport. | ||||
206 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
207 | QVERIFY(serverViewportCreated.isValid()); | ||||
208 | QScopedPointer<Viewport> vp1(m_viewporter->createViewport(s.data(), this)); | ||||
209 | | ||||
210 | QVERIFY(serverViewportCreated.wait()); | ||||
211 | ViewportInterface *serverViewport | ||||
212 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
213 | QVERIFY(serverViewport); | ||||
214 | | ||||
215 | // Create second viewport with error. | ||||
216 | QSignalSpy errorSpy(m_connection, &ConnectionThread::errorOccurred); | ||||
217 | QVERIFY(errorSpy.isValid()); | ||||
218 | QScopedPointer<Viewport> vp2(m_viewporter->createViewport(s.data(), this)); | ||||
219 | QVERIFY(errorSpy.wait()); | ||||
220 | } | ||||
221 | | ||||
222 | void TestViewporter::testWithoutBuffer() | ||||
223 | { | ||||
224 | // This test verifies that setting the viewport while buffer is zero does not change the size. | ||||
225 | using namespace KWayland::Client; | ||||
226 | using namespace KWayland::Server; | ||||
227 | | ||||
228 | // Create surface. | ||||
229 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
230 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
231 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
232 | | ||||
233 | QVERIFY(serverSurfaceCreated.wait()); | ||||
234 | SurfaceInterface *serverSurface | ||||
235 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
236 | QVERIFY(serverSurface); | ||||
237 | | ||||
238 | // Create viewport. | ||||
239 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
240 | QVERIFY(serverViewportCreated.isValid()); | ||||
241 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(s.data(), this)); | ||||
242 | | ||||
243 | QVERIFY(serverViewportCreated.wait()); | ||||
244 | ViewportInterface *serverViewport | ||||
245 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
246 | QVERIFY(serverViewport); | ||||
247 | | ||||
248 | QVERIFY(!serverSurface->buffer()); | ||||
249 | | ||||
250 | // Change the destination size. | ||||
251 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
252 | vp->setDestinationSize(QSize(400, 200)); | ||||
253 | s->commit(Surface::CommitFlag::None); | ||||
254 | | ||||
255 | // Even though a new destination size is set if there is no buffer, the surface size has not | ||||
256 | // changed. | ||||
257 | QVERIFY(!sizeChangedSpy.wait(100)); | ||||
258 | QCOMPARE(sizeChangedSpy.count(), 0); | ||||
259 | QVERIFY(!serverSurface->size().isValid()); | ||||
260 | | ||||
261 | // Now change the source rectangle. | ||||
262 | vp->setSourceRectangle(QRectF(QPointF(100, 50), QSizeF(400, 200))); | ||||
263 | s->commit(Surface::CommitFlag::None); | ||||
264 | | ||||
265 | // Even though a new source rectangle is set if there is no buffer, the surface size has not | ||||
266 | // changed. | ||||
267 | QVERIFY(!sizeChangedSpy.wait(100)); | ||||
268 | QCOMPARE(sizeChangedSpy.count(), 0); | ||||
269 | QVERIFY(!serverSurface->size().isValid()); | ||||
270 | } | ||||
271 | | ||||
272 | void TestViewporter::testDestinationSize() | ||||
273 | { | ||||
274 | // This test verifies setting the destination size is received by the server. | ||||
275 | using namespace KWayland::Client; | ||||
276 | using namespace KWayland::Server; | ||||
277 | | ||||
278 | // Create surface. | ||||
279 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
280 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
281 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
282 | | ||||
283 | QVERIFY(serverSurfaceCreated.wait()); | ||||
284 | SurfaceInterface *serverSurface | ||||
285 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
286 | QVERIFY(serverSurface); | ||||
287 | | ||||
288 | // Create viewport. | ||||
289 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
290 | QVERIFY(serverViewportCreated.isValid()); | ||||
291 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(s.data(), this)); | ||||
292 | | ||||
293 | QVERIFY(serverViewportCreated.wait()); | ||||
294 | ViewportInterface *serverViewport | ||||
295 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
296 | QVERIFY(serverViewport); | ||||
297 | | ||||
298 | // Add a buffer. | ||||
299 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
300 | QVERIFY(sizeChangedSpy.isValid()); | ||||
301 | QImage image(QSize(600, 400), QImage::Format_ARGB32_Premultiplied); | ||||
302 | image.fill(Qt::red); | ||||
303 | s->attachBuffer(m_shm->createBuffer(image)); | ||||
304 | s->damage(QRect(0, 0, 600, 400)); | ||||
305 | s->commit(Surface::CommitFlag::None); | ||||
306 | QVERIFY(sizeChangedSpy.wait()); | ||||
307 | | ||||
308 | // Change the destination size. | ||||
309 | vp->setDestinationSize(QSize(400, 200)); | ||||
310 | s->commit(Surface::CommitFlag::None); | ||||
311 | | ||||
312 | // The size of the surface has changed. | ||||
313 | QVERIFY(sizeChangedSpy.wait()); | ||||
314 | QCOMPARE(sizeChangedSpy.count(), 2); | ||||
315 | QCOMPARE(serverSurface->size(), QSize(400, 200)); | ||||
316 | } | ||||
317 | | ||||
318 | void TestViewporter::testSourceRectangle() | ||||
319 | { | ||||
320 | // This test verifies setting the source rectangle is received by the server. | ||||
321 | using namespace KWayland::Client; | ||||
322 | using namespace KWayland::Server; | ||||
323 | | ||||
324 | // Create surface. | ||||
325 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
326 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
327 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
328 | | ||||
329 | QVERIFY(serverSurfaceCreated.wait()); | ||||
330 | SurfaceInterface *serverSurface | ||||
331 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
332 | QVERIFY(serverSurface); | ||||
333 | | ||||
334 | // Create viewport. | ||||
335 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
336 | QVERIFY(serverViewportCreated.isValid()); | ||||
337 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(s.data(), this)); | ||||
338 | | ||||
339 | QVERIFY(serverViewportCreated.wait()); | ||||
340 | ViewportInterface *serverViewport | ||||
341 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
342 | QVERIFY(serverViewport); | ||||
343 | | ||||
344 | // Add a buffer. | ||||
345 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
346 | QVERIFY(sizeChangedSpy.isValid()); | ||||
347 | QImage image(QSize(600, 400), QImage::Format_ARGB32_Premultiplied); | ||||
348 | image.fill(Qt::red); | ||||
349 | s->attachBuffer(m_shm->createBuffer(image)); | ||||
350 | s->damage(QRect(0, 0, 600, 400)); | ||||
351 | s->commit(Surface::CommitFlag::None); | ||||
352 | QVERIFY(sizeChangedSpy.wait()); | ||||
353 | | ||||
354 | // Change the source rectangle. | ||||
355 | const QRectF rect(QPointF(100, 50), QSizeF(400, 200)); | ||||
356 | QSignalSpy sourceRectangleChangedSpy(serverSurface, &SurfaceInterface::sourceRectangleChanged); | ||||
357 | vp->setSourceRectangle(rect); | ||||
358 | s->commit(Surface::CommitFlag::None); | ||||
359 | | ||||
360 | // The size of the surface has changed. | ||||
361 | QVERIFY(sizeChangedSpy.wait()); | ||||
362 | QCOMPARE(sizeChangedSpy.count(), 2); | ||||
363 | if (sourceRectangleChangedSpy.count() == 0) { | ||||
364 | QVERIFY(sourceRectangleChangedSpy.wait()); | ||||
365 | } | ||||
366 | QCOMPARE(sourceRectangleChangedSpy.count(), 1); | ||||
367 | QCOMPARE(serverSurface->size(), rect.size()); | ||||
368 | QCOMPARE(serverSurface->sourceRectangle(), rect); | ||||
369 | } | ||||
370 | | ||||
371 | void TestViewporter::testDestinationSizeAndSourceRectangle() | ||||
372 | { | ||||
373 | // This test verifies setting the destination size and source rectangle is received by the | ||||
374 | // server. | ||||
375 | using namespace KWayland::Client; | ||||
376 | using namespace KWayland::Server; | ||||
377 | | ||||
378 | // Create surface. | ||||
379 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
380 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
381 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
382 | | ||||
383 | QVERIFY(serverSurfaceCreated.wait()); | ||||
384 | SurfaceInterface *serverSurface | ||||
385 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
386 | QVERIFY(serverSurface); | ||||
387 | | ||||
388 | // Create viewport. | ||||
389 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
390 | QVERIFY(serverViewportCreated.isValid()); | ||||
391 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(s.data(), this)); | ||||
392 | | ||||
393 | QVERIFY(serverViewportCreated.wait()); | ||||
394 | ViewportInterface *serverViewport | ||||
395 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
396 | QVERIFY(serverViewport); | ||||
397 | | ||||
398 | // Add a buffer. | ||||
399 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
400 | QVERIFY(sizeChangedSpy.isValid()); | ||||
401 | QImage image(QSize(600, 400), QImage::Format_ARGB32_Premultiplied); | ||||
402 | image.fill(Qt::red); | ||||
403 | s->attachBuffer(m_shm->createBuffer(image)); | ||||
404 | s->damage(QRect(0, 0, 600, 400)); | ||||
405 | s->commit(Surface::CommitFlag::None); | ||||
406 | QVERIFY(sizeChangedSpy.wait()); | ||||
407 | | ||||
408 | // Change the destination size. | ||||
409 | const QSize destinationSize = QSize(100, 50); | ||||
410 | vp->setDestinationSize(destinationSize); | ||||
411 | | ||||
412 | // Change the source rectangle. | ||||
413 | const QRectF rect(QPointF(100.1, 50.5), QSizeF(400.9, 200.8)); | ||||
414 | QSignalSpy sourceRectangleChangedSpy(serverSurface, &SurfaceInterface::sourceRectangleChanged); | ||||
415 | vp->setSourceRectangle(rect); | ||||
416 | s->commit(Surface::CommitFlag::None); | ||||
417 | | ||||
418 | // The size of the surface has changed. | ||||
419 | QVERIFY(sizeChangedSpy.wait()); | ||||
420 | QCOMPARE(sizeChangedSpy.count(), 2); | ||||
421 | if (sourceRectangleChangedSpy.count() == 0) { | ||||
422 | QVERIFY(sourceRectangleChangedSpy.wait()); | ||||
423 | } | ||||
424 | QCOMPARE(sourceRectangleChangedSpy.count(), 1); | ||||
425 | QCOMPARE(serverSurface->size(), destinationSize); | ||||
426 | QVERIFY((serverSurface->sourceRectangle().topLeft() | ||||
427 | - rect.topLeft()).manhattanLength() < 0.01); | ||||
428 | QVERIFY((serverSurface->sourceRectangle().bottomRight() | ||||
429 | - rect.bottomRight()).manhattanLength() < 0.01); | ||||
430 | } | ||||
431 | | ||||
432 | void TestViewporter::testDataError_data() | ||||
433 | { | ||||
434 | QTest::addColumn<QSize>("destinationSize"); | ||||
435 | QTest::addColumn<QRectF>("sourceRectangle"); | ||||
436 | | ||||
437 | QTest::newRow("destination-size-bad-value1") << QSize(-1, 0) << QRectF(-1, -1, -1, -1); | ||||
438 | QTest::newRow("destination-size-bad-value2") << QSize(-1, -2) << QRectF(-1, -1, -1, -1); | ||||
439 | QTest::newRow("source-rectangle-bad-value1") << QSize(-1, -1) << QRectF(0, 0, 1, -1); | ||||
440 | QTest::newRow("source-rectangle-bad-value2") << QSize(-1, -1) << QRectF(0, 0, 1, 1.5); | ||||
441 | QTest::newRow("source-rectangle-out-of-buffer") << QSize(-1, -1) << QRectF(0, 0, 601, 400); | ||||
442 | } | ||||
443 | | ||||
444 | void TestViewporter::testDataError() | ||||
445 | { | ||||
446 | // This test verifies setting the source rectangle is received by the server. | ||||
447 | using namespace KWayland::Client; | ||||
448 | using namespace KWayland::Server; | ||||
449 | | ||||
450 | // Create surface. | ||||
451 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
452 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
453 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
454 | | ||||
455 | QVERIFY(serverSurfaceCreated.wait()); | ||||
456 | SurfaceInterface *serverSurface | ||||
457 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
458 | QVERIFY(serverSurface); | ||||
459 | | ||||
460 | // Create viewport. | ||||
461 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
462 | QVERIFY(serverViewportCreated.isValid()); | ||||
463 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(s.data(), this)); | ||||
464 | | ||||
465 | QVERIFY(serverViewportCreated.wait()); | ||||
466 | ViewportInterface *serverViewport | ||||
467 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
468 | QVERIFY(serverViewport); | ||||
469 | | ||||
470 | // Add a buffer. | ||||
471 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
472 | QVERIFY(sizeChangedSpy.isValid()); | ||||
473 | QImage image(QSize(600, 400), QImage::Format_ARGB32_Premultiplied); | ||||
474 | image.fill(Qt::red); | ||||
475 | s->attachBuffer(m_shm->createBuffer(image)); | ||||
476 | s->damage(QRect(0, 0, 600, 400)); | ||||
477 | s->commit(Surface::CommitFlag::None); | ||||
478 | QVERIFY(sizeChangedSpy.wait()); | ||||
479 | | ||||
480 | QFETCH(QSize, destinationSize); | ||||
481 | QFETCH(QRectF, sourceRectangle); | ||||
482 | | ||||
483 | QSignalSpy errorSpy(m_connection, &ConnectionThread::errorOccurred); | ||||
484 | QVERIFY(errorSpy.isValid()); | ||||
485 | QVERIFY(!m_connection->hasError()); | ||||
486 | | ||||
487 | // Set the destination size. | ||||
488 | vp->setDestinationSize(destinationSize); | ||||
489 | | ||||
490 | // Set the source rectangle. | ||||
491 | vp->setSourceRectangle(sourceRectangle); | ||||
492 | s->commit(); | ||||
493 | | ||||
494 | // One of these lead to an error. | ||||
495 | QVERIFY(errorSpy.wait()); | ||||
496 | QVERIFY(m_connection->hasError()); | ||||
497 | // TODO: compare protocol error code | ||||
498 | } | ||||
499 | | ||||
500 | void TestViewporter::testBufferSizeChange() | ||||
501 | { | ||||
502 | // This test verifies that changing the buffer size reevaluates the source rectangle contains | ||||
503 | // condition correctly. | ||||
504 | using namespace KWayland::Client; | ||||
505 | using namespace KWayland::Server; | ||||
506 | | ||||
507 | // Create surface. | ||||
508 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
509 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
510 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
511 | | ||||
512 | QVERIFY(serverSurfaceCreated.wait()); | ||||
513 | SurfaceInterface *serverSurface | ||||
514 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
515 | QVERIFY(serverSurface); | ||||
516 | | ||||
517 | // Create viewport. | ||||
518 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
519 | QVERIFY(serverViewportCreated.isValid()); | ||||
520 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(s.data(), this)); | ||||
521 | | ||||
522 | QVERIFY(serverViewportCreated.wait()); | ||||
523 | ViewportInterface *serverViewport | ||||
524 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
525 | QVERIFY(serverViewport); | ||||
526 | | ||||
527 | // Add a buffer. | ||||
528 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
529 | QVERIFY(sizeChangedSpy.isValid()); | ||||
530 | QImage image(QSize(600, 400), QImage::Format_ARGB32_Premultiplied); | ||||
531 | image.fill(Qt::red); | ||||
532 | s->attachBuffer(m_shm->createBuffer(image)); | ||||
533 | s->damage(QRect(0, 0, 600, 400)); | ||||
534 | s->commit(Surface::CommitFlag::None); | ||||
535 | QVERIFY(sizeChangedSpy.wait()); | ||||
536 | | ||||
537 | // Change the source rectangle. | ||||
538 | const QRectF rect(QPointF(100, 200), QSizeF(500, 200)); | ||||
539 | QSignalSpy sourceRectangleChangedSpy(serverSurface, &SurfaceInterface::sourceRectangleChanged); | ||||
540 | vp->setSourceRectangle(rect); | ||||
541 | s->commit(Surface::CommitFlag::None); | ||||
542 | | ||||
543 | // The size of the surface has changed. | ||||
544 | QVERIFY(sizeChangedSpy.wait()); | ||||
545 | QCOMPARE(sizeChangedSpy.count(), 2); | ||||
546 | if (sourceRectangleChangedSpy.count() == 0) { | ||||
547 | QVERIFY(sourceRectangleChangedSpy.wait()); | ||||
548 | } | ||||
549 | QCOMPARE(sourceRectangleChangedSpy.count(), 1); | ||||
550 | QCOMPARE(serverSurface->size(), rect.size()); | ||||
551 | QCOMPARE(serverSurface->sourceRectangle(), rect); | ||||
552 | | ||||
553 | // Now change the buffer such that the source rectangle would not be contained anymore. | ||||
554 | QImage image2(QSize(599, 399), QImage::Format_ARGB32_Premultiplied); | ||||
555 | image2.fill(Qt::red); | ||||
556 | s->attachBuffer(m_shm->createBuffer(image2)); | ||||
557 | s->damage(QRect(0, 0, 599, 399)); | ||||
558 | | ||||
559 | // Change the source rectangle accordingly. | ||||
560 | const QRectF rect2(QPointF(100, 200), QSizeF(499, 199)); | ||||
561 | vp->setSourceRectangle(rect2); | ||||
562 | s->commit(Surface::CommitFlag::None); | ||||
563 | | ||||
564 | // The size of the surface has changed. | ||||
565 | QVERIFY(sizeChangedSpy.wait()); | ||||
566 | QCOMPARE(sizeChangedSpy.count(), 3); | ||||
567 | if (sourceRectangleChangedSpy.count() == 1) { | ||||
568 | QVERIFY(sourceRectangleChangedSpy.wait()); | ||||
569 | } | ||||
570 | QCOMPARE(sourceRectangleChangedSpy.count(), 2); | ||||
571 | QCOMPARE(serverSurface->size(), rect2.size()); | ||||
572 | QCOMPARE(serverSurface->sourceRectangle(), rect2); | ||||
573 | | ||||
574 | // Now change the buffer such that the source rectangle would not be contained anymore. | ||||
575 | QImage image3(QSize(598, 399), QImage::Format_ARGB32_Premultiplied); | ||||
576 | image3.fill(Qt::red); | ||||
577 | s->attachBuffer(m_shm->createBuffer(image3)); | ||||
578 | | ||||
579 | // And try to commit without changing the source rectangle accordingly, what leads to an error. | ||||
580 | QSignalSpy errorSpy(m_connection, &ConnectionThread::errorOccurred); | ||||
581 | QVERIFY(errorSpy.isValid()); | ||||
582 | QVERIFY(!m_connection->hasError()); | ||||
583 | | ||||
584 | s->commit(Surface::CommitFlag::None); | ||||
585 | QVERIFY(errorSpy.wait()); | ||||
586 | QVERIFY(m_connection->hasError()); | ||||
587 | // TODO: compare protocol error code | ||||
588 | } | ||||
589 | | ||||
590 | void TestViewporter::testDestinationSizeChange() | ||||
591 | { | ||||
592 | // This test verifies that changing the destination size reevaluates the source rectangle and | ||||
593 | // its integer condition correctly. | ||||
594 | using namespace KWayland::Client; | ||||
595 | using namespace KWayland::Server; | ||||
596 | | ||||
597 | // Create surface. | ||||
598 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
599 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
600 | QScopedPointer<Surface> s(m_compositor->createSurface()); | ||||
601 | | ||||
602 | QVERIFY(serverSurfaceCreated.wait()); | ||||
603 | SurfaceInterface *serverSurface | ||||
604 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
605 | QVERIFY(serverSurface); | ||||
606 | | ||||
607 | // Create viewport. | ||||
608 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
609 | QVERIFY(serverViewportCreated.isValid()); | ||||
610 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(s.data(), this)); | ||||
611 | | ||||
612 | QVERIFY(serverViewportCreated.wait()); | ||||
613 | ViewportInterface *serverViewport | ||||
614 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
615 | QVERIFY(serverViewport); | ||||
616 | | ||||
617 | // Add a buffer. | ||||
618 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
619 | QVERIFY(sizeChangedSpy.isValid()); | ||||
620 | QImage image(QSize(600, 400), QImage::Format_ARGB32_Premultiplied); | ||||
621 | image.fill(Qt::red); | ||||
622 | s->attachBuffer(m_shm->createBuffer(image)); | ||||
623 | s->damage(QRect(0, 0, 600, 400)); | ||||
624 | s->commit(Surface::CommitFlag::None); | ||||
625 | QVERIFY(sizeChangedSpy.wait()); | ||||
626 | | ||||
627 | // Set the destination size. | ||||
628 | const QSize destinationSize = QSize(100, 50); | ||||
629 | vp->setDestinationSize(destinationSize); | ||||
630 | | ||||
631 | // Change the source rectangle. | ||||
632 | const QRectF rect(QPointF(100.5, 200.3), QSizeF(200, 100)); | ||||
633 | QSignalSpy sourceRectangleChangedSpy(serverSurface, &SurfaceInterface::sourceRectangleChanged); | ||||
634 | vp->setSourceRectangle(rect); | ||||
635 | s->commit(Surface::CommitFlag::None); | ||||
636 | | ||||
637 | // The size of the surface has changed. | ||||
638 | QVERIFY(sizeChangedSpy.wait()); | ||||
639 | QCOMPARE(sizeChangedSpy.count(), 2); | ||||
640 | if (sourceRectangleChangedSpy.count() == 0) { | ||||
641 | QVERIFY(sourceRectangleChangedSpy.wait()); | ||||
642 | } | ||||
643 | QCOMPARE(sourceRectangleChangedSpy.count(), 1); | ||||
644 | QCOMPARE(serverSurface->size(), destinationSize); | ||||
645 | QVERIFY((serverSurface->sourceRectangle().topLeft() | ||||
646 | - rect.topLeft()).manhattanLength() < 0.01); | ||||
647 | QVERIFY((serverSurface->sourceRectangle().bottomRight() | ||||
648 | - rect.bottomRight()).manhattanLength() < 0.01); | ||||
649 | | ||||
650 | // Unset the destination size. | ||||
651 | vp->setDestinationSize(QSize(-1, -1)); | ||||
652 | s->commit(Surface::CommitFlag::None); | ||||
653 | | ||||
654 | // The size of the surface has changed to that of the source rectangle. | ||||
655 | QVERIFY(sizeChangedSpy.wait()); | ||||
656 | QCOMPARE(sizeChangedSpy.count(), 3); | ||||
657 | if (sourceRectangleChangedSpy.count() == 1) { | ||||
658 | QVERIFY(!sourceRectangleChangedSpy.wait(100)); | ||||
659 | } | ||||
660 | QCOMPARE(sourceRectangleChangedSpy.count(), 1); | ||||
661 | QCOMPARE(serverSurface->size(), rect.size()); | ||||
662 | QVERIFY((serverSurface->sourceRectangle().topLeft() | ||||
663 | - rect.topLeft()).manhattanLength() < 0.01); | ||||
664 | QVERIFY((serverSurface->sourceRectangle().bottomRight() | ||||
665 | - rect.bottomRight()).manhattanLength() < 0.01); | ||||
666 | | ||||
667 | // Set the destination size again. | ||||
668 | vp->setDestinationSize(destinationSize); | ||||
669 | | ||||
670 | // Change the source rectangle to non-integer values. | ||||
671 | const QRectF rect2(QPointF(100.5, 200.3), QSizeF(200.5, 100.5)); | ||||
672 | vp->setSourceRectangle(rect2); | ||||
673 | s->commit(Surface::CommitFlag::None); | ||||
674 | | ||||
675 | // The size of the surface has changed back. | ||||
676 | QVERIFY(sizeChangedSpy.wait()); | ||||
677 | QCOMPARE(sizeChangedSpy.count(), 4); | ||||
678 | if (sourceRectangleChangedSpy.count() == 1) { | ||||
679 | QVERIFY(sourceRectangleChangedSpy.wait()); | ||||
680 | } | ||||
681 | QCOMPARE(sourceRectangleChangedSpy.count(), 2); | ||||
682 | QCOMPARE(serverSurface->size(), destinationSize); | ||||
683 | QVERIFY((serverSurface->sourceRectangle().topLeft() | ||||
684 | - rect2.topLeft()).manhattanLength() < 0.01); | ||||
685 | QVERIFY((serverSurface->sourceRectangle().bottomRight() | ||||
686 | - rect2.bottomRight()).manhattanLength() < 0.01); | ||||
687 | | ||||
688 | // And try to unset the destination size, what leads to an error. | ||||
689 | QSignalSpy errorSpy(m_connection, &ConnectionThread::errorOccurred); | ||||
690 | QVERIFY(errorSpy.isValid()); | ||||
691 | QVERIFY(!m_connection->hasError()); | ||||
692 | | ||||
693 | vp->setDestinationSize(QSize(-1, -1)); | ||||
694 | s->commit(Surface::CommitFlag::None); | ||||
695 | QVERIFY(errorSpy.wait()); | ||||
696 | QVERIFY(m_connection->hasError()); | ||||
697 | // TODO: compare protocol error code | ||||
698 | } | ||||
699 | | ||||
700 | void TestViewporter::testNoSurface() | ||||
701 | { | ||||
702 | // This test verifies that setting the viewport for a surface twice results in a protocol error. | ||||
703 | using namespace KWayland::Client; | ||||
704 | using namespace KWayland::Server; | ||||
705 | | ||||
706 | // Create surface. | ||||
707 | QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); | ||||
708 | QVERIFY(serverSurfaceCreated.isValid()); | ||||
709 | QScopedPointer<Surface> surface(m_compositor->createSurface()); | ||||
710 | | ||||
711 | QVERIFY(serverSurfaceCreated.wait()); | ||||
712 | SurfaceInterface *serverSurface | ||||
713 | = serverSurfaceCreated.first().first().value<KWayland::Server::SurfaceInterface*>(); | ||||
714 | QVERIFY(serverSurface); | ||||
715 | | ||||
716 | // Create viewport. | ||||
717 | QSignalSpy serverViewportCreated(m_viewporterInterface, &ViewporterInterface::viewportCreated); | ||||
718 | QVERIFY(serverViewportCreated.isValid()); | ||||
719 | QScopedPointer<Viewport> vp(m_viewporter->createViewport(surface.data(), this)); | ||||
720 | | ||||
721 | QVERIFY(serverViewportCreated.wait()); | ||||
722 | ViewportInterface *serverViewport | ||||
723 | = serverViewportCreated.first().first().value<KWayland::Server::ViewportInterface*>(); | ||||
724 | QVERIFY(serverViewport); | ||||
725 | | ||||
726 | // Add a buffer. | ||||
727 | QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); | ||||
728 | QVERIFY(sizeChangedSpy.isValid()); | ||||
729 | QImage image(QSize(600, 400), QImage::Format_ARGB32_Premultiplied); | ||||
730 | image.fill(Qt::red); | ||||
731 | surface->attachBuffer(m_shm->createBuffer(image)); | ||||
732 | surface->damage(QRect(0, 0, 600, 400)); | ||||
733 | surface->commit(Surface::CommitFlag::None); | ||||
734 | QVERIFY(sizeChangedSpy.wait()); | ||||
735 | | ||||
736 | // Change the destination size. | ||||
737 | vp->setDestinationSize(QSize(400, 200)); | ||||
738 | surface->commit(Surface::CommitFlag::None); | ||||
739 | | ||||
740 | // The size of the surface has changed. | ||||
741 | QVERIFY(sizeChangedSpy.wait()); | ||||
742 | QCOMPARE(sizeChangedSpy.count(), 2); | ||||
743 | QCOMPARE(serverSurface->size(), QSize(400, 200)); | ||||
744 | | ||||
745 | // Now destroy the surface. | ||||
746 | surface.reset(); | ||||
747 | | ||||
748 | // And try to set data with the viewport what leads to a protocol error. | ||||
749 | QSignalSpy errorSpy(m_connection, &ConnectionThread::errorOccurred); | ||||
750 | QVERIFY(errorSpy.isValid()); | ||||
751 | QVERIFY(!m_connection->hasError()); | ||||
752 | | ||||
753 | vp->setDestinationSize(QSize(500, 300)); | ||||
754 | QVERIFY(errorSpy.wait()); | ||||
755 | QVERIFY(m_connection->hasError()); | ||||
756 | // TODO: compare protocol error code | ||||
757 | } | ||||
758 | | ||||
759 | QTEST_GUILESS_MAIN(TestViewporter) | ||||
760 | #include "test_viewporter.moc" |