diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt index d553e44cf5..b75c5b8954 100644 --- a/autotests/CMakeLists.txt +++ b/autotests/CMakeLists.txt @@ -240,42 +240,6 @@ add_library(effectversionplugin MODULE fakeeffectplugin_version.cpp) set_target_properties(effectversionplugin PROPERTIES PREFIX "") target_link_libraries(effectversionplugin kwineffects) -######################################################## -# Test Screens -######################################################## -set(testScreens_SRCS - ../screens.cpp - ../cursor.cpp - ../x11eventfilter.cpp - mock_abstract_client.cpp - mock_screens.cpp - mock_workspace.cpp - mock_x11client.cpp - test_screens.cpp -) -kconfig_add_kcfg_files(testScreens_SRCS ../settings.kcfgc) - -add_executable(testScreens ${testScreens_SRCS}) -target_include_directories(testScreens BEFORE PRIVATE ./) -target_link_libraries(testScreens - Qt5::DBus - Qt5::Sensors - Qt5::Test - Qt5::Widgets - Qt5::X11Extras - - KF5::ConfigCore - KF5::ConfigGui - KF5::I18n - KF5::Notifications - KF5::WindowSystem - - XCB::XCB #for xcbutils.h -) - -add_test(NAME kwin_testScreens COMMAND testScreens) -ecm_mark_as_test(testScreens) - ######################################################## # Test ScreenEdges ######################################################## diff --git a/autotests/integration/CMakeLists.txt b/autotests/integration/CMakeLists.txt index 22437ed509..a1d1bbec05 100644 --- a/autotests/integration/CMakeLists.txt +++ b/autotests/integration/CMakeLists.txt @@ -96,6 +96,7 @@ integrationTest(WAYLAND_ONLY NAME testBufferSizeChange SRCS buffer_size_change_t integrationTest(WAYLAND_ONLY NAME testPlacement SRCS placement_test.cpp) integrationTest(WAYLAND_ONLY NAME testActivation SRCS activation_test.cpp) integrationTest(WAYLAND_ONLY NAME testInputMethod SRCS inputmethod_test.cpp) +integrationTest(WAYLAND_ONLY NAME testScreens SRCS screens_test.cpp) if (KWIN_BUILD_CMS) integrationTest(WAYLAND_ONLY NAME testNightColor SRCS nightcolor_test.cpp LIBS KWinNightColorPlugin) diff --git a/autotests/integration/screens_test.cpp b/autotests/integration/screens_test.cpp new file mode 100644 index 0000000000..1762776b3f --- /dev/null +++ b/autotests/integration/screens_test.cpp @@ -0,0 +1,342 @@ +/* + KWin - the KDE window manager + This file is part of the KDE project. + + SPDX-FileCopyrightText: 2014 Martin Gräßlin + + SPDX-License-Identifier: GPL-2.0-or-later +*/ +#include "kwin_wayland_test.h" +#include "abstract_client.h" +#include "cursor.h" +#include "platform.h" +#include "screens.h" +#include "wayland_server.h" +#include "workspace.h" + +#include +#include +#include + +namespace KWin +{ + +static const QString s_socketName = QStringLiteral("wayland_test_kwin_screens-0"); + +class ScreensTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void init(); + void cleanup(); + void testCurrentFollowsMouse(); + void testReconfigure_data(); + void testReconfigure(); + void testSize_data(); + void testSize(); + void testCount(); + void testIntersecting_data(); + void testIntersecting(); + void testCurrent_data(); + void testCurrent(); + void testCurrentClient(); + void testCurrentWithFollowsMouse_data(); + void testCurrentWithFollowsMouse(); + void testCurrentPoint_data(); + void testCurrentPoint(); +}; + +void ScreensTest::initTestCase() +{ + qRegisterMetaType(); + QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); + QVERIFY(applicationStartedSpy.isValid()); + kwinApp()->platform()->setInitialWindowSize(QSize(1280, 1024)); + QVERIFY(waylandServer()->init(s_socketName)); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); + + kwinApp()->start(); + QVERIFY(applicationStartedSpy.wait()); + QCOMPARE(screens()->count(), 2); + QCOMPARE(screens()->geometry(0), QRect(0, 0, 1280, 1024)); + QCOMPARE(screens()->geometry(1), QRect(1280, 0, 1280, 1024)); + waylandServer()->initWorkspace(); +} + +void ScreensTest::init() +{ + Screens::self()->setCurrent(0); + KWin::Cursors::self()->mouse()->setPos(QPoint(640, 512)); + + QVERIFY(Test::setupWaylandConnection()); +} + +static void purge(KConfig *config) +{ + const QStringList groups = config->groupList(); + for (const QString &group : groups) { + config->deleteGroup(group); + } +} + +void ScreensTest::cleanup() +{ + // Destroy the wayland connection of the test client. + Test::destroyWaylandConnection(); + + // Wipe the screens config clean. + auto config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + purge(config.data()); + config->sync(); + screens()->setConfig(config); + screens()->reconfigure(); + + // Reset the screen layout of the test environment. + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(int, 2)); +} + +void ScreensTest::testCurrentFollowsMouse() +{ + QVERIFY(!screens()->isCurrentFollowsMouse()); + screens()->setCurrentFollowsMouse(true); + QVERIFY(screens()->isCurrentFollowsMouse()); + // setting to same should not do anything + screens()->setCurrentFollowsMouse(true); + QVERIFY(screens()->isCurrentFollowsMouse()); + + // setting back to other value + screens()->setCurrentFollowsMouse(false); + QVERIFY(!screens()->isCurrentFollowsMouse()); + // setting to same should not do anything + screens()->setCurrentFollowsMouse(false); + QVERIFY(!screens()->isCurrentFollowsMouse()); +} + +void ScreensTest::testReconfigure_data() +{ + QTest::addColumn("focusPolicy"); + QTest::addColumn("expectedDefault"); + QTest::addColumn("setting"); + + QTest::newRow("ClickToFocus") << QStringLiteral("ClickToFocus") << false << true; + QTest::newRow("FocusFollowsMouse") << QStringLiteral("FocusFollowsMouse") << true << false; + QTest::newRow("FocusUnderMouse") << QStringLiteral("FocusUnderMouse") << true << false; + QTest::newRow("FocusStrictlyUnderMouse") << QStringLiteral("FocusStrictlyUnderMouse") << true << false; +} + +void ScreensTest::testReconfigure() +{ + screens()->reconfigure(); + QVERIFY(!screens()->isCurrentFollowsMouse()); + + QFETCH(QString, focusPolicy); + + KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); + config->group("Windows").writeEntry("FocusPolicy", focusPolicy); + config->group("Windows").sync(); + config->sync(); + + screens()->setConfig(config); + screens()->reconfigure(); + QTEST(screens()->isCurrentFollowsMouse(), "expectedDefault"); + + QFETCH(bool, setting); + config->group("Windows").writeEntry("ActiveMouseScreen", setting); + config->sync(); + screens()->reconfigure(); + QCOMPARE(screens()->isCurrentFollowsMouse(), setting); +} + +void ScreensTest::testSize_data() +{ + QTest::addColumn>("geometries"); + QTest::addColumn("expectedSize"); + + QTest::newRow("empty") << QVector{{QRect()}} << QSize(0, 0); + QTest::newRow("cloned") << QVector{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QSize(200, 100); + QTest::newRow("adjacent") << QVector{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QSize(600, 400); + QTest::newRow("overlapping") << QVector{{QRect{-10, -20, 50, 100}, QRect{0, 0, 100, 200}}} << QSize(110, 220); + QTest::newRow("gap") << QVector{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QSize(30, 60); +} + +void ScreensTest::testSize() +{ + QSignalSpy sizeChangedSpy(screens(), &Screens::sizeChanged); + QVERIFY(sizeChangedSpy.isValid()); + + QFETCH(QVector, geometries); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::QueuedConnection, + Q_ARG(int, geometries.count()), Q_ARG(QVector, geometries)); + + QVERIFY(sizeChangedSpy.wait()); + QTEST(screens()->size(), "expectedSize"); +} + +void ScreensTest::testCount() +{ + QSignalSpy countChangedSpy(screens(), &Screens::countChanged); + QVERIFY(countChangedSpy.isValid()); + + // the test environments has two outputs + QCOMPARE(screens()->count(), 2); + + // change to one screen + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::QueuedConnection, Q_ARG(int, 1)); + QVERIFY(countChangedSpy.wait()); + QCOMPARE(countChangedSpy.count(), 1); + QCOMPARE(screens()->count(), 1); + + // setting the same geometries shouldn't emit the signal, but we should get a changed signal + QSignalSpy changedSpy(screens(), &Screens::changed); + QVERIFY(changedSpy.isValid()); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::QueuedConnection, Q_ARG(int, 1)); + QVERIFY(changedSpy.wait()); + QCOMPARE(countChangedSpy.count(), 1); +} + +void ScreensTest::testIntersecting_data() +{ + QTest::addColumn>("geometries"); + QTest::addColumn("testGeometry"); + QTest::addColumn("expectedCount"); + + QTest::newRow("null-rect") << QVector{{QRect{0, 0, 100, 100}}} << QRect() << 0; + QTest::newRow("non-overlapping") << QVector{{QRect{0, 0, 100, 100}}} << QRect(100, 0, 100, 100) << 0; + QTest::newRow("in-between") << QVector{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QRect(15, 0, 2, 2) << 0; + QTest::newRow("gap-overlapping") << QVector{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QRect(9, 10, 200, 200) << 2; + QTest::newRow("larger") << QVector{{QRect{0, 0, 100, 100}}} << QRect(-10, -10, 200, 200) << 1; + QTest::newRow("several") << QVector{{QRect{0, 0, 100, 100}, QRect{100, 0, 100, 100}, QRect{200, 100, 100, 100}, QRect{300, 100, 100, 100}}} << QRect(0, 0, 300, 300) << 3; +} + +void ScreensTest::testIntersecting() +{ + QSignalSpy changedSpy(screens(), &Screens::changed); + QVERIFY(changedSpy.isValid()); + + QFETCH(QVector, geometries); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::QueuedConnection, + Q_ARG(int, geometries.count()), Q_ARG(QVector, geometries)); + QVERIFY(changedSpy.wait()); + + QFETCH(QRect, testGeometry); + QCOMPARE(screens()->count(), geometries.count()); + QTEST(screens()->intersecting(testGeometry), "expectedCount"); +} + +void ScreensTest::testCurrent_data() +{ + QTest::addColumn("current"); + QTest::addColumn("signal"); + + QTest::newRow("unchanged") << 0 << false; + QTest::newRow("changed") << 1 << true; +} + +void ScreensTest::testCurrent() +{ + QSignalSpy currentChangedSpy(screens(), &KWin::Screens::currentChanged); + QVERIFY(currentChangedSpy.isValid()); + + QFETCH(int, current); + screens()->setCurrent(current); + QCOMPARE(screens()->current(), current); + QTEST(!currentChangedSpy.isEmpty(), "signal"); +} + +void ScreensTest::testCurrentClient() +{ + QSignalSpy currentChangedSpy(screens(), &Screens::currentChanged); + QVERIFY(currentChangedSpy.isValid()); + + // create a test window + QScopedPointer surface(Test::createSurface()); + QScopedPointer shellSurface(Test::createXdgShellStableSurface(surface.data())); + AbstractClient *client = Test::renderAndWaitForShown(surface.data(), QSize(200, 100), Qt::red); + QVERIFY(client); + QVERIFY(client->isActive()); + + // if the window is sent to another screen, that screen will become current + client->sendToScreen(1); + QCOMPARE(currentChangedSpy.count(), 1); + QCOMPARE(screens()->current(), 1); + + // setting current with the same client again should not change + screens()->setCurrent(client); + QCOMPARE(currentChangedSpy.count(), 1); + + // and it should even still be on screen 1 if we make the client non-current again + workspace()->setActiveClient(nullptr); + client->setActive(false); + QCOMPARE(screens()->current(), 1); + + // it's not the active client, so changing won't work + screens()->setCurrent(client); + client->sendToScreen(0); + QCOMPARE(currentChangedSpy.count(), 1); + QCOMPARE(screens()->current(), 1); +} + +void ScreensTest::testCurrentWithFollowsMouse_data() +{ + QTest::addColumn>("geometries"); + QTest::addColumn("cursorPos"); + QTest::addColumn("expected"); + + QTest::newRow("empty") << QVector{{QRect()}} << QPoint(100, 100) << 0; + QTest::newRow("cloned") << QVector{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0; + QTest::newRow("adjacent-0") << QVector{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0; + QTest::newRow("adjacent-1") << QVector{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1; + QTest::newRow("gap") << QVector{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1; +} + +void ScreensTest::testCurrentWithFollowsMouse() +{ + QSignalSpy changedSpy(screens(), &Screens::changed); + QVERIFY(changedSpy.isValid()); + screens()->setCurrentFollowsMouse(true); + QCOMPARE(screens()->current(), 0); + + QFETCH(QVector, geometries); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::QueuedConnection, + Q_ARG(int, geometries.count()), Q_ARG(QVector, geometries)); + QVERIFY(changedSpy.wait()); + + QFETCH(QPoint, cursorPos); + KWin::Cursors::self()->mouse()->setPos(cursorPos); + QTEST(screens()->current(), "expected"); +} + +void ScreensTest::testCurrentPoint_data() +{ + QTest::addColumn>("geometries"); + QTest::addColumn("cursorPos"); + QTest::addColumn("expected"); + + QTest::newRow("empty") << QVector{{QRect()}} << QPoint(100, 100) << 0; + QTest::newRow("cloned") << QVector{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0; + QTest::newRow("adjacent-0") << QVector{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0; + QTest::newRow("adjacent-1") << QVector{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1; + QTest::newRow("gap") << QVector{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1; +} + +void ScreensTest::testCurrentPoint() +{ + QSignalSpy changedSpy(screens(), &KWin::Screens::changed); + QVERIFY(changedSpy.isValid()); + + QFETCH(QVector, geometries); + QMetaObject::invokeMethod(kwinApp()->platform(), "setVirtualOutputs", Qt::QueuedConnection, + Q_ARG(int, geometries.count()), Q_ARG(QVector, geometries)); + QVERIFY(changedSpy.wait()); + + QFETCH(QPoint, cursorPos); + screens()->setCurrent(cursorPos); + QTEST(screens()->current(), "expected"); +} + +} // namespace KWin + +WAYLANDTEST_MAIN(KWin::ScreensTest) +#include "screens_test.moc" diff --git a/autotests/test_screens.cpp b/autotests/test_screens.cpp deleted file mode 100644 index 493600f745..0000000000 --- a/autotests/test_screens.cpp +++ /dev/null @@ -1,345 +0,0 @@ -/* - KWin - the KDE window manager - This file is part of the KDE project. - - SPDX-FileCopyrightText: 2014 Martin Gräßlin - - SPDX-License-Identifier: GPL-2.0-or-later -*/ -#include "mock_workspace.h" -#include "../cursor.h" -#include "mock_screens.h" -#include "mock_x11client.h" -// frameworks -#include -// Qt -#include - -Q_LOGGING_CATEGORY(KWIN_CORE, "kwin_core") - -// Mock - -class TestScreens : public QObject -{ - Q_OBJECT -private Q_SLOTS: - void init(); - void testCurrentFollowsMouse(); - void testReconfigure_data(); - void testReconfigure(); - void testSize_data(); - void testSize(); - void testCount(); - void testIntersecting_data(); - void testIntersecting(); - void testCurrent_data(); - void testCurrent(); - void testCurrentClient(); - void testCurrentWithFollowsMouse_data(); - void testCurrentWithFollowsMouse(); - void testCurrentPoint_data(); - void testCurrentPoint(); -}; - -void TestScreens::init() -{ - KWin::Cursors::self()->setMouse(new KWin::Cursor(this)); -} - -void TestScreens::testCurrentFollowsMouse() -{ - KWin::MockWorkspace ws; - KWin::Screens *screens = KWin::Screens::create(&ws); - QVERIFY(!screens->isCurrentFollowsMouse()); - screens->setCurrentFollowsMouse(true); - QVERIFY(screens->isCurrentFollowsMouse()); - // setting to same should not do anything - screens->setCurrentFollowsMouse(true); - QVERIFY(screens->isCurrentFollowsMouse()); - - // setting back to other value - screens->setCurrentFollowsMouse(false); - QVERIFY(!screens->isCurrentFollowsMouse()); - // setting to same should not do anything - screens->setCurrentFollowsMouse(false); - QVERIFY(!screens->isCurrentFollowsMouse()); -} - -void TestScreens::testReconfigure_data() -{ - QTest::addColumn("focusPolicy"); - QTest::addColumn("expectedDefault"); - QTest::addColumn("setting"); - - QTest::newRow("ClickToFocus") << QStringLiteral("ClickToFocus") << false << true; - QTest::newRow("FocusFollowsMouse") << QStringLiteral("FocusFollowsMouse") << true << false; - QTest::newRow("FocusUnderMouse") << QStringLiteral("FocusUnderMouse") << true << false; - QTest::newRow("FocusStrictlyUnderMouse") << QStringLiteral("FocusStrictlyUnderMouse") << true << false; -} - -void TestScreens::testReconfigure() -{ - using namespace KWin; - MockWorkspace ws; - Screens::create(&ws); - screens()->reconfigure(); - QVERIFY(!screens()->isCurrentFollowsMouse()); - - QFETCH(QString, focusPolicy); - - KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig); - config->group("Windows").writeEntry("FocusPolicy", focusPolicy); - config->group("Windows").sync(); - config->sync(); - - screens()->setConfig(config); - screens()->reconfigure(); - QTEST(screens()->isCurrentFollowsMouse(), "expectedDefault"); - - QFETCH(bool, setting); - config->group("Windows").writeEntry("ActiveMouseScreen", setting); - config->sync(); - screens()->reconfigure(); - QCOMPARE(screens()->isCurrentFollowsMouse(), setting); -} - -void TestScreens::testSize_data() -{ - QTest::addColumn< QList >("geometries"); - QTest::addColumn("expectedSize"); - - QTest::newRow("empty") << QList{{QRect()}} << QSize(0, 0); - QTest::newRow("cloned") << QList{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QSize(200, 100); - QTest::newRow("adjacent") << QList{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QSize(600, 400); - QTest::newRow("overlapping") << QList{{QRect{-10, -20, 50, 100}, QRect{0, 0, 100, 200}}} << QSize(110, 220); - QTest::newRow("gap") << QList{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QSize(30, 60); -} - -void TestScreens::testSize() -{ - using namespace KWin; - MockWorkspace ws; - MockScreens *mockScreens = static_cast(Screens::create(&ws)); - QSignalSpy sizeChangedSpy(screens(), &KWin::Screens::sizeChanged); - QVERIFY(sizeChangedSpy.isValid()); - - QCOMPARE(screens()->size(), QSize(100, 100)); - QFETCH(QList, geometries); - QVERIFY(!mockScreens->isChanging()); - mockScreens->setGeometries(geometries); - QVERIFY(mockScreens->isChanging()); - - QVERIFY(sizeChangedSpy.wait()); - QVERIFY(!mockScreens->isChanging()); - QTEST(screens()->size(), "expectedSize"); -} - -void TestScreens::testCount() -{ - using namespace KWin; - MockWorkspace ws; - MockScreens *mockScreens = static_cast(Screens::create(&ws)); - QSignalSpy countChangedSpy(screens(), &KWin::Screens::countChanged); - QVERIFY(countChangedSpy.isValid()); - - QCOMPARE(screens()->count(), 1); - - // change to two screens - QList geometries{{QRect{0, 0, 100, 200}, QRect{100, 0, 100, 200}}}; - mockScreens->setGeometries(geometries); - - QVERIFY(countChangedSpy.wait()); - QCOMPARE(countChangedSpy.count(), 1); - QCOMPARE(countChangedSpy.first().first().toInt(), 1); - QCOMPARE(countChangedSpy.first().last().toInt(), 2); - QCOMPARE(screens()->count(), 2); - - // go back to one screen - geometries.takeLast(); - mockScreens->setGeometries(geometries); - QVERIFY(countChangedSpy.wait()); - QCOMPARE(countChangedSpy.count(), 2); - QCOMPARE(countChangedSpy.last().first().toInt(), 2); - QCOMPARE(countChangedSpy.last().last().toInt(), 1); - QCOMPARE(screens()->count(), 1); - - // setting the same geometries shouldn't emit the signal, but we should get a changed signal - QSignalSpy changedSpy(screens(), &KWin::Screens::changed); - QVERIFY(changedSpy.isValid()); - mockScreens->setGeometries(geometries); - QVERIFY(changedSpy.wait()); - QCOMPARE(countChangedSpy.count(), 2); -} - -void TestScreens::testIntersecting_data() -{ - QTest::addColumn>("geometries"); - QTest::addColumn("testGeometry"); - QTest::addColumn("expectedCount"); - - QTest::newRow("null-rect") << QList{{QRect{0, 0, 100, 100}}} << QRect() << 0; - QTest::newRow("non-overlapping") << QList{{QRect{0, 0, 100, 100}}} << QRect(100, 0, 100, 100) << 0; - QTest::newRow("in-between") << QList{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QRect(15, 0, 2, 2) << 0; - QTest::newRow("gap-overlapping") << QList{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QRect(9, 10, 200, 200) << 2; - QTest::newRow("larger") << QList{{QRect{0, 0, 100, 100}}} << QRect(-10, -10, 200, 200) << 1; - QTest::newRow("several") << QList{{QRect{0, 0, 100, 100}, QRect{100, 0, 100, 100}, QRect{200, 100, 100, 100}, QRect{300, 100, 100, 100}}} << QRect(0, 0, 300, 300) << 3; -} - -void TestScreens::testIntersecting() -{ - using namespace KWin; - MockWorkspace ws; - MockScreens *mockScreens = static_cast(Screens::create(&ws)); - QSignalSpy changedSpy(screens(), &KWin::Screens::changed); - QVERIFY(changedSpy.isValid()); - QFETCH(QList, geometries); - mockScreens->setGeometries(geometries); - // first is before it's updated - QVERIFY(changedSpy.wait()); - // second is after it's updated - QVERIFY(changedSpy.wait()); - - QFETCH(QRect, testGeometry); - QCOMPARE(screens()->count(), geometries.count()); - QTEST(screens()->intersecting(testGeometry), "expectedCount"); -} - -void TestScreens::testCurrent_data() -{ - QTest::addColumn("current"); - QTest::addColumn("signal"); - - QTest::newRow("unchanged") << 0 << false; - QTest::newRow("changed") << 1 << true; -} - -void TestScreens::testCurrent() -{ - using namespace KWin; - MockWorkspace ws; - Screens::create(&ws); - QSignalSpy currentChangedSpy(screens(), &KWin::Screens::currentChanged); - QVERIFY(currentChangedSpy.isValid()); - - QFETCH(int, current); - screens()->setCurrent(current); - QCOMPARE(screens()->current(), current); - QTEST(!currentChangedSpy.isEmpty(), "signal"); -} - -void TestScreens::testCurrentClient() -{ - using namespace KWin; - MockWorkspace ws; - MockScreens *mockScreens = static_cast(Screens::create(&ws)); - QSignalSpy changedSpy(screens(), &KWin::Screens::changed); - QVERIFY(changedSpy.isValid()); - mockScreens->setGeometries(QList{{QRect{0, 0, 100, 100}, QRect{100, 0, 100, 100}}}); - // first is before it's updated - QVERIFY(changedSpy.wait()); - // second is after it's updated - QVERIFY(changedSpy.wait()); - - QSignalSpy currentChangedSpy(screens(), &KWin::Screens::currentChanged); - QVERIFY(currentChangedSpy.isValid()); - - // create a mock client - X11Client *client = new X11Client(&ws); - client->setScreen(1); - - // it's not the active client, so changing won't work - screens()->setCurrent(client); - QVERIFY(currentChangedSpy.isEmpty()); - QCOMPARE(screens()->current(), 0); - - // making the client active should affect things - client->setActive(true); - ws.setActiveClient(client); - - // first of all current should be changed just by the fact that there is an active client - QCOMPARE(screens()->current(), 1); - // but also calling setCurrent should emit the changed signal - screens()->setCurrent(client); - QCOMPARE(currentChangedSpy.count(), 1); - QCOMPARE(screens()->current(), 1); - - // setting current with the same client again should not change, though - screens()->setCurrent(client); - QCOMPARE(currentChangedSpy.count(), 1); - - // and it should even still be on screen 1 if we make the client non-current again - ws.setActiveClient(nullptr); - client->setActive(false); - QCOMPARE(screens()->current(), 1); -} - -void TestScreens::testCurrentWithFollowsMouse_data() -{ - QTest::addColumn< QList >("geometries"); - QTest::addColumn("cursorPos"); - QTest::addColumn("expected"); - - QTest::newRow("empty") << QList{{QRect()}} << QPoint(100, 100) << 0; - QTest::newRow("cloned") << QList{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0; - QTest::newRow("adjacent-0") << QList{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0; - QTest::newRow("adjacent-1") << QList{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1; - QTest::newRow("gap") << QList{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1; -} - -void TestScreens::testCurrentWithFollowsMouse() -{ - using namespace KWin; - MockWorkspace ws; - MockScreens *mockScreens = static_cast(Screens::create(&ws)); - QSignalSpy changedSpy(screens(), &KWin::Screens::changed); - QVERIFY(changedSpy.isValid()); - screens()->setCurrentFollowsMouse(true); - QCOMPARE(screens()->current(), 0); - - QFETCH(QList, geometries); - mockScreens->setGeometries(geometries); - // first is before it's updated - QVERIFY(changedSpy.wait()); - // second is after it's updated - QVERIFY(changedSpy.wait()); - - QFETCH(QPoint, cursorPos); - KWin::Cursors::self()->mouse()->setPos(cursorPos); - QTEST(screens()->current(), "expected"); -} - -void TestScreens::testCurrentPoint_data() -{ - QTest::addColumn< QList >("geometries"); - QTest::addColumn("cursorPos"); - QTest::addColumn("expected"); - - QTest::newRow("empty") << QList{{QRect()}} << QPoint(100, 100) << 0; - QTest::newRow("cloned") << QList{{QRect{0, 0, 200, 100}, QRect{0, 0, 200, 100}}} << QPoint(50, 50) << 0; - QTest::newRow("adjacent-0") << QList{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(199, 99) << 0; - QTest::newRow("adjacent-1") << QList{{QRect{0, 0, 200, 100}, QRect{200, 100, 400, 300}}} << QPoint(200, 100) << 1; - QTest::newRow("gap") << QList{{QRect{0, 0, 10, 20}, QRect{20, 40, 10, 20}}} << QPoint(15, 30) << 1; -} - -void TestScreens::testCurrentPoint() -{ - using namespace KWin; - MockWorkspace ws; - MockScreens *mockScreens = static_cast(Screens::create(&ws)); - QSignalSpy changedSpy(screens(), &KWin::Screens::changed); - QVERIFY(changedSpy.isValid()); - - QFETCH(QList, geometries); - mockScreens->setGeometries(geometries); - // first is before it's updated - QVERIFY(changedSpy.wait()); - // second is after it's updated - QVERIFY(changedSpy.wait()); - - QFETCH(QPoint, cursorPos); - screens()->setCurrent(cursorPos); - QTEST(screens()->current(), "expected"); -} - -QTEST_MAIN(TestScreens) -#include "test_screens.moc"