KWin
Loading...
Searching...
No Matches
idle_inhibition_test.cpp
Go to the documentation of this file.
1/*
2 KWin - the KDE window manager
3 This file is part of the KDE project.
4
5 SPDX-FileCopyrightText: 2017 Martin Flöser <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "kwin_wayland_test.h"
10
11#include "virtualdesktops.h"
12#include "wayland_server.h"
13#include "window.h"
14#include "workspace.h"
15
16#include <KWayland/Client/surface.h>
17
18using namespace KWin;
19
20static const QString s_socketName = QStringLiteral("wayland_test_kwin_idle_inhbition_test-0");
21
22class TestIdleInhibition : public QObject
23{
24 Q_OBJECT
25private Q_SLOTS:
26 void initTestCase();
27 void init();
28 void cleanup();
29
30 void testInhibit();
31 void testDontInhibitWhenNotOnCurrentDesktop();
32 void testDontInhibitWhenMinimized();
33 void testDontInhibitWhenUnmapped();
34 void testDontInhibitWhenLeftCurrentDesktop();
35};
36
37void TestIdleInhibition::initTestCase()
38{
39 qRegisterMetaType<KWin::Window *>();
40
41 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
42 QVERIFY(waylandServer()->init(s_socketName));
44 QRect(0, 0, 1280, 1024),
45 QRect(1280, 0, 1280, 1024),
46 });
47
48 kwinApp()->start();
49 QVERIFY(applicationStartedSpy.wait());
50}
51
52void TestIdleInhibition::init()
53{
54 QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::IdleInhibitV1));
55}
56
57void TestIdleInhibition::cleanup()
58{
60
61 VirtualDesktopManager::self()->setCount(1);
62 QCOMPARE(VirtualDesktopManager::self()->count(), 1u);
63}
64
65void TestIdleInhibition::testInhibit()
66{
67 // no idle inhibitors at the start
68 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
69
70 // now create window
71 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
72 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
73
74 // now create inhibition on window
75 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get()));
76 QVERIFY(inhibitor);
77
78 // render the window
79 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
80 QVERIFY(window);
81
82 // this should inhibit our server object
83 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
84
85 // deleting the object should uninhibit again
86 inhibitor.reset();
87 Test::flushWaylandConnection(); // don't use QTRY_COMPARE(), it doesn't spin event loop
88 QGuiApplication::processEvents();
89 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
90
91 // inhibit again and destroy window
92 std::unique_ptr<Test::IdleInhibitorV1> inhibitor2(Test::createIdleInhibitorV1(surface.get()));
94 QGuiApplication::processEvents();
95 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
96
97 shellSurface.reset();
98 QVERIFY(Test::waitForWindowClosed(window));
99 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
100}
101
102void TestIdleInhibition::testDontInhibitWhenNotOnCurrentDesktop()
103{
104 // This test verifies that the idle inhibitor object is not honored when
105 // the associated surface is not on the current virtual desktop.
106
107 VirtualDesktopManager::self()->setCount(2);
108 QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
109
110 // Create the test window.
111 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
112 QVERIFY(surface != nullptr);
113 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
114 QVERIFY(shellSurface != nullptr);
115
116 // Create the inhibitor object.
117 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get()));
118 QVERIFY(inhibitor);
119
120 // Render the window.
121 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
122 QVERIFY(window);
123
124 // The test window should be only on the first virtual desktop.
125 QCOMPARE(window->desktops().count(), 1);
126 QCOMPARE(window->desktops().first(), VirtualDesktopManager::self()->desktops().first());
127
128 // This should inhibit our server object.
129 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
130
131 // Switch to the second virtual desktop.
132 VirtualDesktopManager::self()->setCurrent(2);
133
134 // The surface is no longer visible, so the compositor don't have to honor the
135 // idle inhibitor object.
136 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
137
138 // Switch back to the first virtual desktop.
139 VirtualDesktopManager::self()->setCurrent(1);
140
141 // The test window became visible again, so the compositor has to honor the idle
142 // inhibitor object back again.
143 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
144
145 // Destroy the test window.
146 shellSurface.reset();
147 QVERIFY(Test::waitForWindowClosed(window));
148 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
149}
150
151void TestIdleInhibition::testDontInhibitWhenMinimized()
152{
153 // This test verifies that the idle inhibitor object is not honored when the
154 // associated surface is minimized.
155
156 // Create the test window.
157 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
158 QVERIFY(surface != nullptr);
159 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
160 QVERIFY(shellSurface != nullptr);
161
162 // Create the inhibitor object.
163 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get()));
164 QVERIFY(inhibitor);
165
166 // Render the window.
167 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
168 QVERIFY(window);
169
170 // This should inhibit our server object.
171 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
172
173 // Minimize the window, the idle inhibitor object should not be honored.
174 window->setMinimized(true);
175 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
176
177 // Unminimize the window, the idle inhibitor object should be honored back again.
178 window->setMinimized(false);
179 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
180
181 // Destroy the test window.
182 shellSurface.reset();
183 QVERIFY(Test::waitForWindowClosed(window));
184 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
185}
186
187void TestIdleInhibition::testDontInhibitWhenUnmapped()
188{
189 // This test verifies that the idle inhibitor object is not honored by KWin
190 // when the associated window is unmapped.
191
192 // Create the test window.
193 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
194 QVERIFY(surface != nullptr);
195 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
196 QVERIFY(shellSurface != nullptr);
197 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
198
199 // Create the inhibitor object.
200 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get()));
201 QVERIFY(inhibitor);
202
203 // Map the window.
204 QSignalSpy windowAddedSpy(workspace(), &Workspace::windowAdded);
205 Test::render(surface.get(), QSize(100, 50), Qt::blue);
206 QVERIFY(windowAddedSpy.isEmpty());
207 QVERIFY(windowAddedSpy.wait());
208 QCOMPARE(windowAddedSpy.count(), 1);
209 Window *window = windowAddedSpy.last().first().value<Window *>();
210 QVERIFY(window);
211 QCOMPARE(window->readyForPainting(), true);
212
213 // The compositor will respond with a configure event when the surface becomes active.
214 QVERIFY(surfaceConfigureRequestedSpy.wait());
215 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
216
217 // This should inhibit our server object.
218 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
219
220 // Unmap the window.
221 surface->attachBuffer(KWayland::Client::Buffer::Ptr());
222 surface->commit(KWayland::Client::Surface::CommitFlag::None);
223 QVERIFY(Test::waitForWindowClosed(window));
224
225 // The surface is no longer visible, so the compositor doesn't have to honor the
226 // idle inhibitor object.
227 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
228
229 // Tell the compositor that we want to map the surface.
230 surface->commit(KWayland::Client::Surface::CommitFlag::None);
231
232 // The compositor will respond with a configure event.
233 QVERIFY(surfaceConfigureRequestedSpy.wait());
234 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
235
236 // Map the window.
237 Test::render(surface.get(), QSize(100, 50), Qt::blue);
238 QVERIFY(windowAddedSpy.wait());
239 QCOMPARE(windowAddedSpy.count(), 2);
240 window = windowAddedSpy.last().first().value<Window *>();
241 QVERIFY(window);
242 QCOMPARE(window->readyForPainting(), true);
243
244 // The test window became visible again, so the compositor has to honor the idle
245 // inhibitor object back again.
246 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
247
248 // Destroy the test window.
249 shellSurface.reset();
250 QVERIFY(Test::waitForWindowClosed(window));
251 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
252}
253
254void TestIdleInhibition::testDontInhibitWhenLeftCurrentDesktop()
255{
256 // This test verifies that the idle inhibitor object is not honored by KWin
257 // when the associated surface leaves the current virtual desktop.
258
259 VirtualDesktopManager::self()->setCount(2);
260 QCOMPARE(VirtualDesktopManager::self()->count(), 2u);
261
262 // Create the test window.
263 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
264 QVERIFY(surface != nullptr);
265 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
266 QVERIFY(shellSurface != nullptr);
267
268 // Create the inhibitor object.
269 std::unique_ptr<Test::IdleInhibitorV1> inhibitor(Test::createIdleInhibitorV1(surface.get()));
270 QVERIFY(inhibitor);
271
272 // Render the window.
273 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
274 QVERIFY(window);
275
276 // The test window should be only on the first virtual desktop.
277 QCOMPARE(window->desktops().count(), 1);
278 QCOMPARE(window->desktops().first(), VirtualDesktopManager::self()->desktops().first());
279
280 // This should inhibit our server object.
281 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
282
283 // Let the window enter the second virtual desktop.
284 window->enterDesktop(VirtualDesktopManager::self()->desktops().at(1));
285 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
286
287 // If the window leaves the first virtual desktop, then the associated idle
288 // inhibitor object should not be honored.
289 window->leaveDesktop(VirtualDesktopManager::self()->desktops().at(0));
290 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
291
292 // If the window enters the first desktop, then the associated idle inhibitor
293 // object should be honored back again.
294 window->enterDesktop(VirtualDesktopManager::self()->desktops().at(0));
295 QCOMPARE(input()->idleInhibitors(), QList<Window *>{window});
296
297 // Destroy the test window.
298 shellSurface.reset();
299 QVERIFY(Test::waitForWindowClosed(window));
300 QCOMPARE(input()->idleInhibitors(), QList<Window *>{});
301}
302
304#include "idle_inhibition_test.moc"
void configureRequested(quint32 serial)
void windowAdded(KWin::Window *)
#define WAYLANDTEST_MAIN(TestObject)
Window * renderAndWaitForShown(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32, int timeout=5000)
void destroyWaylandConnection()
void setOutputConfig(const QList< QRect > &geometries)
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32_Premultiplied)
std::unique_ptr< KWayland::Client::Surface > createSurface()
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
IdleInhibitorV1 * createIdleInhibitorV1(KWayland::Client::Surface *surface)
void flushWaylandConnection()
bool waitForWindowClosed(Window *window)
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
InputRedirection * input()
Definition input.h:549