File indexing completed on 2024-11-10 04:56:20
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 // Qt 0007 #include <QImage> 0008 #include <QPainter> 0009 #include <QSignalSpy> 0010 #include <QTest> 0011 // KWin 0012 #include "core/graphicsbuffer.h" 0013 #include "core/graphicsbufferview.h" 0014 #include "wayland/clientconnection.h" 0015 #include "wayland/compositor.h" 0016 #include "wayland/display.h" 0017 #include "wayland/idleinhibit_v1.h" 0018 #include "wayland/output.h" 0019 #include "wayland/surface.h" 0020 0021 #include "KWayland/Client/compositor.h" 0022 #include "KWayland/Client/connection_thread.h" 0023 #include "KWayland/Client/event_queue.h" 0024 #include "KWayland/Client/idleinhibit.h" 0025 #include "KWayland/Client/output.h" 0026 #include "KWayland/Client/region.h" 0027 #include "KWayland/Client/registry.h" 0028 #include "KWayland/Client/shm_pool.h" 0029 #include "KWayland/Client/surface.h" 0030 0031 #include "../../../tests/fakeoutput.h" 0032 0033 // Wayland 0034 #include <wayland-client-protocol.h> 0035 0036 class TestWaylandSurface : public QObject 0037 { 0038 Q_OBJECT 0039 public: 0040 explicit TestWaylandSurface(QObject *parent = nullptr); 0041 private Q_SLOTS: 0042 void init(); 0043 void cleanup(); 0044 0045 void testStaticAccessor(); 0046 void testDamage(); 0047 void testFrameCallback(); 0048 void testAttachBuffer(); 0049 void testOpaque(); 0050 void testInput(); 0051 void testScale(); 0052 void testUnmapOfNotMappedSurface(); 0053 void testSurfaceAt(); 0054 void testDestroyAttachedBuffer(); 0055 void testDestroyWithPendingCallback(); 0056 void testOutput(); 0057 void testDisconnect(); 0058 void testInhibit(); 0059 0060 private: 0061 KWin::Display *m_display; 0062 KWin::CompositorInterface *m_compositorInterface; 0063 KWin::IdleInhibitManagerV1Interface *m_idleInhibitInterface; 0064 KWayland::Client::ConnectionThread *m_connection; 0065 KWayland::Client::Compositor *m_compositor; 0066 KWayland::Client::ShmPool *m_shm; 0067 KWayland::Client::EventQueue *m_queue; 0068 KWayland::Client::IdleInhibitManager *m_idleInhibitManager; 0069 QThread *m_thread; 0070 }; 0071 0072 static const QString s_socketName = QStringLiteral("kwin-test-wayland-surface-0"); 0073 0074 TestWaylandSurface::TestWaylandSurface(QObject *parent) 0075 : QObject(parent) 0076 , m_display(nullptr) 0077 , m_compositorInterface(nullptr) 0078 , m_connection(nullptr) 0079 , m_compositor(nullptr) 0080 , m_thread(nullptr) 0081 { 0082 } 0083 0084 void TestWaylandSurface::init() 0085 { 0086 using namespace KWin; 0087 delete m_display; 0088 m_display = new KWin::Display(this); 0089 m_display->addSocketName(s_socketName); 0090 m_display->start(); 0091 QVERIFY(m_display->isRunning()); 0092 m_display->createShm(); 0093 0094 m_compositorInterface = new CompositorInterface(m_display, m_display); 0095 QVERIFY(m_compositorInterface); 0096 0097 m_idleInhibitInterface = new IdleInhibitManagerV1Interface(m_display, m_display); 0098 QVERIFY(m_idleInhibitInterface); 0099 0100 // setup connection 0101 m_connection = new KWayland::Client::ConnectionThread; 0102 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected); 0103 m_connection->setSocketName(s_socketName); 0104 0105 m_thread = new QThread(this); 0106 m_connection->moveToThread(m_thread); 0107 m_thread->start(); 0108 0109 /*connect(QCoreApplication::eventDispatcher(), &QAbstractEventDispatcher::aboutToBlock, m_connection, 0110 [this]() { 0111 if (m_connection->display()) { 0112 wl_display_flush(m_connection->display()); 0113 } 0114 } 0115 );*/ 0116 0117 m_connection->initConnection(); 0118 QVERIFY(connectedSpy.wait()); 0119 0120 m_queue = new KWayland::Client::EventQueue(this); 0121 QVERIFY(!m_queue->isValid()); 0122 m_queue->setup(m_connection); 0123 QVERIFY(m_queue->isValid()); 0124 0125 KWayland::Client::Registry registry; 0126 registry.setEventQueue(m_queue); 0127 QSignalSpy compositorSpy(®istry, &KWayland::Client::Registry::compositorAnnounced); 0128 QSignalSpy shmSpy(®istry, &KWayland::Client::Registry::shmAnnounced); 0129 QSignalSpy allAnnounced(®istry, &KWayland::Client::Registry::interfacesAnnounced); 0130 registry.create(m_connection->display()); 0131 QVERIFY(registry.isValid()); 0132 registry.setup(); 0133 QVERIFY(allAnnounced.wait()); 0134 QVERIFY(!compositorSpy.isEmpty()); 0135 QVERIFY(!shmSpy.isEmpty()); 0136 0137 m_compositor = registry.createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this); 0138 QVERIFY(m_compositor->isValid()); 0139 m_shm = registry.createShmPool(shmSpy.first().first().value<quint32>(), shmSpy.first().last().value<quint32>(), this); 0140 QVERIFY(m_shm->isValid()); 0141 0142 m_idleInhibitManager = registry.createIdleInhibitManager(registry.interface(KWayland::Client::Registry::Interface::IdleInhibitManagerUnstableV1).name, 0143 registry.interface(KWayland::Client::Registry::Interface::IdleInhibitManagerUnstableV1).version, 0144 this); 0145 QVERIFY(m_idleInhibitManager->isValid()); 0146 } 0147 0148 void TestWaylandSurface::cleanup() 0149 { 0150 if (m_compositor) { 0151 delete m_compositor; 0152 m_compositor = nullptr; 0153 } 0154 if (m_idleInhibitManager) { 0155 delete m_idleInhibitManager; 0156 m_idleInhibitManager = nullptr; 0157 } 0158 if (m_shm) { 0159 delete m_shm; 0160 m_shm = nullptr; 0161 } 0162 if (m_queue) { 0163 delete m_queue; 0164 m_queue = nullptr; 0165 } 0166 if (m_thread) { 0167 m_thread->quit(); 0168 m_thread->wait(); 0169 delete m_thread; 0170 m_thread = nullptr; 0171 } 0172 delete m_connection; 0173 m_connection = nullptr; 0174 0175 delete m_display; 0176 m_display = nullptr; 0177 0178 // these are the children of the display 0179 m_compositorInterface = nullptr; 0180 m_idleInhibitInterface = nullptr; 0181 } 0182 0183 void TestWaylandSurface::testStaticAccessor() 0184 { 0185 QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0186 0187 QVERIFY(!KWin::SurfaceInterface::get(nullptr)); 0188 QVERIFY(!KWin::SurfaceInterface::get(1, nullptr)); 0189 QVERIFY(KWayland::Client::Surface::all().isEmpty()); 0190 std::unique_ptr<KWayland::Client::Surface> s1(m_compositor->createSurface()); 0191 QVERIFY(s1->isValid()); 0192 QCOMPARE(KWayland::Client::Surface::all().count(), 1); 0193 QCOMPARE(KWayland::Client::Surface::all().first(), s1.get()); 0194 QCOMPARE(KWayland::Client::Surface::get(*s1), s1.get()); 0195 QVERIFY(serverSurfaceCreated.wait()); 0196 auto serverSurface1 = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0197 QVERIFY(serverSurface1); 0198 QCOMPARE(KWin::SurfaceInterface::get(serverSurface1->resource()), serverSurface1); 0199 QCOMPARE(KWin::SurfaceInterface::get(serverSurface1->id(), serverSurface1->client()), serverSurface1); 0200 0201 QVERIFY(!s1->size().isValid()); 0202 QSignalSpy sizeChangedSpy(s1.get(), &KWayland::Client::Surface::sizeChanged); 0203 const QSize testSize(200, 300); 0204 s1->setSize(testSize); 0205 QCOMPARE(s1->size(), testSize); 0206 QCOMPARE(sizeChangedSpy.count(), 1); 0207 QCOMPARE(sizeChangedSpy.first().first().toSize(), testSize); 0208 0209 // add another surface 0210 std::unique_ptr<KWayland::Client::Surface> s2(m_compositor->createSurface()); 0211 QVERIFY(s2->isValid()); 0212 QCOMPARE(KWayland::Client::Surface::all().count(), 2); 0213 QCOMPARE(KWayland::Client::Surface::all().first(), s1.get()); 0214 QCOMPARE(KWayland::Client::Surface::all().last(), s2.get()); 0215 QCOMPARE(KWayland::Client::Surface::get(*s1), s1.get()); 0216 QCOMPARE(KWayland::Client::Surface::get(*s2), s2.get()); 0217 serverSurfaceCreated.clear(); 0218 QVERIFY(serverSurfaceCreated.wait()); 0219 auto serverSurface2 = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0220 QVERIFY(serverSurface2); 0221 QCOMPARE(KWin::SurfaceInterface::get(serverSurface1->resource()), serverSurface1); 0222 QCOMPARE(KWin::SurfaceInterface::get(serverSurface1->id(), serverSurface1->client()), serverSurface1); 0223 QCOMPARE(KWin::SurfaceInterface::get(serverSurface2->resource()), serverSurface2); 0224 QCOMPARE(KWin::SurfaceInterface::get(serverSurface2->id(), serverSurface2->client()), serverSurface2); 0225 0226 const quint32 surfaceId1 = serverSurface1->id(); 0227 const quint32 surfaceId2 = serverSurface2->id(); 0228 0229 // delete s2 again 0230 s2.reset(); 0231 QCOMPARE(KWayland::Client::Surface::all().count(), 1); 0232 QCOMPARE(KWayland::Client::Surface::all().first(), s1.get()); 0233 QCOMPARE(KWayland::Client::Surface::get(*s1), s1.get()); 0234 0235 // and finally delete the last one 0236 s1.reset(); 0237 QVERIFY(KWayland::Client::Surface::all().isEmpty()); 0238 QVERIFY(!KWayland::Client::Surface::get(nullptr)); 0239 QSignalSpy destroyedSpy(serverSurface1, &KWin::SurfaceInterface::destroyed); 0240 QVERIFY(destroyedSpy.wait()); 0241 QVERIFY(!KWin::SurfaceInterface::get(nullptr)); 0242 QVERIFY(!KWin::SurfaceInterface::get(surfaceId1, nullptr)); 0243 QVERIFY(!KWin::SurfaceInterface::get(surfaceId2, nullptr)); 0244 } 0245 0246 void TestWaylandSurface::testDamage() 0247 { 0248 QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0249 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0250 s->setScale(2); 0251 QVERIFY(serverSurfaceCreated.wait()); 0252 KWin::SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0253 QVERIFY(serverSurface); 0254 QCOMPARE(serverSurface->bufferDamage(), QRegion()); 0255 QVERIFY(!serverSurface->isMapped()); 0256 0257 QSignalSpy committedSpy(serverSurface, &KWin::SurfaceInterface::committed); 0258 QSignalSpy damageSpy(serverSurface, &KWin::SurfaceInterface::damaged); 0259 0260 // send damage without a buffer 0261 { 0262 s->damage(QRect(0, 0, 100, 100)); 0263 s->commit(KWayland::Client::Surface::CommitFlag::None); 0264 wl_display_flush(m_connection->display()); 0265 QCoreApplication::processEvents(); 0266 QCoreApplication::processEvents(); 0267 QVERIFY(damageSpy.isEmpty()); 0268 QVERIFY(!serverSurface->isMapped()); 0269 QCOMPARE(committedSpy.count(), 1); 0270 } 0271 0272 // surface damage 0273 { 0274 QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied); 0275 img.fill(Qt::black); 0276 auto b = m_shm->createBuffer(img); 0277 s->attachBuffer(b, QPoint(55, 55)); 0278 s->damage(QRect(0, 0, 10, 10)); 0279 s->commit(KWayland::Client::Surface::CommitFlag::None); 0280 QVERIFY(damageSpy.wait()); 0281 QCOMPARE(serverSurface->offset(), QPoint(55, 55)); // offset is surface local so scale doesn't change this 0282 QCOMPARE(serverSurface->bufferDamage(), QRegion(0, 0, 10, 10)); 0283 QCOMPARE(damageSpy.first().first().value<QRegion>(), QRegion(0, 0, 10, 10)); 0284 QVERIFY(serverSurface->isMapped()); 0285 QCOMPARE(committedSpy.count(), 2); 0286 } 0287 0288 // damage multiple times 0289 { 0290 const QRegion surfaceDamage = QRegion(5, 8, 3, 6).united(QRect(10, 11, 6, 1)); 0291 const QRegion expectedDamage = QRegion(10, 16, 6, 12).united(QRect(20, 22, 12, 2)); 0292 QImage img(QSize(80, 70), QImage::Format_ARGB32_Premultiplied); 0293 img.fill(Qt::black); 0294 auto b = m_shm->createBuffer(img); 0295 s->attachBuffer(b); 0296 s->damage(surfaceDamage); 0297 damageSpy.clear(); 0298 s->commit(KWayland::Client::Surface::CommitFlag::None); 0299 QVERIFY(damageSpy.wait()); 0300 QCOMPARE(serverSurface->bufferDamage(), expectedDamage); 0301 QCOMPARE(damageSpy.first().first().value<QRegion>(), expectedDamage); 0302 QVERIFY(serverSurface->isMapped()); 0303 QCOMPARE(committedSpy.count(), 3); 0304 } 0305 0306 // damage buffer 0307 { 0308 const QRegion damage(30, 40, 22, 4); 0309 QImage img(QSize(80, 70), QImage::Format_ARGB32_Premultiplied); 0310 img.fill(Qt::black); 0311 auto b = m_shm->createBuffer(img); 0312 s->attachBuffer(b); 0313 s->damageBuffer(damage); 0314 damageSpy.clear(); 0315 s->commit(KWayland::Client::Surface::CommitFlag::None); 0316 QVERIFY(damageSpy.wait()); 0317 QCOMPARE(serverSurface->bufferDamage(), damage); 0318 QCOMPARE(damageSpy.first().first().value<QRegion>(), damage); 0319 QVERIFY(serverSurface->isMapped()); 0320 } 0321 0322 // combined regular damage and damaged buffer 0323 { 0324 const QRegion surfaceDamage(10, 20, 5, 5); 0325 const QRegion bufferDamage(30, 50, 50, 20); 0326 const QRegion expectedDamage = QRegion(20, 40, 10, 10).united(QRect(30, 50, 50, 20)); 0327 QImage img(QSize(80, 70), QImage::Format_ARGB32_Premultiplied); 0328 img.fill(Qt::black); 0329 auto b = m_shm->createBuffer(img); 0330 s->attachBuffer(b); 0331 s->damage(surfaceDamage); 0332 s->damageBuffer(bufferDamage); 0333 damageSpy.clear(); 0334 s->commit(KWayland::Client::Surface::CommitFlag::None); 0335 QVERIFY(damageSpy.wait()); 0336 QCOMPARE(serverSurface->bufferDamage(), expectedDamage); 0337 QCOMPARE(damageSpy.first().first().value<QRegion>(), expectedDamage); 0338 QVERIFY(serverSurface->isMapped()); 0339 } 0340 } 0341 0342 void TestWaylandSurface::testFrameCallback() 0343 { 0344 QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0345 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0346 QVERIFY(serverSurfaceCreated.wait()); 0347 KWin::SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0348 QVERIFY(serverSurface); 0349 0350 QSignalSpy damageSpy(serverSurface, &KWin::SurfaceInterface::damaged); 0351 0352 QSignalSpy frameRenderedSpy(s.get(), &KWayland::Client::Surface::frameRendered); 0353 QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied); 0354 img.fill(Qt::black); 0355 auto b = m_shm->createBuffer(img); 0356 s->attachBuffer(b); 0357 s->damage(QRect(0, 0, 10, 10)); 0358 s->commit(); 0359 QVERIFY(damageSpy.wait()); 0360 serverSurface->frameRendered(10); 0361 QVERIFY(frameRenderedSpy.isEmpty()); 0362 QVERIFY(frameRenderedSpy.wait()); 0363 QVERIFY(!frameRenderedSpy.isEmpty()); 0364 } 0365 0366 void TestWaylandSurface::testAttachBuffer() 0367 { 0368 // create the surface 0369 QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0370 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0371 QVERIFY(serverSurfaceCreated.wait()); 0372 KWin::SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0373 QVERIFY(serverSurface); 0374 0375 // create three images 0376 QImage black(24, 24, QImage::Format_RGB32); 0377 black.fill(Qt::black); 0378 QImage red(24, 24, QImage::Format_ARGB32); // Note - deliberately not premultiplied 0379 red.fill(QColor(255, 0, 0, 128)); 0380 QImage blue(24, 24, QImage::Format_ARGB32_Premultiplied); 0381 blue.fill(QColor(0, 0, 255, 128)); 0382 0383 QSharedPointer<KWayland::Client::Buffer> blackBufferPtr = m_shm->createBuffer(black).toStrongRef(); 0384 QVERIFY(blackBufferPtr); 0385 wl_buffer *blackBuffer = *(blackBufferPtr.data()); 0386 QSharedPointer<KWayland::Client::Buffer> redBuffer = m_shm->createBuffer(red).toStrongRef(); 0387 QVERIFY(redBuffer); 0388 QSharedPointer<KWayland::Client::Buffer> blueBuffer = m_shm->createBuffer(blue).toStrongRef(); 0389 QVERIFY(blueBuffer); 0390 0391 QCOMPARE(blueBuffer->format(), KWayland::Client::Buffer::Format::ARGB32); 0392 QCOMPARE(blueBuffer->size(), blue.size()); 0393 QVERIFY(!blueBuffer->isReleased()); 0394 QVERIFY(!blueBuffer->isUsed()); 0395 QCOMPARE(blueBuffer->stride(), blue.bytesPerLine()); 0396 0397 s->attachBuffer(redBuffer.data()); 0398 s->attachBuffer(blackBuffer); 0399 s->damage(QRect(0, 0, 24, 24)); 0400 s->commit(KWayland::Client::Surface::CommitFlag::None); 0401 QSignalSpy damageSpy(serverSurface, &KWin::SurfaceInterface::damaged); 0402 QSignalSpy mappedSpy(serverSurface, &KWin::SurfaceInterface::mapped); 0403 QSignalSpy unmappedSpy(serverSurface, &KWin::SurfaceInterface::unmapped); 0404 QVERIFY(damageSpy.wait()); 0405 QCOMPARE(mappedSpy.count(), 1); 0406 QVERIFY(unmappedSpy.isEmpty()); 0407 0408 // now the ServerSurface should have the black image attached as a buffer 0409 KWin::GraphicsBuffer *buffer = serverSurface->buffer(); 0410 buffer->ref(); 0411 { 0412 KWin::GraphicsBufferView view(buffer); 0413 QVERIFY(view.image()); 0414 QCOMPARE(*view.image(), black); 0415 QCOMPARE(view.image()->format(), QImage::Format_RGB32); 0416 QCOMPARE(view.image()->size(), QSize(24, 24)); 0417 } 0418 0419 // render another frame 0420 s->attachBuffer(redBuffer); 0421 s->damage(QRect(0, 0, 24, 24)); 0422 s->commit(KWayland::Client::Surface::CommitFlag::None); 0423 damageSpy.clear(); 0424 QVERIFY(damageSpy.wait()); 0425 QCOMPARE(mappedSpy.count(), 1); 0426 QVERIFY(unmappedSpy.isEmpty()); 0427 KWin::GraphicsBuffer *buffer2 = serverSurface->buffer(); 0428 buffer2->ref(); 0429 { 0430 KWin::GraphicsBufferView view(buffer2); 0431 QVERIFY(view.image()); 0432 QCOMPARE(view.image()->format(), QImage::Format_ARGB32_Premultiplied); 0433 QCOMPARE(view.image()->size(), QSize(24, 24)); 0434 for (int i = 0; i < 24; ++i) { 0435 for (int j = 0; j < 24; ++j) { 0436 // it's premultiplied in the format 0437 QCOMPARE(view.image()->pixel(i, j), qRgba(128, 0, 0, 128)); 0438 } 0439 } 0440 } 0441 buffer2->unref(); 0442 QVERIFY(buffer2->isReferenced()); 0443 QVERIFY(!redBuffer.data()->isReleased()); 0444 0445 // render another frame 0446 blueBuffer->setUsed(true); 0447 QVERIFY(blueBuffer->isUsed()); 0448 s->attachBuffer(blueBuffer.data()); 0449 s->damage(QRect(0, 0, 24, 24)); 0450 QSignalSpy frameRenderedSpy(s.get(), &KWayland::Client::Surface::frameRendered); 0451 s->commit(); 0452 damageSpy.clear(); 0453 QVERIFY(damageSpy.wait()); 0454 QCOMPARE(mappedSpy.count(), 1); 0455 QVERIFY(unmappedSpy.isEmpty()); 0456 QVERIFY(!buffer2->isReferenced()); 0457 // TODO: we should have a signal on when the Buffer gets released 0458 QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); 0459 if (!redBuffer.data()->isReleased()) { 0460 QCoreApplication::processEvents(QEventLoop::WaitForMoreEvents); 0461 } 0462 QVERIFY(redBuffer.data()->isReleased()); 0463 0464 KWin::GraphicsBuffer *buffer3 = serverSurface->buffer(); 0465 buffer3->ref(); 0466 { 0467 KWin::GraphicsBufferView view(buffer3); 0468 QVERIFY(view.image()); 0469 QCOMPARE(view.image()->format(), QImage::Format_ARGB32_Premultiplied); 0470 QCOMPARE(view.image()->size(), QSize(24, 24)); 0471 for (int i = 0; i < 24; ++i) { 0472 for (int j = 0; j < 24; ++j) { 0473 // it's premultiplied in the format 0474 QCOMPARE(view.image()->pixel(i, j), qRgba(0, 0, 128, 128)); 0475 } 0476 } 0477 } 0478 buffer3->unref(); 0479 QVERIFY(buffer3->isReferenced()); 0480 0481 serverSurface->frameRendered(1); 0482 QVERIFY(frameRenderedSpy.wait()); 0483 0484 // commit a different value shouldn't change our buffer 0485 QCOMPARE(serverSurface->buffer(), buffer3); 0486 damageSpy.clear(); 0487 s->setInputRegion(m_compositor->createRegion(QRegion(0, 0, 24, 24)).get()); 0488 s->commit(KWayland::Client::Surface::CommitFlag::None); 0489 wl_display_flush(m_connection->display()); 0490 QCoreApplication::processEvents(); 0491 QCoreApplication::processEvents(); 0492 QCOMPARE(serverSurface->buffer(), buffer3); 0493 QVERIFY(damageSpy.isEmpty()); 0494 QCOMPARE(mappedSpy.count(), 1); 0495 QVERIFY(unmappedSpy.isEmpty()); 0496 QVERIFY(serverSurface->isMapped()); 0497 0498 // clear the surface 0499 s->attachBuffer(blackBuffer); 0500 s->damage(QRect(0, 0, 1, 1)); 0501 // TODO: better method 0502 s->attachBuffer((wl_buffer *)nullptr); 0503 s->damage(QRect(0, 0, 10, 10)); 0504 s->commit(KWayland::Client::Surface::CommitFlag::None); 0505 QVERIFY(unmappedSpy.wait()); 0506 QCOMPARE(mappedSpy.count(), 1); 0507 QCOMPARE(unmappedSpy.count(), 1); 0508 QVERIFY(damageSpy.isEmpty()); 0509 QVERIFY(!serverSurface->isMapped()); 0510 0511 // TODO: add signal test on release 0512 buffer->unref(); 0513 } 0514 0515 void TestWaylandSurface::testOpaque() 0516 { 0517 using namespace KWin; 0518 QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0519 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0520 QVERIFY(serverSurfaceCreated.wait()); 0521 SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0522 QVERIFY(serverSurface); 0523 QSignalSpy opaqueRegionChangedSpy(serverSurface, &KWin::SurfaceInterface::opaqueChanged); 0524 0525 // by default there should be an empty opaque region 0526 QCOMPARE(serverSurface->opaque(), QRegion()); 0527 0528 // let's install an opaque region 0529 s->setOpaqueRegion(m_compositor->createRegion(QRegion(0, 10, 20, 30)).get()); 0530 // the region should only be applied after the surface got committed 0531 wl_display_flush(m_connection->display()); 0532 QCoreApplication::processEvents(); 0533 QCOMPARE(serverSurface->opaque(), QRegion()); 0534 QCOMPARE(opaqueRegionChangedSpy.count(), 0); 0535 0536 // so let's commit to get the new region 0537 QImage black(20, 40, QImage::Format_ARGB32_Premultiplied); 0538 black.fill(Qt::black); 0539 QSharedPointer<KWayland::Client::Buffer> buffer1 = m_shm->createBuffer(black).toStrongRef(); 0540 s->attachBuffer(buffer1); 0541 s->commit(KWayland::Client::Surface::CommitFlag::None); 0542 QVERIFY(opaqueRegionChangedSpy.wait()); 0543 QCOMPARE(opaqueRegionChangedSpy.count(), 1); 0544 QCOMPARE(opaqueRegionChangedSpy.last().first().value<QRegion>(), QRegion(0, 10, 20, 30)); 0545 QCOMPARE(serverSurface->opaque(), QRegion(0, 10, 20, 30)); 0546 0547 // committing without setting a new region shouldn't change 0548 s->commit(KWayland::Client::Surface::CommitFlag::None); 0549 wl_display_flush(m_connection->display()); 0550 QCoreApplication::processEvents(); 0551 QCOMPARE(opaqueRegionChangedSpy.count(), 1); 0552 QCOMPARE(serverSurface->opaque(), QRegion(0, 10, 20, 30)); 0553 0554 // let's change the opaque region, it will be clipped with rect(0, 0, 20, 40) 0555 s->setOpaqueRegion(m_compositor->createRegion(QRegion(10, 20, 30, 40)).get()); 0556 s->commit(KWayland::Client::Surface::CommitFlag::None); 0557 QVERIFY(opaqueRegionChangedSpy.wait()); 0558 QCOMPARE(opaqueRegionChangedSpy.count(), 2); 0559 QCOMPARE(opaqueRegionChangedSpy.last().first().value<QRegion>(), QRegion(10, 20, 10, 20)); 0560 QCOMPARE(serverSurface->opaque(), QRegion(10, 20, 10, 20)); 0561 0562 // and let's go back to an empty region 0563 s->setOpaqueRegion(); 0564 s->commit(KWayland::Client::Surface::CommitFlag::None); 0565 QVERIFY(opaqueRegionChangedSpy.wait()); 0566 QCOMPARE(opaqueRegionChangedSpy.count(), 3); 0567 QCOMPARE(opaqueRegionChangedSpy.last().first().value<QRegion>(), QRegion()); 0568 QCOMPARE(serverSurface->opaque(), QRegion()); 0569 } 0570 0571 void TestWaylandSurface::testInput() 0572 { 0573 using namespace KWin; 0574 QSignalSpy serverSurfaceCreated(m_compositorInterface, &KWin::CompositorInterface::surfaceCreated); 0575 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0576 QVERIFY(serverSurfaceCreated.wait()); 0577 SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0578 QVERIFY(serverSurface); 0579 QSignalSpy inputRegionChangedSpy(serverSurface, &KWin::SurfaceInterface::inputChanged); 0580 QSignalSpy committedSpy(serverSurface, &SurfaceInterface::committed); 0581 0582 // the input region should be empty if the surface has no buffer 0583 QVERIFY(!serverSurface->isMapped()); 0584 QCOMPARE(serverSurface->input(), QRegion()); 0585 0586 // the default input region is infinite 0587 QImage black(100, 50, QImage::Format_RGB32); 0588 black.fill(Qt::black); 0589 QSharedPointer<KWayland::Client::Buffer> buffer1 = m_shm->createBuffer(black).toStrongRef(); 0590 QVERIFY(buffer1); 0591 s->attachBuffer(buffer1); 0592 s->commit(KWayland::Client::Surface::CommitFlag::None); 0593 QVERIFY(committedSpy.wait()); 0594 QVERIFY(serverSurface->isMapped()); 0595 QCOMPARE(inputRegionChangedSpy.count(), 1); 0596 QCOMPARE(serverSurface->input(), QRegion(0, 0, 100, 50)); 0597 0598 // let's install an input region 0599 s->setInputRegion(m_compositor->createRegion(QRegion(0, 10, 20, 30)).get()); 0600 // the region should only be applied after the surface got committed 0601 wl_display_flush(m_connection->display()); 0602 QCoreApplication::processEvents(); 0603 QCOMPARE(inputRegionChangedSpy.count(), 1); 0604 QCOMPARE(serverSurface->input(), QRegion(0, 0, 100, 50)); 0605 0606 // so let's commit to get the new region 0607 s->commit(KWayland::Client::Surface::CommitFlag::None); 0608 QVERIFY(committedSpy.wait()); 0609 QCOMPARE(inputRegionChangedSpy.count(), 2); 0610 QCOMPARE(serverSurface->input(), QRegion(0, 10, 20, 30)); 0611 0612 // committing without setting a new region shouldn't change 0613 s->commit(KWayland::Client::Surface::CommitFlag::None); 0614 wl_display_flush(m_connection->display()); 0615 QCoreApplication::processEvents(); 0616 QCOMPARE(inputRegionChangedSpy.count(), 2); 0617 QCOMPARE(serverSurface->input(), QRegion(0, 10, 20, 30)); 0618 0619 // let's change the input region, note that the new input region is cropped 0620 s->setInputRegion(m_compositor->createRegion(QRegion(10, 20, 30, 40)).get()); 0621 s->commit(KWayland::Client::Surface::CommitFlag::None); 0622 QVERIFY(committedSpy.wait()); 0623 QCOMPARE(inputRegionChangedSpy.count(), 3); 0624 QCOMPARE(serverSurface->input(), QRegion(10, 20, 30, 30)); 0625 0626 // and let's go back to an empty region 0627 s->setInputRegion(); 0628 s->commit(KWayland::Client::Surface::CommitFlag::None); 0629 QVERIFY(committedSpy.wait()); 0630 QCOMPARE(inputRegionChangedSpy.count(), 4); 0631 QCOMPARE(serverSurface->input(), QRegion(0, 0, 100, 50)); 0632 } 0633 0634 void TestWaylandSurface::testScale() 0635 { 0636 // this test verifies that updating the scale factor is correctly passed to the Wayland server 0637 using namespace KWin; 0638 // create surface 0639 QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); 0640 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0641 QCOMPARE(s->scale(), 1); 0642 QVERIFY(serverSurfaceCreated.wait()); 0643 SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0644 QVERIFY(serverSurface); 0645 0646 // changing the scale implicitly changes the size 0647 QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); 0648 0649 // attach a buffer of 100x100 0650 QImage red(100, 100, QImage::Format_ARGB32_Premultiplied); 0651 red.fill(QColor(255, 0, 0, 128)); 0652 QSharedPointer<KWayland::Client::Buffer> redBuffer = m_shm->createBuffer(red).toStrongRef(); 0653 QVERIFY(redBuffer); 0654 s->attachBuffer(redBuffer.data()); 0655 s->damageBuffer(QRect(0, 0, 100, 100)); 0656 s->commit(KWayland::Client::Surface::CommitFlag::None); 0657 QVERIFY(sizeChangedSpy.wait()); 0658 QCOMPARE(sizeChangedSpy.count(), 1); 0659 QCOMPARE(serverSurface->size(), QSize(100, 100)); 0660 0661 // set the scale to 2, buffer is still 100x100 so size should change to 50x50 0662 s->setScale(2); 0663 s->commit(KWayland::Client::Surface::CommitFlag::None); 0664 QVERIFY(sizeChangedSpy.wait()); 0665 QCOMPARE(sizeChangedSpy.count(), 2); 0666 QCOMPARE(serverSurface->size(), QSize(50, 50)); 0667 0668 // set scale and size in one commit, buffer is 60x60 at scale 3 so size should be 20x20 0669 QImage blue(60, 60, QImage::Format_ARGB32_Premultiplied); 0670 red.fill(QColor(255, 0, 0, 128)); 0671 QSharedPointer<KWayland::Client::Buffer> blueBuffer = m_shm->createBuffer(blue).toStrongRef(); 0672 QVERIFY(blueBuffer); 0673 s->attachBuffer(blueBuffer.data()); 0674 s->setScale(3); 0675 s->commit(KWayland::Client::Surface::CommitFlag::None); 0676 QVERIFY(sizeChangedSpy.wait()); 0677 QCOMPARE(sizeChangedSpy.count(), 3); 0678 QCOMPARE(serverSurface->size(), QSize(20, 20)); 0679 } 0680 0681 void TestWaylandSurface::testUnmapOfNotMappedSurface() 0682 { 0683 // this test verifies that a surface which doesn't have a buffer attached doesn't trigger the unmapped signal 0684 using namespace KWin; 0685 // create surface 0686 QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); 0687 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0688 QVERIFY(serverSurfaceCreated.wait()); 0689 SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0690 0691 QSignalSpy unmappedSpy(serverSurface, &SurfaceInterface::unmapped); 0692 QSignalSpy committedSpy(serverSurface, &SurfaceInterface::committed); 0693 0694 // let's map a null buffer and change scale to trigger a signal we can wait for 0695 s->attachBuffer(KWayland::Client::Buffer::Ptr()); 0696 s->commit(KWayland::Client::Surface::CommitFlag::None); 0697 0698 QVERIFY(committedSpy.wait()); 0699 QVERIFY(unmappedSpy.isEmpty()); 0700 } 0701 0702 void TestWaylandSurface::testSurfaceAt() 0703 { 0704 // this test verifies that surfaceAt(const QPointF&) works as expected for the case of no children 0705 using namespace KWin; 0706 // create surface 0707 QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); 0708 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0709 QVERIFY(serverSurfaceCreated.wait()); 0710 SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0711 0712 // a newly created surface should not be mapped and not provide a surface at a position 0713 QVERIFY(!serverSurface->isMapped()); 0714 QVERIFY(!serverSurface->surfaceAt(QPointF(0, 0))); 0715 0716 // let's damage this surface 0717 QSignalSpy sizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); 0718 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 0719 image.fill(Qt::red); 0720 s->attachBuffer(m_shm->createBuffer(image)); 0721 s->damage(QRect(0, 0, 100, 100)); 0722 s->commit(KWayland::Client::Surface::CommitFlag::None); 0723 QVERIFY(sizeChangedSpy.wait()); 0724 0725 // now the surface is mapped and surfaceAt should give the surface 0726 QVERIFY(serverSurface->isMapped()); 0727 QCOMPARE(serverSurface->surfaceAt(QPointF(0, 0)), serverSurface); 0728 QCOMPARE(serverSurface->surfaceAt(QPointF(99, 99)), serverSurface); 0729 // outside the geometry it should not give a surface 0730 QVERIFY(!serverSurface->surfaceAt(QPointF(100, 100))); 0731 QVERIFY(!serverSurface->surfaceAt(QPointF(-1, -1))); 0732 } 0733 0734 void TestWaylandSurface::testDestroyAttachedBuffer() 0735 { 0736 // this test verifies that destroying of a buffer attached to a surface works 0737 using namespace KWin; 0738 // create surface 0739 QSignalSpy serverSurfaceCreated(m_compositorInterface, &CompositorInterface::surfaceCreated); 0740 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0741 QVERIFY(serverSurfaceCreated.wait()); 0742 SurfaceInterface *serverSurface = serverSurfaceCreated.first().first().value<KWin::SurfaceInterface *>(); 0743 0744 // let's damage this surface 0745 QSignalSpy damagedSpy(serverSurface, &SurfaceInterface::damaged); 0746 QImage image(QSize(100, 100), QImage::Format_ARGB32_Premultiplied); 0747 image.fill(Qt::red); 0748 s->attachBuffer(m_shm->createBuffer(image)); 0749 s->damage(QRect(0, 0, 100, 100)); 0750 s->commit(KWayland::Client::Surface::CommitFlag::None); 0751 QVERIFY(damagedSpy.wait()); 0752 QVERIFY(serverSurface->buffer()); 0753 0754 // attach another buffer 0755 image.fill(Qt::blue); 0756 s->attachBuffer(m_shm->createBuffer(image)); 0757 m_connection->flush(); 0758 0759 // Let's try to destroy it 0760 delete m_shm; 0761 m_shm = nullptr; 0762 QTRY_VERIFY(serverSurface->buffer()->isDropped()); 0763 } 0764 0765 void TestWaylandSurface::testDestroyWithPendingCallback() 0766 { 0767 // this test tries to verify that destroying a surface with a pending callback works correctly 0768 // first create surface 0769 using namespace KWin; 0770 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0771 QVERIFY(s != nullptr); 0772 QVERIFY(s->isValid()); 0773 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0774 QVERIFY(surfaceCreatedSpy.wait()); 0775 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0776 QVERIFY(serverSurface); 0777 0778 // now render to it 0779 QImage img(QSize(10, 10), QImage::Format_ARGB32_Premultiplied); 0780 img.fill(Qt::black); 0781 auto b = m_shm->createBuffer(img); 0782 s->attachBuffer(b); 0783 s->damage(QRect(0, 0, 10, 10)); 0784 // add some frame callbacks 0785 for (int i = 0; i < 1000; i++) { 0786 wl_surface_frame(*s); 0787 } 0788 s->commit(KWayland::Client::Surface::CommitFlag::FrameCallback); 0789 QSignalSpy damagedSpy(serverSurface, &SurfaceInterface::damaged); 0790 QVERIFY(damagedSpy.wait()); 0791 0792 // now try to destroy the Surface again 0793 QSignalSpy destroyedSpy(serverSurface, &QObject::destroyed); 0794 s.reset(); 0795 QVERIFY(destroyedSpy.wait()); 0796 } 0797 0798 void TestWaylandSurface::testDisconnect() 0799 { 0800 // this test verifies that the server side correctly tears down the resources when the client disconnects 0801 using namespace KWin; 0802 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0803 QVERIFY(s != nullptr); 0804 QVERIFY(s->isValid()); 0805 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0806 QVERIFY(surfaceCreatedSpy.wait()); 0807 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0808 QVERIFY(serverSurface); 0809 0810 // destroy client 0811 QSignalSpy clientDisconnectedSpy(serverSurface->client(), &ClientConnection::disconnected); 0812 QSignalSpy surfaceDestroyedSpy(serverSurface, &QObject::destroyed); 0813 if (m_connection) { 0814 m_connection->deleteLater(); 0815 m_connection = nullptr; 0816 } 0817 QVERIFY(clientDisconnectedSpy.wait()); 0818 QCOMPARE(clientDisconnectedSpy.count(), 1); 0819 if (surfaceDestroyedSpy.isEmpty()) { 0820 QVERIFY(surfaceDestroyedSpy.wait()); 0821 } 0822 QTRY_COMPARE(surfaceDestroyedSpy.count(), 1); 0823 0824 s->destroy(); 0825 m_shm->destroy(); 0826 m_compositor->destroy(); 0827 m_queue->destroy(); 0828 m_idleInhibitManager->destroy(); 0829 } 0830 0831 void TestWaylandSurface::testOutput() 0832 { 0833 // This test verifies that the enter/leave are sent correctly to the Client 0834 using namespace KWin; 0835 qRegisterMetaType<KWayland::Client::Output *>(); 0836 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0837 QVERIFY(s != nullptr); 0838 QVERIFY(s->isValid()); 0839 QVERIFY(s->outputs().isEmpty()); 0840 QSignalSpy enteredSpy(s.get(), &KWayland::Client::Surface::outputEntered); 0841 QSignalSpy leftSpy(s.get(), &KWayland::Client::Surface::outputLeft); 0842 // wait for the surface on the Server side 0843 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0844 QVERIFY(surfaceCreatedSpy.wait()); 0845 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0846 QVERIFY(serverSurface); 0847 QCOMPARE(serverSurface->outputs(), QList<OutputInterface *>()); 0848 0849 // create another registry to get notified about added outputs 0850 KWayland::Client::Registry registry; 0851 registry.setEventQueue(m_queue); 0852 QSignalSpy allAnnounced(®istry, &KWayland::Client::Registry::interfacesAnnounced); 0853 registry.create(m_connection); 0854 QVERIFY(registry.isValid()); 0855 registry.setup(); 0856 QVERIFY(allAnnounced.wait()); 0857 QSignalSpy outputAnnouncedSpy(®istry, &KWayland::Client::Registry::outputAnnounced); 0858 0859 auto outputHandle = std::make_unique<FakeOutput>(); 0860 auto serverOutput = std::make_unique<OutputInterface>(m_display, outputHandle.get()); 0861 QVERIFY(outputAnnouncedSpy.wait()); 0862 std::unique_ptr<KWayland::Client::Output> clientOutput( 0863 registry.createOutput(outputAnnouncedSpy.first().first().value<quint32>(), outputAnnouncedSpy.first().last().value<quint32>())); 0864 QVERIFY(clientOutput->isValid()); 0865 m_connection->flush(); 0866 m_display->dispatchEvents(); 0867 0868 // now enter it 0869 serverSurface->setOutputs(QList<OutputInterface *>{serverOutput.get()}, serverOutput.get()); 0870 QCOMPARE(serverSurface->outputs(), QList<OutputInterface *>{serverOutput.get()}); 0871 QVERIFY(enteredSpy.wait()); 0872 QCOMPARE(enteredSpy.count(), 1); 0873 QCOMPARE(enteredSpy.first().first().value<KWayland::Client::Output *>(), clientOutput.get()); 0874 QCOMPARE(s->outputs(), QList<KWayland::Client::Output *>{clientOutput.get()}); 0875 0876 // adding to same should not trigger 0877 serverSurface->setOutputs(QList<OutputInterface *>{serverOutput.get()}, serverOutput.get()); 0878 0879 // leave again 0880 serverSurface->setOutputs(QList<OutputInterface *>(), nullptr); 0881 QCOMPARE(serverSurface->outputs(), QList<OutputInterface *>()); 0882 QVERIFY(leftSpy.wait()); 0883 QCOMPARE(enteredSpy.count(), 1); 0884 QCOMPARE(leftSpy.count(), 1); 0885 QCOMPARE(leftSpy.first().first().value<KWayland::Client::Output *>(), clientOutput.get()); 0886 QCOMPARE(s->outputs(), QList<KWayland::Client::Output *>()); 0887 0888 // leave again should not trigger 0889 serverSurface->setOutputs(QList<OutputInterface *>(), nullptr); 0890 0891 // and enter again, just to verify 0892 serverSurface->setOutputs(QList<OutputInterface *>{serverOutput.get()}, serverOutput.get()); 0893 QCOMPARE(serverSurface->outputs(), QList<OutputInterface *>{serverOutput.get()}); 0894 QVERIFY(enteredSpy.wait()); 0895 QCOMPARE(enteredSpy.count(), 2); 0896 QCOMPARE(leftSpy.count(), 1); 0897 0898 // delete output client is on. 0899 // client should get an exit and be left on no outputs (which is allowed) 0900 serverOutput.reset(); 0901 outputHandle.reset(); 0902 QVERIFY(leftSpy.wait()); 0903 QCOMPARE(serverSurface->outputs(), QList<OutputInterface *>()); 0904 } 0905 0906 void TestWaylandSurface::testInhibit() 0907 { 0908 using namespace KWin; 0909 std::unique_ptr<KWayland::Client::Surface> s(m_compositor->createSurface()); 0910 // wait for the surface on the Server side 0911 QSignalSpy surfaceCreatedSpy(m_compositorInterface, &CompositorInterface::surfaceCreated); 0912 QVERIFY(surfaceCreatedSpy.wait()); 0913 auto serverSurface = surfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0914 QVERIFY(serverSurface); 0915 QCOMPARE(serverSurface->inhibitsIdle(), false); 0916 0917 QSignalSpy inhibitsChangedSpy(serverSurface, &SurfaceInterface::inhibitsIdleChanged); 0918 0919 // now create an idle inhibition 0920 std::unique_ptr<KWayland::Client::IdleInhibitor> inhibitor1(m_idleInhibitManager->createInhibitor(s.get())); 0921 QVERIFY(inhibitsChangedSpy.wait()); 0922 QCOMPARE(serverSurface->inhibitsIdle(), true); 0923 0924 // creating a second idle inhibition should not trigger the signal 0925 std::unique_ptr<KWayland::Client::IdleInhibitor> inhibitor2(m_idleInhibitManager->createInhibitor(s.get())); 0926 QVERIFY(!inhibitsChangedSpy.wait(500)); 0927 QCOMPARE(serverSurface->inhibitsIdle(), true); 0928 0929 // and also deleting the first inhibitor should not yet change the inhibition 0930 inhibitor1.reset(); 0931 QVERIFY(!inhibitsChangedSpy.wait(500)); 0932 QCOMPARE(serverSurface->inhibitsIdle(), true); 0933 0934 // but deleting also the second inhibitor should trigger 0935 inhibitor2.reset(); 0936 QVERIFY(inhibitsChangedSpy.wait()); 0937 QCOMPARE(serverSurface->inhibitsIdle(), false); 0938 QCOMPARE(inhibitsChangedSpy.count(), 2); 0939 0940 // recreate inhibitor1 should inhibit again 0941 inhibitor1.reset(m_idleInhibitManager->createInhibitor(s.get())); 0942 QVERIFY(inhibitsChangedSpy.wait()); 0943 QCOMPARE(serverSurface->inhibitsIdle(), true); 0944 // and destroying should uninhibit 0945 inhibitor1.reset(); 0946 QVERIFY(inhibitsChangedSpy.wait()); 0947 QCOMPARE(serverSurface->inhibitsIdle(), false); 0948 QCOMPARE(inhibitsChangedSpy.count(), 4); 0949 } 0950 0951 QTEST_GUILESS_MAIN(TestWaylandSurface) 0952 #include "test_wayland_surface.moc"