File indexing completed on 2024-11-10 04:56:18
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 <QSignalSpy> 0008 #include <QTest> 0009 // KWin 0010 #include "wayland/display.h" 0011 #include "wayland/output.h" 0012 0013 #include "KWayland/Client/connection_thread.h" 0014 #include "KWayland/Client/event_queue.h" 0015 #include "KWayland/Client/output.h" 0016 #include "KWayland/Client/registry.h" 0017 0018 #include "../../../tests/fakeoutput.h" 0019 0020 // Wayland 0021 #include <wayland-client-protocol.h> 0022 0023 class TestWaylandOutput : public QObject 0024 { 0025 Q_OBJECT 0026 public: 0027 explicit TestWaylandOutput(QObject *parent = nullptr); 0028 private Q_SLOTS: 0029 void init(); 0030 void cleanup(); 0031 0032 void testRegistry(); 0033 void testModeChange(); 0034 void testScaleChange(); 0035 0036 void testSubPixel_data(); 0037 void testSubPixel(); 0038 0039 void testTransform_data(); 0040 void testTransform(); 0041 0042 private: 0043 KWin::Display *m_display; 0044 KWayland::Client::ConnectionThread *m_connection; 0045 KWayland::Client::EventQueue *m_queue; 0046 QThread *m_thread; 0047 }; 0048 0049 static const QString s_socketName = QStringLiteral("kwin-test-wayland-output-0"); 0050 0051 TestWaylandOutput::TestWaylandOutput(QObject *parent) 0052 : QObject(parent) 0053 , m_display(nullptr) 0054 , m_connection(nullptr) 0055 , m_thread(nullptr) 0056 { 0057 } 0058 0059 void TestWaylandOutput::init() 0060 { 0061 delete m_display; 0062 m_display = new KWin::Display(this); 0063 m_display->addSocketName(s_socketName); 0064 m_display->start(); 0065 QVERIFY(m_display->isRunning()); 0066 0067 // setup connection 0068 m_connection = new KWayland::Client::ConnectionThread; 0069 QSignalSpy connectedSpy(m_connection, &KWayland::Client::ConnectionThread::connected); 0070 m_connection->setSocketName(s_socketName); 0071 0072 m_thread = new QThread(this); 0073 m_connection->moveToThread(m_thread); 0074 m_thread->start(); 0075 0076 m_connection->initConnection(); 0077 QVERIFY(connectedSpy.wait()); 0078 0079 m_queue = new KWayland::Client::EventQueue(this); 0080 QVERIFY(!m_queue->isValid()); 0081 m_queue->setup(m_connection); 0082 QVERIFY(m_queue->isValid()); 0083 } 0084 0085 void TestWaylandOutput::cleanup() 0086 { 0087 if (m_queue) { 0088 delete m_queue; 0089 m_queue = nullptr; 0090 } 0091 if (m_thread) { 0092 m_thread->quit(); 0093 m_thread->wait(); 0094 delete m_thread; 0095 m_thread = nullptr; 0096 } 0097 delete m_connection; 0098 m_connection = nullptr; 0099 0100 delete m_display; 0101 m_display = nullptr; 0102 } 0103 0104 void TestWaylandOutput::testRegistry() 0105 { 0106 auto outputHandle = std::make_unique<FakeOutput>(); 0107 outputHandle->setMode(QSize(1024, 768), 60000); 0108 outputHandle->moveTo(QPoint(100, 50)); 0109 outputHandle->setPhysicalSize(QSize(200, 100)); 0110 0111 auto outputInterface = std::make_unique<KWin::OutputInterface>(m_display, outputHandle.get()); 0112 0113 KWayland::Client::Registry registry; 0114 QSignalSpy announced(®istry, &KWayland::Client::Registry::outputAnnounced); 0115 registry.create(m_connection->display()); 0116 QVERIFY(registry.isValid()); 0117 registry.setup(); 0118 wl_display_flush(m_connection->display()); 0119 QVERIFY(announced.wait()); 0120 0121 KWayland::Client::Output output; 0122 QVERIFY(!output.isValid()); 0123 QCOMPARE(output.geometry(), QRect()); 0124 QCOMPARE(output.globalPosition(), QPoint()); 0125 QCOMPARE(output.manufacturer(), QString()); 0126 QCOMPARE(output.model(), QString()); 0127 QCOMPARE(output.physicalSize(), QSize()); 0128 QCOMPARE(output.pixelSize(), QSize()); 0129 QCOMPARE(output.refreshRate(), 0); 0130 QCOMPARE(output.scale(), 1); 0131 QCOMPARE(output.subPixel(), KWayland::Client::Output::SubPixel::Unknown); 0132 QCOMPARE(output.transform(), KWayland::Client::Output::Transform::Normal); 0133 0134 QSignalSpy outputChanged(&output, &KWayland::Client::Output::changed); 0135 auto o = registry.bindOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>()); 0136 QVERIFY(!KWayland::Client::Output::get(o)); 0137 output.setup(o); 0138 QCOMPARE(KWayland::Client::Output::get(o), &output); 0139 wl_display_flush(m_connection->display()); 0140 QVERIFY(outputChanged.wait()); 0141 0142 QCOMPARE(output.geometry(), QRect(100, 50, 1024, 768)); 0143 QCOMPARE(output.globalPosition(), QPoint(100, 50)); 0144 QCOMPARE(output.manufacturer(), QString()); 0145 QCOMPARE(output.model(), QString()); 0146 QCOMPARE(output.physicalSize(), QSize(200, 100)); 0147 QCOMPARE(output.pixelSize(), QSize(1024, 768)); 0148 QCOMPARE(output.refreshRate(), 60000); 0149 QCOMPARE(output.scale(), 1); 0150 // for xwayland output it's unknown 0151 QCOMPARE(output.subPixel(), KWayland::Client::Output::SubPixel::Unknown); 0152 // for xwayland transform is normal 0153 QCOMPARE(output.transform(), KWayland::Client::Output::Transform::Normal); 0154 } 0155 0156 void TestWaylandOutput::testModeChange() 0157 { 0158 auto outputHandle = std::make_unique<FakeOutput>(); 0159 outputHandle->setMode(QSize(1024, 768), 60000); 0160 0161 auto outputInterface = std::make_unique<KWin::OutputInterface>(m_display, outputHandle.get()); 0162 0163 KWayland::Client::Registry registry; 0164 QSignalSpy announced(®istry, &KWayland::Client::Registry::outputAnnounced); 0165 registry.setEventQueue(m_queue); 0166 registry.create(m_connection->display()); 0167 QVERIFY(registry.isValid()); 0168 registry.setup(); 0169 wl_display_flush(m_connection->display()); 0170 QVERIFY(announced.wait()); 0171 0172 KWayland::Client::Output output; 0173 QSignalSpy outputChanged(&output, &KWayland::Client::Output::changed); 0174 QSignalSpy modeAddedSpy(&output, &KWayland::Client::Output::modeAdded); 0175 output.setup(registry.bindOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>())); 0176 wl_display_flush(m_connection->display()); 0177 QVERIFY(outputChanged.wait()); 0178 QCOMPARE(modeAddedSpy.count(), 1); 0179 QCOMPARE(modeAddedSpy.at(0).first().value<KWayland::Client::Output::Mode>().size, QSize(1024, 768)); 0180 QCOMPARE(modeAddedSpy.at(0).first().value<KWayland::Client::Output::Mode>().refreshRate, 60000); 0181 QCOMPARE(modeAddedSpy.at(0).first().value<KWayland::Client::Output::Mode>().flags, KWayland::Client::Output::Mode::Flags(KWayland::Client::Output::Mode::Flag::Current)); 0182 QCOMPARE(modeAddedSpy.at(0).first().value<KWayland::Client::Output::Mode>().output, QPointer<KWayland::Client::Output>(&output)); 0183 QCOMPARE(output.pixelSize(), QSize(1024, 768)); 0184 QCOMPARE(output.refreshRate(), 60000); 0185 0186 // change once more 0187 outputHandle->setMode(QSize(1280, 1024), 90000); 0188 QVERIFY(outputChanged.wait()); 0189 QCOMPARE(modeAddedSpy.count(), 2); 0190 QCOMPARE(modeAddedSpy.at(1).first().value<KWayland::Client::Output::Mode>().size, QSize(1280, 1024)); 0191 QCOMPARE(modeAddedSpy.at(1).first().value<KWayland::Client::Output::Mode>().refreshRate, 90000); 0192 QCOMPARE(modeAddedSpy.at(1).first().value<KWayland::Client::Output::Mode>().flags, KWayland::Client::Output::Mode::Flags(KWayland::Client::Output::Mode::Flag::Current)); 0193 QCOMPARE(modeAddedSpy.at(1).first().value<KWayland::Client::Output::Mode>().output, QPointer<KWayland::Client::Output>(&output)); 0194 QCOMPARE(output.pixelSize(), QSize(1280, 1024)); 0195 QCOMPARE(output.refreshRate(), 90000); 0196 } 0197 0198 void TestWaylandOutput::testScaleChange() 0199 { 0200 auto outputHandle = std::make_unique<FakeOutput>(); 0201 outputHandle->setMode(QSize(1024, 768), 60000); 0202 0203 auto outputInterface = std::make_unique<KWin::OutputInterface>(m_display, outputHandle.get()); 0204 0205 KWayland::Client::Registry registry; 0206 QSignalSpy announced(®istry, &KWayland::Client::Registry::outputAnnounced); 0207 registry.create(m_connection->display()); 0208 QVERIFY(registry.isValid()); 0209 registry.setup(); 0210 wl_display_flush(m_connection->display()); 0211 QVERIFY(announced.wait()); 0212 0213 KWayland::Client::Output output; 0214 QSignalSpy outputChanged(&output, &KWayland::Client::Output::changed); 0215 output.setup(registry.bindOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>())); 0216 wl_display_flush(m_connection->display()); 0217 QVERIFY(outputChanged.wait()); 0218 QCOMPARE(output.scale(), 1); 0219 0220 // change the scale 0221 outputChanged.clear(); 0222 outputHandle->setScale(2); 0223 QVERIFY(outputChanged.wait()); 0224 QCOMPARE(output.scale(), 2); 0225 // changing to same value should not trigger 0226 outputHandle->setScale(2); 0227 QVERIFY(!outputChanged.wait(100)); 0228 0229 // change once more 0230 outputChanged.clear(); 0231 outputHandle->setScale(4); 0232 QVERIFY(outputChanged.wait()); 0233 QCOMPARE(output.scale(), 4); 0234 } 0235 0236 void TestWaylandOutput::testSubPixel_data() 0237 { 0238 QTest::addColumn<KWayland::Client::Output::SubPixel>("expected"); 0239 QTest::addColumn<KWin::Output::SubPixel>("actual"); 0240 0241 QTest::newRow("none") << KWayland::Client::Output::SubPixel::None << KWin::Output::SubPixel::None; 0242 QTest::newRow("horizontal/rgb") << KWayland::Client::Output::SubPixel::HorizontalRGB << KWin::Output::SubPixel::Horizontal_RGB; 0243 QTest::newRow("horizontal/bgr") << KWayland::Client::Output::SubPixel::HorizontalBGR << KWin::Output::SubPixel::Horizontal_BGR; 0244 QTest::newRow("vertical/rgb") << KWayland::Client::Output::SubPixel::VerticalRGB << KWin::Output::SubPixel::Vertical_RGB; 0245 QTest::newRow("vertical/bgr") << KWayland::Client::Output::SubPixel::VerticalBGR << KWin::Output::SubPixel::Vertical_BGR; 0246 } 0247 0248 void TestWaylandOutput::testSubPixel() 0249 { 0250 QFETCH(KWin::Output::SubPixel, actual); 0251 0252 auto outputHandle = std::make_unique<FakeOutput>(); 0253 outputHandle->setMode(QSize(1024, 768), 60000); 0254 outputHandle->setSubPixel(actual); 0255 0256 auto outputInterface = std::make_unique<KWin::OutputInterface>(m_display, outputHandle.get()); 0257 0258 KWayland::Client::Registry registry; 0259 QSignalSpy announced(®istry, &KWayland::Client::Registry::outputAnnounced); 0260 registry.create(m_connection->display()); 0261 QVERIFY(registry.isValid()); 0262 registry.setup(); 0263 wl_display_flush(m_connection->display()); 0264 QVERIFY(announced.wait()); 0265 0266 KWayland::Client::Output output; 0267 QSignalSpy outputChanged(&output, &KWayland::Client::Output::changed); 0268 output.setup(registry.bindOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>())); 0269 wl_display_flush(m_connection->display()); 0270 if (outputChanged.isEmpty()) { 0271 QVERIFY(outputChanged.wait()); 0272 } 0273 0274 QTEST(output.subPixel(), "expected"); 0275 } 0276 0277 void TestWaylandOutput::testTransform_data() 0278 { 0279 QTest::addColumn<KWayland::Client::Output::Transform>("expected"); 0280 QTest::addColumn<KWin::OutputTransform::Kind>("actual"); 0281 0282 QTest::newRow("90") << KWayland::Client::Output::Transform::Rotated90 << KWin::OutputTransform::Rotate90; 0283 QTest::newRow("180") << KWayland::Client::Output::Transform::Rotated180 << KWin::OutputTransform::Rotate180; 0284 QTest::newRow("270") << KWayland::Client::Output::Transform::Rotated270 << KWin::OutputTransform::Rotate270; 0285 QTest::newRow("Flipped") << KWayland::Client::Output::Transform::Flipped << KWin::OutputTransform::FlipX; 0286 QTest::newRow("Flipped 90") << KWayland::Client::Output::Transform::Flipped90 << KWin::OutputTransform::FlipX90; 0287 QTest::newRow("Flipped 180") << KWayland::Client::Output::Transform::Flipped180 << KWin::OutputTransform::FlipX180; 0288 QTest::newRow("Flipped 280") << KWayland::Client::Output::Transform::Flipped270 << KWin::OutputTransform::FlipX270; 0289 } 0290 0291 void TestWaylandOutput::testTransform() 0292 { 0293 QFETCH(KWin::OutputTransform::Kind, actual); 0294 0295 auto outputHandle = std::make_unique<FakeOutput>(); 0296 outputHandle->setMode(QSize(1024, 768), 60000); 0297 outputHandle->setTransform(actual); 0298 0299 auto outputInterface = std::make_unique<KWin::OutputInterface>(m_display, outputHandle.get()); 0300 0301 using namespace KWin; 0302 0303 KWayland::Client::Registry registry; 0304 QSignalSpy announced(®istry, &KWayland::Client::Registry::outputAnnounced); 0305 registry.create(m_connection->display()); 0306 QVERIFY(registry.isValid()); 0307 registry.setup(); 0308 wl_display_flush(m_connection->display()); 0309 QVERIFY(announced.wait()); 0310 0311 KWayland::Client::Output *output = registry.createOutput(announced.first().first().value<quint32>(), announced.first().last().value<quint32>(), ®istry); 0312 QSignalSpy outputChanged(output, &KWayland::Client::Output::changed); 0313 wl_display_flush(m_connection->display()); 0314 if (outputChanged.isEmpty()) { 0315 QVERIFY(outputChanged.wait()); 0316 } 0317 0318 QTEST(output->transform(), "expected"); 0319 0320 // change back to normal 0321 outputChanged.clear(); 0322 outputHandle->setTransform(KWin::OutputTransform::Normal); 0323 if (outputChanged.isEmpty()) { 0324 QVERIFY(outputChanged.wait()); 0325 } 0326 QCOMPARE(output->transform(), KWayland::Client::Output::Transform::Normal); 0327 } 0328 0329 QTEST_GUILESS_MAIN(TestWaylandOutput) 0330 #include "test_wayland_output.moc"