File indexing completed on 2024-11-10 04:55:58
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 "virtualdesktops.h" 0012 #include "wayland_server.h" 0013 #include "window.h" 0014 #include "workspace.h" 0015 0016 #include <KWayland/Client/surface.h> 0017 0018 using namespace KWin; 0019 0020 static const QString s_socketName = QStringLiteral("wayland_test_kwin_idle_inhbition_test-0"); 0021 0022 class TestIdleInhibition : public QObject 0023 { 0024 Q_OBJECT 0025 private Q_SLOTS: 0026 void initTestCase(); 0027 void init(); 0028 void cleanup(); 0029 0030 void testInhibit(); 0031 void testDontInhibitWhenNotOnCurrentDesktop(); 0032 void testDontInhibitWhenMinimized(); 0033 void testDontInhibitWhenUnmapped(); 0034 void testDontInhibitWhenLeftCurrentDesktop(); 0035 }; 0036 0037 void TestIdleInhibition::initTestCase() 0038 { 0039 qRegisterMetaType<KWin::Window *>(); 0040 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()->start(); 0049 QVERIFY(applicationStartedSpy.wait()); 0050 } 0051 0052 void TestIdleInhibition::init() 0053 { 0054 QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::IdleInhibitV1)); 0055 } 0056 0057 void TestIdleInhibition::cleanup() 0058 { 0059 Test::destroyWaylandConnection(); 0060 0061 VirtualDesktopManager::self()->setCount(1); 0062 QCOMPARE(VirtualDesktopManager::self()->count(), 1u); 0063 } 0064 0065 void TestIdleInhibition::testInhibit() 0066 { 0067 // no idle inhibitors at the start 0068 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0069 0070 // now create window 0071 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0072 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0073 0074 // now create inhibition on window 0075 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get())); 0076 QVERIFY(inhibitor); 0077 0078 // render the window 0079 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0080 QVERIFY(window); 0081 0082 // this should inhibit our server object 0083 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0084 0085 // deleting the object should uninhibit again 0086 inhibitor.reset(); 0087 Test::flushWaylandConnection(); // don't use QTRY_COMPARE(), it doesn't spin event loop 0088 QGuiApplication::processEvents(); 0089 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0090 0091 // inhibit again and destroy window 0092 std::unique_ptr<Test::IdleInhibitorV1> inhibitor2(Test::createIdleInhibitorV1(surface.get())); 0093 Test::flushWaylandConnection(); 0094 QGuiApplication::processEvents(); 0095 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0096 0097 shellSurface.reset(); 0098 QVERIFY(Test::waitForWindowClosed(window)); 0099 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0100 } 0101 0102 void TestIdleInhibition::testDontInhibitWhenNotOnCurrentDesktop() 0103 { 0104 // This test verifies that the idle inhibitor object is not honored when 0105 // the associated surface is not on the current virtual desktop. 0106 0107 VirtualDesktopManager::self()->setCount(2); 0108 QCOMPARE(VirtualDesktopManager::self()->count(), 2u); 0109 0110 // Create the test window. 0111 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0112 QVERIFY(surface != nullptr); 0113 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0114 QVERIFY(shellSurface != nullptr); 0115 0116 // Create the inhibitor object. 0117 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get())); 0118 QVERIFY(inhibitor); 0119 0120 // Render the window. 0121 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0122 QVERIFY(window); 0123 0124 // The test window should be only on the first virtual desktop. 0125 QCOMPARE(window->desktops().count(), 1); 0126 QCOMPARE(window->desktops().first(), VirtualDesktopManager::self()->desktops().first()); 0127 0128 // This should inhibit our server object. 0129 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0130 0131 // Switch to the second virtual desktop. 0132 VirtualDesktopManager::self()->setCurrent(2); 0133 0134 // The surface is no longer visible, so the compositor don't have to honor the 0135 // idle inhibitor object. 0136 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0137 0138 // Switch back to the first virtual desktop. 0139 VirtualDesktopManager::self()->setCurrent(1); 0140 0141 // The test window became visible again, so the compositor has to honor the idle 0142 // inhibitor object back again. 0143 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0144 0145 // Destroy the test window. 0146 shellSurface.reset(); 0147 QVERIFY(Test::waitForWindowClosed(window)); 0148 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0149 } 0150 0151 void TestIdleInhibition::testDontInhibitWhenMinimized() 0152 { 0153 // This test verifies that the idle inhibitor object is not honored when the 0154 // associated surface is minimized. 0155 0156 // Create the test window. 0157 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0158 QVERIFY(surface != nullptr); 0159 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0160 QVERIFY(shellSurface != nullptr); 0161 0162 // Create the inhibitor object. 0163 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get())); 0164 QVERIFY(inhibitor); 0165 0166 // Render the window. 0167 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0168 QVERIFY(window); 0169 0170 // This should inhibit our server object. 0171 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0172 0173 // Minimize the window, the idle inhibitor object should not be honored. 0174 window->setMinimized(true); 0175 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0176 0177 // Unminimize the window, the idle inhibitor object should be honored back again. 0178 window->setMinimized(false); 0179 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0180 0181 // Destroy the test window. 0182 shellSurface.reset(); 0183 QVERIFY(Test::waitForWindowClosed(window)); 0184 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0185 } 0186 0187 void TestIdleInhibition::testDontInhibitWhenUnmapped() 0188 { 0189 // This test verifies that the idle inhibitor object is not honored by KWin 0190 // when the associated window is unmapped. 0191 0192 // Create the test window. 0193 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0194 QVERIFY(surface != nullptr); 0195 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0196 QVERIFY(shellSurface != nullptr); 0197 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested); 0198 0199 // Create the inhibitor object. 0200 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get())); 0201 QVERIFY(inhibitor); 0202 0203 // Map the window. 0204 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded); 0205 Test::render(surface.get(), QSize(100, 50), Qt::blue); 0206 QVERIFY(windowAddedSpy.isEmpty()); 0207 QVERIFY(windowAddedSpy.wait()); 0208 QCOMPARE(windowAddedSpy.count(), 1); 0209 Window *window = windowAddedSpy.last().first().value<Window *>(); 0210 QVERIFY(window); 0211 QCOMPARE(window->readyForPainting(), true); 0212 0213 // The compositor will respond with a configure event when the surface becomes active. 0214 QVERIFY(surfaceConfigureRequestedSpy.wait()); 0215 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1); 0216 0217 // This should inhibit our server object. 0218 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0219 0220 // Unmap the window. 0221 surface->attachBuffer(KWayland::Client::Buffer::Ptr()); 0222 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0223 QVERIFY(Test::waitForWindowClosed(window)); 0224 0225 // The surface is no longer visible, so the compositor doesn't have to honor the 0226 // idle inhibitor object. 0227 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0228 0229 // Tell the compositor that we want to map the surface. 0230 surface->commit(KWayland::Client::Surface::CommitFlag::None); 0231 0232 // The compositor will respond with a configure event. 0233 QVERIFY(surfaceConfigureRequestedSpy.wait()); 0234 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2); 0235 0236 // Map the window. 0237 Test::render(surface.get(), QSize(100, 50), Qt::blue); 0238 QVERIFY(windowAddedSpy.wait()); 0239 QCOMPARE(windowAddedSpy.count(), 2); 0240 window = windowAddedSpy.last().first().value<Window *>(); 0241 QVERIFY(window); 0242 QCOMPARE(window->readyForPainting(), true); 0243 0244 // The test window became visible again, so the compositor has to honor the idle 0245 // inhibitor object back again. 0246 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0247 0248 // Destroy the test window. 0249 shellSurface.reset(); 0250 QVERIFY(Test::waitForWindowClosed(window)); 0251 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0252 } 0253 0254 void TestIdleInhibition::testDontInhibitWhenLeftCurrentDesktop() 0255 { 0256 // This test verifies that the idle inhibitor object is not honored by KWin 0257 // when the associated surface leaves the current virtual desktop. 0258 0259 VirtualDesktopManager::self()->setCount(2); 0260 QCOMPARE(VirtualDesktopManager::self()->count(), 2u); 0261 0262 // Create the test window. 0263 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0264 QVERIFY(surface != nullptr); 0265 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0266 QVERIFY(shellSurface != nullptr); 0267 0268 // Create the inhibitor object. 0269 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get())); 0270 QVERIFY(inhibitor); 0271 0272 // Render the window. 0273 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0274 QVERIFY(window); 0275 0276 // The test window should be only on the first virtual desktop. 0277 QCOMPARE(window->desktops().count(), 1); 0278 QCOMPARE(window->desktops().first(), VirtualDesktopManager::self()->desktops().first()); 0279 0280 // This should inhibit our server object. 0281 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0282 0283 // Let the window enter the second virtual desktop. 0284 window->enterDesktop(VirtualDesktopManager::self()->desktops().at(1)); 0285 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0286 0287 // If the window leaves the first virtual desktop, then the associated idle 0288 // inhibitor object should not be honored. 0289 window->leaveDesktop(VirtualDesktopManager::self()->desktops().at(0)); 0290 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0291 0292 // If the window enters the first desktop, then the associated idle inhibitor 0293 // object should be honored back again. 0294 window->enterDesktop(VirtualDesktopManager::self()->desktops().at(0)); 0295 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window}); 0296 0297 // Destroy the test window. 0298 shellSurface.reset(); 0299 QVERIFY(Test::waitForWindowClosed(window)); 0300 QCOMPARE(input()->idleInhibitors(), QList<Window *>{}); 0301 } 0302 0303 WAYLANDTEST_MAIN(TestIdleInhibition) 0304 #include "idle_inhibition_test.moc"