File indexing completed on 2024-11-10 04:56:23
0001 /* 0002 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include <QSignalSpy> 0008 #include <QTest> 0009 #include <QThread> 0010 0011 #include "wayland/compositor.h" 0012 #include "wayland/display.h" 0013 #include "wayland/surface.h" 0014 #include "wayland/viewporter.h" 0015 0016 #include "KWayland/Client/compositor.h" 0017 #include "KWayland/Client/connection_thread.h" 0018 #include "KWayland/Client/event_queue.h" 0019 #include "KWayland/Client/registry.h" 0020 #include "KWayland/Client/shm_pool.h" 0021 #include "KWayland/Client/surface.h" 0022 0023 #include "qwayland-viewporter.h" 0024 0025 using namespace KWin; 0026 0027 class Viewporter : public QtWayland::wp_viewporter 0028 { 0029 }; 0030 0031 class Viewport : public QtWayland::wp_viewport 0032 { 0033 }; 0034 0035 class TestViewporterInterface : public QObject 0036 { 0037 Q_OBJECT 0038 0039 public: 0040 ~TestViewporterInterface() override; 0041 0042 private Q_SLOTS: 0043 void initTestCase(); 0044 void testCropScale(); 0045 0046 private: 0047 KWayland::Client::ConnectionThread *m_connection; 0048 KWayland::Client::EventQueue *m_queue; 0049 KWayland::Client::Compositor *m_clientCompositor; 0050 KWayland::Client::ShmPool *m_shm; 0051 0052 QThread *m_thread; 0053 KWin::Display m_display; 0054 CompositorInterface *m_serverCompositor; 0055 Viewporter *m_viewporter; 0056 }; 0057 0058 static const QString s_socketName = QStringLiteral("kwin-wayland-server-viewporter-test-0"); 0059 0060 void TestViewporterInterface::initTestCase() 0061 { 0062 m_display.addSocketName(s_socketName); 0063 m_display.start(); 0064 QVERIFY(m_display.isRunning()); 0065 0066 m_display.createShm(); 0067 new ViewporterInterface(&m_display); 0068 0069 m_serverCompositor = new CompositorInterface(&m_display, this); 0070 0071 m_connection = new KWayland::Client::ConnectionThread; 0072 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected); 0073 m_connection->setSocketName(s_socketName); 0074 0075 m_thread = new QThread(this); 0076 m_connection->moveToThread(m_thread); 0077 m_thread->start(); 0078 0079 m_connection->initConnection(); 0080 QVERIFY(connectedSpy.wait()); 0081 QVERIFY(!m_connection->connections().isEmpty()); 0082 0083 m_queue = new KWayland::Client::EventQueue(this); 0084 QVERIFY(!m_queue->isValid()); 0085 m_queue->setup(m_connection); 0086 QVERIFY(m_queue->isValid()); 0087 0088 auto registry = new KWayland::Client::Registry(this); 0089 connect(registry, &KWayland::Client::Registry::interfaceAnnounced, this, [this, registry](const QByteArray &interface, quint32 id, quint32 version) { 0090 if (interface == QByteArrayLiteral("wp_viewporter")) { 0091 m_viewporter = new Viewporter(); 0092 m_viewporter->init(*registry, id, version); 0093 } 0094 }); 0095 QSignalSpy allAnnouncedSpy(registry, &KWayland::Client::Registry::interfaceAnnounced); 0096 QSignalSpy compositorSpy(registry, &KWayland::Client::Registry::compositorAnnounced); 0097 QSignalSpy shmSpy(registry, &KWayland::Client::Registry::shmAnnounced); 0098 registry->setEventQueue(m_queue); 0099 registry->create(m_connection->display()); 0100 QVERIFY(registry->isValid()); 0101 registry->setup(); 0102 QVERIFY(allAnnouncedSpy.wait()); 0103 0104 m_clientCompositor = registry->createCompositor(compositorSpy.first().first().value<quint32>(), compositorSpy.first().last().value<quint32>(), this); 0105 QVERIFY(m_clientCompositor->isValid()); 0106 0107 m_shm = registry->createShmPool(shmSpy.first().first().value<quint32>(), shmSpy.first().last().value<quint32>(), this); 0108 QVERIFY(m_shm->isValid()); 0109 } 0110 0111 TestViewporterInterface::~TestViewporterInterface() 0112 { 0113 if (m_viewporter) { 0114 delete m_viewporter; 0115 m_viewporter = nullptr; 0116 } 0117 if (m_shm) { 0118 delete m_shm; 0119 m_shm = nullptr; 0120 } 0121 if (m_queue) { 0122 delete m_queue; 0123 m_queue = nullptr; 0124 } 0125 if (m_thread) { 0126 m_thread->quit(); 0127 m_thread->wait(); 0128 delete m_thread; 0129 m_thread = nullptr; 0130 } 0131 m_connection->deleteLater(); 0132 m_connection = nullptr; 0133 } 0134 0135 void TestViewporterInterface::testCropScale() 0136 { 0137 // Create a test surface. 0138 QSignalSpy serverSurfaceCreatedSpy(m_serverCompositor, &CompositorInterface::surfaceCreated); 0139 std::unique_ptr<KWayland::Client::Surface> clientSurface(m_clientCompositor->createSurface(this)); 0140 QVERIFY(serverSurfaceCreatedSpy.wait()); 0141 SurfaceInterface *serverSurface = serverSurfaceCreatedSpy.first().first().value<SurfaceInterface *>(); 0142 QVERIFY(serverSurface); 0143 0144 QSignalSpy serverSurfaceMappedSpy(serverSurface, &SurfaceInterface::mapped); 0145 QSignalSpy serverSurfaceSizeChangedSpy(serverSurface, &SurfaceInterface::sizeChanged); 0146 QSignalSpy bufferSourceBoxChangedSpy(serverSurface, &SurfaceInterface::bufferSourceBoxChanged); 0147 0148 // Map the surface. 0149 QImage image(QSize(200, 100), QImage::Format_ARGB32_Premultiplied); 0150 image.fill(Qt::black); 0151 KWayland::Client::Buffer::Ptr buffer = m_shm->createBuffer(image); 0152 clientSurface->attachBuffer(buffer); 0153 clientSurface->setScale(2); 0154 clientSurface->damage(image.rect()); 0155 clientSurface->commit(KWayland::Client::Surface::CommitFlag::None); 0156 QVERIFY(serverSurfaceMappedSpy.wait()); 0157 QCOMPARE(bufferSourceBoxChangedSpy.count(), 1); 0158 QCOMPARE(serverSurface->size(), QSize(100, 50)); 0159 QCOMPARE(serverSurface->bufferSourceBox(), QRectF(0, 0, 200, 100)); 0160 0161 // Create a viewport for the surface. 0162 std::unique_ptr<Viewport> clientViewport(new Viewport); 0163 clientViewport->init(m_viewporter->get_viewport(*clientSurface)); 0164 0165 // Crop the surface. 0166 clientViewport->set_source(wl_fixed_from_double(10), wl_fixed_from_double(10), wl_fixed_from_double(30), wl_fixed_from_double(20)); 0167 clientSurface->commit(KWayland::Client::Surface::CommitFlag::None); 0168 QVERIFY(serverSurfaceSizeChangedSpy.wait()); 0169 QCOMPARE(bufferSourceBoxChangedSpy.count(), 2); 0170 QCOMPARE(serverSurface->size(), QSize(30, 20)); 0171 QCOMPARE(serverSurface->bufferSourceBox(), QRectF(20, 20, 60, 40)); 0172 0173 // Scale the surface. 0174 clientViewport->set_destination(500, 250); 0175 clientSurface->commit(KWayland::Client::Surface::CommitFlag::None); 0176 QVERIFY(serverSurfaceSizeChangedSpy.wait()); 0177 QCOMPARE(bufferSourceBoxChangedSpy.count(), 2); 0178 QCOMPARE(serverSurface->size(), QSize(500, 250)); 0179 QCOMPARE(serverSurface->bufferSourceBox(), QRectF(20, 20, 60, 40)); 0180 0181 // If the viewport is destroyed, the crop and scale state will be unset on a next commit. 0182 clientViewport->destroy(); 0183 clientSurface->commit(KWayland::Client::Surface::CommitFlag::None); 0184 QVERIFY(serverSurfaceSizeChangedSpy.wait()); 0185 QCOMPARE(bufferSourceBoxChangedSpy.count(), 3); 0186 QCOMPARE(serverSurface->size(), QSize(100, 50)); 0187 QCOMPARE(serverSurface->bufferSourceBox(), QRectF(0, 0, 200, 100)); 0188 } 0189 0190 QTEST_GUILESS_MAIN(TestViewporterInterface) 0191 0192 #include "test_viewporter_interface.moc"