File indexing completed on 2025-03-16 13:56:01
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2017 Martin Flöser <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "kwin_wayland_test.h" 0010 0011 #include "core/outputbackend.h" 0012 #include "main.h" 0013 #include "virtualdesktops.h" 0014 #include "wayland_server.h" 0015 #include "window.h" 0016 #include "workspace.h" 0017 0018 #include <KWayland/Client/surface.h> 0019 0020 using namespace KWin; 0021 0022 static const QString s_socketName = QStringLiteral("wayland_test_kwin_virtualdesktop-0"); 0023 0024 class VirtualDesktopTest : public QObject 0025 { 0026 Q_OBJECT 0027 private Q_SLOTS: 0028 void initTestCase(); 0029 void init(); 0030 void cleanup(); 0031 0032 void testNetCurrentDesktop(); 0033 void testLastDesktopRemoved(); 0034 void testWindowOnMultipleDesktops(); 0035 void testRemoveDesktopWithWindow(); 0036 }; 0037 0038 void VirtualDesktopTest::initTestCase() 0039 { 0040 qRegisterMetaType<KWin::Window *>(); 0041 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0042 QVERIFY(waylandServer()->init(s_socketName)); 0043 QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024))); 0044 0045 kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); 0046 qputenv("KWIN_XKB_DEFAULT_KEYMAP", "1"); 0047 qputenv("XKB_DEFAULT_RULES", "evdev"); 0048 0049 kwinApp()->start(); 0050 QVERIFY(applicationStartedSpy.wait()); 0051 0052 if (kwinApp()->x11Connection()) { 0053 // verify the current desktop x11 property on startup, see BUG: 391034 0054 Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP"); 0055 QVERIFY(currentDesktopAtom.isValid()); 0056 Xcb::Property currentDesktop(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0057 bool ok = true; 0058 QCOMPARE(currentDesktop.value(0, &ok), 0); 0059 QVERIFY(ok); 0060 } 0061 } 0062 0063 void VirtualDesktopTest::init() 0064 { 0065 QVERIFY(Test::setupWaylandConnection()); 0066 workspace()->setActiveOutput(QPoint(640, 512)); 0067 VirtualDesktopManager::self()->setCount(1); 0068 } 0069 0070 void VirtualDesktopTest::cleanup() 0071 { 0072 Test::destroyWaylandConnection(); 0073 } 0074 0075 void VirtualDesktopTest::testNetCurrentDesktop() 0076 { 0077 if (!kwinApp()->x11Connection()) { 0078 QSKIP("Skipped on Wayland only"); 0079 } 0080 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0081 VirtualDesktopManager::self()->setCount(4); 0082 QCOMPARE(VirtualDesktopManager::self()->count(), 4u); 0083 0084 Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP"); 0085 QVERIFY(currentDesktopAtom.isValid()); 0086 Xcb::Property currentDesktop(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0087 bool ok = true; 0088 QCOMPARE(currentDesktop.value(0, &ok), 0); 0089 QVERIFY(ok); 0090 0091 // go to desktop 2 0092 VirtualDesktopManager::self()->setCurrent(2); 0093 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0094 QCOMPARE(currentDesktop.value(0, &ok), 1); 0095 QVERIFY(ok); 0096 0097 // go to desktop 3 0098 VirtualDesktopManager::self()->setCurrent(3); 0099 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0100 QCOMPARE(currentDesktop.value(0, &ok), 2); 0101 QVERIFY(ok); 0102 0103 // go to desktop 4 0104 VirtualDesktopManager::self()->setCurrent(4); 0105 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0106 QCOMPARE(currentDesktop.value(0, &ok), 3); 0107 QVERIFY(ok); 0108 0109 // and back to first 0110 VirtualDesktopManager::self()->setCurrent(1); 0111 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0112 QCOMPARE(currentDesktop.value(0, &ok), 0); 0113 QVERIFY(ok); 0114 } 0115 0116 void VirtualDesktopTest::testLastDesktopRemoved() 0117 { 0118 // first create a new desktop 0119 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0120 VirtualDesktopManager::self()->setCount(2); 0121 QCOMPARE(VirtualDesktopManager::self()->count(), 2u); 0122 0123 // switch to last desktop 0124 VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last()); 0125 QCOMPARE(VirtualDesktopManager::self()->current(), 2u); 0126 0127 // now create a window on this desktop 0128 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0129 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0130 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0131 0132 QVERIFY(window); 0133 QCOMPARE(window->desktop(), 2); 0134 QSignalSpy desktopPresenceChangedSpy(window, &Window::desktopPresenceChanged); 0135 0136 QCOMPARE(window->desktops().count(), 1u); 0137 QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first()); 0138 0139 // and remove last desktop 0140 VirtualDesktopManager::self()->setCount(1); 0141 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0142 // now the window should be moved as well 0143 QTRY_COMPARE(desktopPresenceChangedSpy.count(), 1); 0144 QCOMPARE(window->desktop(), 1); 0145 0146 QCOMPARE(window->desktops().count(), 1u); 0147 QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first()); 0148 } 0149 0150 void VirtualDesktopTest::testWindowOnMultipleDesktops() 0151 { 0152 // first create two new desktops 0153 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0154 VirtualDesktopManager::self()->setCount(3); 0155 QCOMPARE(VirtualDesktopManager::self()->count(), 3u); 0156 0157 // switch to last desktop 0158 VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last()); 0159 QCOMPARE(VirtualDesktopManager::self()->current(), 3u); 0160 0161 // now create a window on this desktop 0162 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0163 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0164 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0165 0166 QVERIFY(window); 0167 QCOMPARE(window->desktop(), 3u); 0168 QSignalSpy desktopPresenceChangedSpy(window, &Window::desktopPresenceChanged); 0169 0170 QCOMPARE(window->desktops().count(), 1u); 0171 QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first()); 0172 0173 // Set the window on desktop 2 as well 0174 window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(2)); 0175 QCOMPARE(window->desktops().count(), 2u); 0176 QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]); 0177 QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[1]); 0178 QVERIFY(window->isOnDesktop(2)); 0179 QVERIFY(window->isOnDesktop(3)); 0180 0181 // leave desktop 3 0182 window->leaveDesktop(VirtualDesktopManager::self()->desktopForX11Id(3)); 0183 QCOMPARE(window->desktops().count(), 1u); 0184 // leave desktop 2 0185 window->leaveDesktop(VirtualDesktopManager::self()->desktopForX11Id(2)); 0186 QCOMPARE(window->desktops().count(), 0u); 0187 // we should be on all desktops now 0188 QVERIFY(window->isOnAllDesktops()); 0189 // put on desktop 1 0190 window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(1)); 0191 QVERIFY(window->isOnDesktop(1)); 0192 QVERIFY(!window->isOnDesktop(2)); 0193 QVERIFY(!window->isOnDesktop(3)); 0194 QCOMPARE(window->desktops().count(), 1u); 0195 // put on desktop 2 0196 window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(2)); 0197 QVERIFY(window->isOnDesktop(1)); 0198 QVERIFY(window->isOnDesktop(2)); 0199 QVERIFY(!window->isOnDesktop(3)); 0200 QCOMPARE(window->desktops().count(), 2u); 0201 // put on desktop 3 0202 window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(3)); 0203 QVERIFY(window->isOnDesktop(1)); 0204 QVERIFY(window->isOnDesktop(2)); 0205 QVERIFY(window->isOnDesktop(3)); 0206 QCOMPARE(window->desktops().count(), 3u); 0207 0208 // entering twice dooes nothing 0209 window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(3)); 0210 QCOMPARE(window->desktops().count(), 3u); 0211 0212 // adding to "all desktops" results in just that one desktop 0213 window->setOnAllDesktops(true); 0214 QCOMPARE(window->desktops().count(), 0u); 0215 window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(3)); 0216 QVERIFY(window->isOnDesktop(3)); 0217 QCOMPARE(window->desktops().count(), 1u); 0218 0219 // leaving a desktop on "all desktops" puts on everything else 0220 window->setOnAllDesktops(true); 0221 QCOMPARE(window->desktops().count(), 0u); 0222 window->leaveDesktop(VirtualDesktopManager::self()->desktopForX11Id(3)); 0223 QVERIFY(window->isOnDesktop(1)); 0224 QVERIFY(window->isOnDesktop(2)); 0225 QCOMPARE(window->desktops().count(), 2u); 0226 } 0227 0228 void VirtualDesktopTest::testRemoveDesktopWithWindow() 0229 { 0230 // first create two new desktops 0231 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0232 VirtualDesktopManager::self()->setCount(3); 0233 QCOMPARE(VirtualDesktopManager::self()->count(), 3u); 0234 0235 // switch to last desktop 0236 VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last()); 0237 QCOMPARE(VirtualDesktopManager::self()->current(), 3u); 0238 0239 // now create a window on this desktop 0240 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0241 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0242 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0243 0244 QVERIFY(window); 0245 QCOMPARE(window->desktop(), 3u); 0246 QSignalSpy desktopPresenceChangedSpy(window, &Window::desktopPresenceChanged); 0247 0248 QCOMPARE(window->desktops().count(), 1u); 0249 QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first()); 0250 0251 // Set the window on desktop 2 as well 0252 window->enterDesktop(VirtualDesktopManager::self()->desktops()[1]); 0253 QCOMPARE(window->desktops().count(), 2u); 0254 QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]); 0255 QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[1]); 0256 QVERIFY(window->isOnDesktop(2)); 0257 QVERIFY(window->isOnDesktop(3)); 0258 0259 // remove desktop 3 0260 VirtualDesktopManager::self()->setCount(2); 0261 QCOMPARE(window->desktops().count(), 1u); 0262 // window is only on desktop 2 0263 QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[0]); 0264 0265 // Again 3 desktops 0266 VirtualDesktopManager::self()->setCount(3); 0267 // move window to be only on desktop 3 0268 window->enterDesktop(VirtualDesktopManager::self()->desktops()[2]); 0269 window->leaveDesktop(VirtualDesktopManager::self()->desktops()[1]); 0270 QCOMPARE(window->desktops().count(), 1u); 0271 // window is only on desktop 3 0272 QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]); 0273 0274 // remove desktop 3 0275 VirtualDesktopManager::self()->setCount(2); 0276 QCOMPARE(window->desktops().count(), 1u); 0277 // window is only on desktop 2 0278 QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[0]); 0279 } 0280 0281 WAYLANDTEST_MAIN(VirtualDesktopTest) 0282 #include "virtual_desktop_test.moc"