File indexing completed on 2024-05-05 17:35:58

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #include "kwin_wayland_test.h"
0010 
0011 #include "core/output.h"
0012 #include "core/outputbackend.h"
0013 #include "cursor.h"
0014 #include "wayland_server.h"
0015 #include "window.h"
0016 #include "workspace.h"
0017 
0018 #include <KConfigGroup>
0019 #include <KWayland/Client/surface.h>
0020 
0021 namespace KWin
0022 {
0023 
0024 static const QString s_socketName = QStringLiteral("wayland_test_kwin_screens-0");
0025 
0026 class ScreensTest : public QObject
0027 {
0028     Q_OBJECT
0029 
0030 private Q_SLOTS:
0031     void initTestCase();
0032     void init();
0033     void cleanup();
0034     void testCurrent_data();
0035     void testCurrent();
0036     void testCurrentWithFollowsMouse_data();
0037     void testCurrentWithFollowsMouse();
0038     void testCurrentPoint_data();
0039     void testCurrentPoint();
0040 };
0041 
0042 void ScreensTest::initTestCase()
0043 {
0044     qRegisterMetaType<KWin::Window *>();
0045     QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
0046     QVERIFY(waylandServer()->init(s_socketName));
0047     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
0048 
0049     kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
0050 
0051     kwinApp()->start();
0052     QVERIFY(applicationStartedSpy.wait());
0053     const auto outputs = workspace()->outputs();
0054     QCOMPARE(outputs.count(), 2);
0055     QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
0056     QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
0057 }
0058 
0059 void ScreensTest::init()
0060 {
0061     workspace()->setActiveOutput(QPoint(640, 512));
0062     KWin::Cursors::self()->mouse()->setPos(QPoint(640, 512));
0063 
0064     QVERIFY(Test::setupWaylandConnection());
0065 }
0066 
0067 static void purge(KConfig *config)
0068 {
0069     const QStringList groups = config->groupList();
0070     for (const QString &group : groups) {
0071         config->deleteGroup(group);
0072     }
0073 }
0074 
0075 void ScreensTest::cleanup()
0076 {
0077     // Destroy the wayland connection of the test window.
0078     Test::destroyWaylandConnection();
0079 
0080     // Wipe the screens config clean.
0081     auto config = kwinApp()->config();
0082     purge(config.data());
0083     config->sync();
0084     workspace()->slotReconfigure();
0085 
0086     // Reset the screen layout of the test environment.
0087     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024)));
0088 }
0089 
0090 void ScreensTest::testCurrent_data()
0091 {
0092     QTest::addColumn<int>("currentId");
0093 
0094     QTest::newRow("first") << 0;
0095     QTest::newRow("second") << 1;
0096 }
0097 
0098 void ScreensTest::testCurrent()
0099 {
0100     QFETCH(int, currentId);
0101     Output *output = workspace()->outputs().at(currentId);
0102 
0103     // Disable "active screen follows mouse"
0104     auto group = kwinApp()->config()->group("Windows");
0105     group.writeEntry("ActiveMouseScreen", false);
0106     group.sync();
0107     workspace()->slotReconfigure();
0108 
0109     workspace()->setActiveOutput(output);
0110     QCOMPARE(workspace()->activeOutput(), output);
0111 }
0112 
0113 void ScreensTest::testCurrentWithFollowsMouse_data()
0114 {
0115     QTest::addColumn<QVector<QRect>>("geometries");
0116     QTest::addColumn<QPoint>("cursorPos");
0117     QTest::addColumn<int>("expectedId");
0118 
0119     QTest::newRow("cloned") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0;
0120     QTest::newRow("adjacent-0") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0;
0121     QTest::newRow("adjacent-1") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1;
0122     QTest::newRow("gap") << QVector<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1;
0123 }
0124 
0125 void ScreensTest::testCurrentWithFollowsMouse()
0126 {
0127     // Enable "active screen follows mouse"
0128     auto group = kwinApp()->config()->group("Windows");
0129     group.writeEntry("ActiveMouseScreen", true);
0130     group.sync();
0131     workspace()->slotReconfigure();
0132 
0133     QFETCH(QVector<QRect>, geometries);
0134     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, geometries));
0135 
0136     QFETCH(QPoint, cursorPos);
0137     KWin::Cursors::self()->mouse()->setPos(cursorPos);
0138 
0139     QFETCH(int, expectedId);
0140     Output *expected = workspace()->outputs().at(expectedId);
0141     QCOMPARE(workspace()->activeOutput(), expected);
0142 }
0143 
0144 void ScreensTest::testCurrentPoint_data()
0145 {
0146     QTest::addColumn<QVector<QRect>>("geometries");
0147     QTest::addColumn<QPoint>("cursorPos");
0148     QTest::addColumn<int>("expectedId");
0149 
0150     QTest::newRow("cloned") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0;
0151     QTest::newRow("adjacent-0") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0;
0152     QTest::newRow("adjacent-1") << QVector<QRect>{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1;
0153     QTest::newRow("gap") << QVector<QRect>{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1;
0154 }
0155 
0156 void ScreensTest::testCurrentPoint()
0157 {
0158     QFETCH(QVector<QRect>, geometries);
0159     QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, geometries));
0160 
0161     // Disable "active screen follows mouse"
0162     auto group = kwinApp()->config()->group("Windows");
0163     group.writeEntry("ActiveMouseScreen", false);
0164     group.sync();
0165     workspace()->slotReconfigure();
0166 
0167     QFETCH(QPoint, cursorPos);
0168     workspace()->setActiveOutput(cursorPos);
0169 
0170     QFETCH(int, expectedId);
0171     Output *expected = workspace()->outputs().at(expectedId);
0172     QCOMPARE(workspace()->activeOutput(), expected);
0173 }
0174 
0175 } // namespace KWin
0176 
0177 WAYLANDTEST_MAIN(KWin::ScreensTest)
0178 #include "screens_test.moc"