File indexing completed on 2024-11-10 04:56:09
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 "main.h" 0012 #include "utils/xcbutils.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 Test::setOutputConfig({ 0044 QRect(0, 0, 1280, 1024), 0045 QRect(1280, 0, 1280, 1024), 0046 }); 0047 0048 kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig)); 0049 qputenv("KWIN_XKB_DEFAULT_KEYMAP", "1"); 0050 qputenv("XKB_DEFAULT_RULES", "evdev"); 0051 0052 kwinApp()->start(); 0053 QVERIFY(applicationStartedSpy.wait()); 0054 0055 if (kwinApp()->x11Connection()) { 0056 // verify the current desktop x11 property on startup, see BUG: 391034 0057 Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP"); 0058 QVERIFY(currentDesktopAtom.isValid()); 0059 Xcb::Property currentDesktop(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0060 bool ok = true; 0061 QCOMPARE(currentDesktop.value(0, &ok), 0); 0062 QVERIFY(ok); 0063 } 0064 } 0065 0066 void VirtualDesktopTest::init() 0067 { 0068 QVERIFY(Test::setupWaylandConnection()); 0069 workspace()->setActiveOutput(QPoint(640, 512)); 0070 VirtualDesktopManager::self()->setCount(1); 0071 } 0072 0073 void VirtualDesktopTest::cleanup() 0074 { 0075 Test::destroyWaylandConnection(); 0076 } 0077 0078 void VirtualDesktopTest::testNetCurrentDesktop() 0079 { 0080 if (!kwinApp()->x11Connection()) { 0081 QSKIP("Skipped on Wayland only"); 0082 } 0083 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0084 VirtualDesktopManager::self()->setCount(4); 0085 QCOMPARE(VirtualDesktopManager::self()->count(), 4u); 0086 0087 Xcb::Atom currentDesktopAtom("_NET_CURRENT_DESKTOP"); 0088 QVERIFY(currentDesktopAtom.isValid()); 0089 Xcb::Property currentDesktop(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0090 bool ok = true; 0091 QCOMPARE(currentDesktop.value(0, &ok), 0); 0092 QVERIFY(ok); 0093 0094 // go to desktop 2 0095 VirtualDesktopManager::self()->setCurrent(2); 0096 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0097 QCOMPARE(currentDesktop.value(0, &ok), 1); 0098 QVERIFY(ok); 0099 0100 // go to desktop 3 0101 VirtualDesktopManager::self()->setCurrent(3); 0102 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0103 QCOMPARE(currentDesktop.value(0, &ok), 2); 0104 QVERIFY(ok); 0105 0106 // go to desktop 4 0107 VirtualDesktopManager::self()->setCurrent(4); 0108 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0109 QCOMPARE(currentDesktop.value(0, &ok), 3); 0110 QVERIFY(ok); 0111 0112 // and back to first 0113 VirtualDesktopManager::self()->setCurrent(1); 0114 currentDesktop = Xcb::Property(0, kwinApp()->x11RootWindow(), currentDesktopAtom, XCB_ATOM_CARDINAL, 0, 1); 0115 QCOMPARE(currentDesktop.value(0, &ok), 0); 0116 QVERIFY(ok); 0117 } 0118 0119 void VirtualDesktopTest::testLastDesktopRemoved() 0120 { 0121 // first create a new desktop 0122 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0123 VirtualDesktopManager::self()->setCount(2); 0124 QCOMPARE(VirtualDesktopManager::self()->count(), 2u); 0125 0126 // switch to last desktop 0127 VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last()); 0128 QCOMPARE(VirtualDesktopManager::self()->current(), 2u); 0129 0130 // now create a window on this desktop 0131 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0132 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0133 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0134 0135 QVERIFY(window); 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 QCOMPARE(window->desktops().count(), 1u); 0144 QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first()); 0145 } 0146 0147 void VirtualDesktopTest::testWindowOnMultipleDesktops() 0148 { 0149 // first create two new desktops 0150 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0151 VirtualDesktopManager::self()->setCount(3); 0152 QCOMPARE(VirtualDesktopManager::self()->count(), 3u); 0153 0154 // switch to last desktop 0155 const auto desktops = VirtualDesktopManager::self()->desktops(); 0156 VirtualDesktopManager::self()->setCurrent(desktops.at(2)); 0157 0158 // now create a window on this desktop 0159 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0160 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0161 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0162 QVERIFY(window); 0163 QCOMPARE(window->desktops(), (QList<VirtualDesktop *>{desktops.at(2)})); 0164 0165 // Set the window on desktop 2 as well 0166 window->enterDesktop(VirtualDesktopManager::self()->desktopForX11Id(2)); 0167 QCOMPARE(window->desktops().count(), 2u); 0168 QCOMPARE(window->desktops()[0], desktops.at(2)); 0169 QCOMPARE(window->desktops()[1], desktops.at(1)); 0170 0171 // leave desktop 3 0172 window->leaveDesktop(desktops.at(2)); 0173 QCOMPARE(window->desktops(), (QList<VirtualDesktop *>{desktops.at(1)})); 0174 // leave desktop 2 0175 window->leaveDesktop(desktops.at(1)); 0176 QCOMPARE(window->desktops(), QList<VirtualDesktop *>{}); 0177 // we should be on all desktops now 0178 QVERIFY(window->isOnAllDesktops()); 0179 // put on desktop 1 0180 window->enterDesktop(desktops.at(0)); 0181 QVERIFY(window->isOnDesktop(desktops.at(0))); 0182 QVERIFY(!window->isOnDesktop(desktops.at(1))); 0183 QVERIFY(!window->isOnDesktop(desktops.at(2))); 0184 QCOMPARE(window->desktops().count(), 1u); 0185 // put on desktop 2 0186 window->enterDesktop(desktops.at(1)); 0187 QVERIFY(window->isOnDesktop(desktops.at(0))); 0188 QVERIFY(window->isOnDesktop(desktops.at(1))); 0189 QVERIFY(!window->isOnDesktop(desktops.at(2))); 0190 QCOMPARE(window->desktops().count(), 2u); 0191 // put on desktop 3 0192 window->enterDesktop(desktops.at(2)); 0193 QVERIFY(window->isOnDesktop(desktops.at(0))); 0194 QVERIFY(window->isOnDesktop(desktops.at(1))); 0195 QVERIFY(window->isOnDesktop(desktops.at(2))); 0196 QCOMPARE(window->desktops().count(), 3u); 0197 0198 // entering twice dooes nothing 0199 window->enterDesktop(desktops.at(2)); 0200 QCOMPARE(window->desktops().count(), 3u); 0201 0202 // adding to "all desktops" results in just that one desktop 0203 window->setOnAllDesktops(true); 0204 QCOMPARE(window->desktops().count(), 0u); 0205 window->enterDesktop(desktops.at(2)); 0206 QVERIFY(window->isOnDesktop(desktops.at(2))); 0207 QCOMPARE(window->desktops().count(), 1u); 0208 0209 // leaving a desktop on "all desktops" puts on everything else 0210 window->setOnAllDesktops(true); 0211 QCOMPARE(window->desktops().count(), 0u); 0212 window->leaveDesktop(desktops.at(2)); 0213 QVERIFY(window->isOnDesktop(desktops.at(0))); 0214 QVERIFY(window->isOnDesktop(desktops.at(1))); 0215 QCOMPARE(window->desktops().count(), 2u); 0216 } 0217 0218 void VirtualDesktopTest::testRemoveDesktopWithWindow() 0219 { 0220 // first create two new desktops 0221 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0222 VirtualDesktopManager::self()->setCount(3); 0223 QCOMPARE(VirtualDesktopManager::self()->count(), 3u); 0224 0225 // switch to last desktop 0226 VirtualDesktopManager::self()->setCurrent(VirtualDesktopManager::self()->desktops().last()); 0227 QCOMPARE(VirtualDesktopManager::self()->current(), 3u); 0228 0229 // now create a window on this desktop 0230 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0231 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0232 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0233 0234 QVERIFY(window); 0235 0236 QCOMPARE(window->desktops().count(), 1u); 0237 QCOMPARE(VirtualDesktopManager::self()->currentDesktop(), window->desktops().first()); 0238 0239 // Set the window on desktop 2 as well 0240 window->enterDesktop(VirtualDesktopManager::self()->desktops()[1]); 0241 QCOMPARE(window->desktops().count(), 2u); 0242 QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]); 0243 QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[1]); 0244 0245 // remove desktop 3 0246 VirtualDesktopManager::self()->setCount(2); 0247 QCOMPARE(window->desktops().count(), 1u); 0248 // window is only on desktop 2 0249 QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[0]); 0250 0251 // Again 3 desktops 0252 VirtualDesktopManager::self()->setCount(3); 0253 // move window to be only on desktop 3 0254 window->enterDesktop(VirtualDesktopManager::self()->desktops()[2]); 0255 window->leaveDesktop(VirtualDesktopManager::self()->desktops()[1]); 0256 QCOMPARE(window->desktops().count(), 1u); 0257 // window is only on desktop 3 0258 QCOMPARE(VirtualDesktopManager::self()->desktops()[2], window->desktops()[0]); 0259 0260 // remove desktop 3 0261 VirtualDesktopManager::self()->setCount(2); 0262 QCOMPARE(window->desktops().count(), 1u); 0263 // window is only on desktop 2 0264 QCOMPARE(VirtualDesktopManager::self()->desktops()[1], window->desktops()[0]); 0265 } 0266 0267 WAYLANDTEST_MAIN(VirtualDesktopTest) 0268 #include "virtual_desktop_test.moc"