KWin
Loading...
Searching...
No Matches
quick_tiling_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: 2015 Martin Gräßlin <mgraesslin@kde.org>
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8*/
9#include "kwin_wayland_test.h"
10
11#include "core/output.h"
12#include "cursor.h"
15#include "pointer_input.h"
16#include "scripting/scripting.h"
17#include "utils/common.h"
18#include "wayland_server.h"
19#include "window.h"
20#include "workspace.h"
21#include "x11window.h"
22
23#include <KDecoration2/DecoratedClient>
24#include <KDecoration2/Decoration>
25#include <KDecoration2/DecorationSettings>
26
27#include <KWayland/Client/compositor.h>
28#include <KWayland/Client/connection_thread.h>
29#include <KWayland/Client/surface.h>
30
31#include <QDBusConnection>
32#include <QDBusMessage>
33#include <QDBusPendingCall>
34#include <QTemporaryFile>
35#include <QTextStream>
36
37#include <netwm.h>
38#include <xcb/xcb_icccm.h>
39
40#include <linux/input.h>
41
42Q_DECLARE_METATYPE(KWin::QuickTileMode)
44
45namespace KWin
46{
47
48static const QString s_socketName = QStringLiteral("wayland_test_kwin_quick_tiling-0");
49
50class QuickTilingTest : public QObject
51{
52 Q_OBJECT
53private Q_SLOTS:
54 void initTestCase();
55 void init();
56 void cleanup();
57 void testQuickTiling_data();
58 void testQuickTiling();
59 void testQuickMaximizing_data();
60 void testQuickMaximizing();
61 void testQuickTilingKeyboardMove_data();
62 void testQuickTilingKeyboardMove();
63 void testQuickTilingPointerMove_data();
64 void testQuickTilingPointerMove();
65 void testQuickTilingTouchMove_data();
66 void testQuickTilingTouchMove();
67 void testX11QuickTiling_data();
68 void testX11QuickTiling();
69 void testX11QuickTilingAfterVertMaximize_data();
70 void testX11QuickTilingAfterVertMaximize();
71 void testShortcut_data();
72 void testShortcut();
73 void testScript_data();
74 void testScript();
75
76private:
77 KWayland::Client::ConnectionThread *m_connection = nullptr;
78 KWayland::Client::Compositor *m_compositor = nullptr;
79};
80
81void QuickTilingTest::initTestCase()
82{
83 qRegisterMetaType<KWin::Window *>();
84 qRegisterMetaType<KWin::MaximizeMode>("MaximizeMode");
85 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
86 QVERIFY(waylandServer()->init(s_socketName));
88 QRect(0, 0, 1280, 1024),
89 QRect(1280, 0, 1280, 1024),
90 });
91
92 // set custom config which disables the Outline
93 KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
94 KConfigGroup group = config->group(QStringLiteral("Outline"));
95 group.writeEntry(QStringLiteral("QmlPath"), QString("/does/not/exist.qml"));
96 group.sync();
97
98 kwinApp()->setConfig(config);
99
100 qputenv("XKB_DEFAULT_RULES", "evdev");
101
102 kwinApp()->start();
103 QVERIFY(applicationStartedSpy.wait());
104
105 const auto outputs = workspace()->outputs();
106 QCOMPARE(outputs.count(), 2);
107 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
108 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
109}
110
111void QuickTilingTest::init()
112{
114 m_connection = Test::waylandConnection();
115 m_compositor = Test::waylandCompositor();
116
117 workspace()->setActiveOutput(QPoint(640, 512));
118 input()->pointer()->warp(QPoint(640, 512));
119}
120
121void QuickTilingTest::cleanup()
122{
124}
125
126void QuickTilingTest::testQuickTiling_data()
127{
128 QTest::addColumn<QuickTileMode>("mode");
129 QTest::addColumn<QRectF>("expectedGeometry");
130 QTest::addColumn<QRectF>("secondScreen");
131 QTest::addColumn<QuickTileMode>("expectedModeAfterToggle");
132
133#define FLAG(name) QuickTileMode(QuickTileFlag::name)
134
135 QTest::newRow("left") << FLAG(Left) << QRectF(0, 0, 640, 1024) << QRectF(1280, 0, 640, 1024) << FLAG(Right);
136 QTest::newRow("top") << FLAG(Top) << QRectF(0, 0, 1280, 512) << QRectF(1280, 0, 1280, 512) << QuickTileMode();
137 QTest::newRow("right") << FLAG(Right) << QRectF(640, 0, 640, 1024) << QRectF(1920, 0, 640, 1024) << QuickTileMode();
138 QTest::newRow("bottom") << FLAG(Bottom) << QRectF(0, 512, 1280, 512) << QRectF(1280, 512, 1280, 512) << QuickTileMode();
139
140 QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRectF(0, 0, 640, 512) << QRectF(1280, 0, 640, 512) << (FLAG(Right) | FLAG(Top));
141 QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRectF(640, 0, 640, 512) << QRectF(1920, 0, 640, 512) << QuickTileMode();
142 QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRectF(0, 512, 640, 512) << QRectF(1280, 512, 640, 512) << (FLAG(Right) | FLAG(Bottom));
143 QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRectF(640, 512, 640, 512) << QRectF(1920, 512, 640, 512) << QuickTileMode();
144
145 QTest::newRow("maximize") << FLAG(Maximize) << QRectF(0, 0, 1280, 1024) << QRectF(1280, 0, 1280, 1024) << QuickTileMode();
146
147#undef FLAG
148}
149
150void QuickTilingTest::testQuickTiling()
151{
152 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
153 QVERIFY(surface != nullptr);
154 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
155 QVERIFY(shellSurface != nullptr);
156
157 // Map the window.
158 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
159 QVERIFY(window);
160 QCOMPARE(workspace()->activeWindow(), window);
161 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
162 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
163
164 // We have to receive a configure event when the window becomes active.
165 QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
166 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
167 QVERIFY(surfaceConfigureRequestedSpy.wait());
168 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
169
170 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
171 QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
172
173 QFETCH(QuickTileMode, mode);
174 QFETCH(QRectF, expectedGeometry);
175 window->setQuickTileMode(mode, true);
176 QCOMPARE(quickTileChangedSpy.count(), 1);
177 // at this point the geometry did not yet change
178 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
179 // but quick tile mode already changed
180 QCOMPARE(window->quickTileMode(), mode);
181
182 // but we got requested a new geometry
183 QVERIFY(surfaceConfigureRequestedSpy.wait());
184 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
185 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), expectedGeometry.size());
186
187 // attach a new image
188 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
189 Test::render(surface.get(), expectedGeometry.size().toSize(), Qt::red);
190
191 QVERIFY(frameGeometryChangedSpy.wait());
192 QCOMPARE(frameGeometryChangedSpy.count(), 1);
193 QCOMPARE(window->frameGeometry(), expectedGeometry);
194
195 // send window to other screen
196 QList<Output *> outputs = workspace()->outputs();
197 QCOMPARE(window->output(), outputs[0]);
198 window->sendToOutput(outputs[1]);
199 QCOMPARE(window->output(), outputs[1]);
200 // quick tile should not be changed
201 QCOMPARE(window->quickTileMode(), mode);
202 QTEST(window->frameGeometry(), "secondScreen");
203
204 // now try to toggle again
205 window->setQuickTileMode(mode, true);
206 QTEST(window->quickTileMode(), "expectedModeAfterToggle");
207}
208
209void QuickTilingTest::testQuickMaximizing_data()
210{
211 QTest::addColumn<QuickTileMode>("mode");
212
213#define FLAG(name) QuickTileMode(QuickTileFlag::name)
214
215 QTest::newRow("maximize") << FLAG(Maximize);
216 QTest::newRow("none") << FLAG(None);
217
218#undef FLAG
219}
220
221void QuickTilingTest::testQuickMaximizing()
222{
223 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
224 QVERIFY(surface != nullptr);
225 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
226 QVERIFY(shellSurface != nullptr);
227
228 // Map the window.
229 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
230 QVERIFY(window);
231 QCOMPARE(workspace()->activeWindow(), window);
232 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
233 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
234 QCOMPARE(window->maximizeMode(), MaximizeRestore);
235
236 // We have to receive a configure event upon becoming active.
237 QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
238 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
239 QVERIFY(surfaceConfigureRequestedSpy.wait());
240 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
241
242 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
243 QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
244 QSignalSpy maximizeChangedSpy(window, &Window::maximizedChanged);
245
246 window->setQuickTileMode(QuickTileFlag::Maximize, true);
247 QCOMPARE(quickTileChangedSpy.count(), 1);
248
249 // at this point the geometry did not yet change
250 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
251 // but quick tile mode already changed
252 QCOMPARE(window->quickTileMode(), QuickTileFlag::Maximize);
253 QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
254
255 // but we got requested a new geometry
256 QVERIFY(surfaceConfigureRequestedSpy.wait());
257 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
258 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), QSize(1280, 1024));
259
260 // attach a new image
261 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
262 Test::render(surface.get(), QSize(1280, 1024), Qt::red);
263
264 QVERIFY(frameGeometryChangedSpy.wait());
265 QCOMPARE(frameGeometryChangedSpy.count(), 1);
266 QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
267 QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
268
269 // window is now set to maximised
270 QCOMPARE(maximizeChangedSpy.count(), 1);
271 QCOMPARE(window->maximizeMode(), MaximizeFull);
272 QCOMPARE(window->tile(), nullptr);
273
274 // go back to quick tile none
275 QFETCH(QuickTileMode, mode);
276 window->setQuickTileMode(mode, true);
277 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
278 QCOMPARE(quickTileChangedSpy.count(), 2);
279 // geometry not yet changed
280 QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
281 QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
282 // we got requested a new geometry
283 QVERIFY(surfaceConfigureRequestedSpy.wait());
284 QCOMPARE(surfaceConfigureRequestedSpy.count(), 3);
285 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), QSize(100, 50));
286
287 // render again
288 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
289 Test::render(surface.get(), QSize(100, 50), Qt::yellow);
290
291 QVERIFY(frameGeometryChangedSpy.wait());
292 QCOMPARE(frameGeometryChangedSpy.count(), 2);
293 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
294 QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
295 QCOMPARE(maximizeChangedSpy.count(), 2);
296}
297
298void QuickTilingTest::testQuickTilingKeyboardMove_data()
299{
300 QTest::addColumn<QPoint>("targetPos");
301 QTest::addColumn<QuickTileMode>("expectedMode");
302
303 QTest::newRow("topRight") << QPoint(2559, 24) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Right);
304 QTest::newRow("right") << QPoint(2559, 512) << QuickTileMode(QuickTileFlag::Right);
305 QTest::newRow("bottomRight") << QPoint(2559, 1023) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Right);
306 QTest::newRow("bottomLeft") << QPoint(0, 1023) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Left);
307 QTest::newRow("Left") << QPoint(0, 512) << QuickTileMode(QuickTileFlag::Left);
308 QTest::newRow("topLeft") << QPoint(0, 24) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Left);
309}
310
311void QuickTilingTest::testQuickTilingKeyboardMove()
312{
313 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
314 QVERIFY(surface != nullptr);
315
316 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
317 QVERIFY(shellSurface != nullptr);
318 // let's render
319 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
320
321 QVERIFY(window);
322 QCOMPARE(workspace()->activeWindow(), window);
323 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
324 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
325 QCOMPARE(window->maximizeMode(), MaximizeRestore);
326
327 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
328
330 QCOMPARE(window, workspace()->moveResizeWindow());
331 QCOMPARE(Cursors::self()->mouse()->pos(), QPoint(50, 25));
332
333 QFETCH(QPoint, targetPos);
334 quint32 timestamp = 1;
335 Test::keyboardKeyPressed(KEY_LEFTCTRL, timestamp++);
336 while (Cursors::self()->mouse()->pos().x() > targetPos.x()) {
337 Test::keyboardKeyPressed(KEY_LEFT, timestamp++);
338 Test::keyboardKeyReleased(KEY_LEFT, timestamp++);
339 }
340 while (Cursors::self()->mouse()->pos().x() < targetPos.x()) {
341 Test::keyboardKeyPressed(KEY_RIGHT, timestamp++);
342 Test::keyboardKeyReleased(KEY_RIGHT, timestamp++);
343 }
344 while (Cursors::self()->mouse()->pos().y() < targetPos.y()) {
345 Test::keyboardKeyPressed(KEY_DOWN, timestamp++);
346 Test::keyboardKeyReleased(KEY_DOWN, timestamp++);
347 }
348 while (Cursors::self()->mouse()->pos().y() > targetPos.y()) {
349 Test::keyboardKeyPressed(KEY_UP, timestamp++);
350 Test::keyboardKeyReleased(KEY_UP, timestamp++);
351 }
352 Test::keyboardKeyReleased(KEY_LEFTCTRL, timestamp++);
353 Test::keyboardKeyPressed(KEY_ENTER, timestamp++);
354 Test::keyboardKeyReleased(KEY_ENTER, timestamp++);
355 QCOMPARE(Cursors::self()->mouse()->pos(), targetPos);
356 QVERIFY(!workspace()->moveResizeWindow());
357
358 QCOMPARE(quickTileChangedSpy.count(), 1);
359 QTEST(window->quickTileMode(), "expectedMode");
360}
361
362void QuickTilingTest::testQuickTilingPointerMove_data()
363{
364 QTest::addColumn<QPoint>("pointerPos");
365 QTest::addColumn<QSize>("tileSize");
366 QTest::addColumn<QuickTileMode>("expectedMode");
367
368 QTest::newRow("topRight") << QPoint(2559, 24) << QSize(640, 512) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Right);
369 QTest::newRow("right") << QPoint(2559, 512) << QSize(640, 1024) << QuickTileMode(QuickTileFlag::Right);
370 QTest::newRow("bottomRight") << QPoint(2559, 1023) << QSize(640, 512) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Right);
371 QTest::newRow("bottomLeft") << QPoint(0, 1023) << QSize(640, 512) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Left);
372 QTest::newRow("Left") << QPoint(0, 512) << QSize(640, 1024) << QuickTileMode(QuickTileFlag::Left);
373 QTest::newRow("topLeft") << QPoint(0, 24) << QSize(640, 512) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Left);
374}
375
376void QuickTilingTest::testQuickTilingPointerMove()
377{
378 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
379 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
380
381 // let's render
382 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
383 QVERIFY(window);
384 QCOMPARE(workspace()->activeWindow(), window);
385 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
386 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
387 QCOMPARE(window->maximizeMode(), MaximizeRestore);
388
389 // we have to receive a configure event when the window becomes active
390 QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
391 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
392 QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
393 QVERIFY(surfaceConfigureRequestedSpy.wait());
394 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
395
396 // verify that basic quick tile mode works as expected, i.e. the window is going to be
397 // tiled if the user drags it to a screen edge or a corner
398 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
400 QCOMPARE(window, workspace()->moveResizeWindow());
401 QCOMPARE(Cursors::self()->mouse()->pos(), QPoint(50, 25));
402
403 QFETCH(QPoint, pointerPos);
404 QFETCH(QSize, tileSize);
405 quint32 timestamp = 1;
406 Test::pointerButtonPressed(BTN_LEFT, timestamp++);
407 Test::pointerMotion(pointerPos, timestamp++);
408 Test::pointerButtonReleased(BTN_LEFT, timestamp++);
409 QCOMPARE(quickTileChangedSpy.count(), 1);
410 QTEST(window->quickTileMode(), "expectedMode");
411 QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
412 QVERIFY(surfaceConfigureRequestedSpy.wait());
413 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
414 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), tileSize);
415
416 // attach a new image
417 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
418 Test::render(surface.get(), tileSize, Qt::red);
419 QVERIFY(frameGeometryChangedSpy.wait());
420 QCOMPARE(window->frameGeometry().size(), tileSize);
421
422 // verify that geometry restore is correct after user untiles the window, but changes
423 // their mind and tiles the window again while still holding left button
425 QCOMPARE(window, workspace()->moveResizeWindow());
426
427 Test::pointerButtonPressed(BTN_LEFT, timestamp++); // untile the window
428 Test::pointerMotion(QPoint(1280, 1024) / 2, timestamp++);
429 QCOMPARE(quickTileChangedSpy.count(), 2);
430 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
431 QVERIFY(surfaceConfigureRequestedSpy.wait());
432 QCOMPARE(surfaceConfigureRequestedSpy.count(), 3);
433 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), QSize(100, 50));
434
435 // attach a new image
436 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
437 Test::render(surface.get(), QSize(100, 50), Qt::red);
438 QVERIFY(frameGeometryChangedSpy.wait());
439 QCOMPARE(window->frameGeometry().size(), QSize(100, 50));
440
441 Test::pointerMotion(pointerPos, timestamp++); // tile the window again
442 Test::pointerButtonReleased(BTN_LEFT, timestamp++);
443 QCOMPARE(quickTileChangedSpy.count(), 3);
444 QTEST(window->quickTileMode(), "expectedMode");
445 QCOMPARE(window->geometryRestore(), QRect(0, 0, 100, 50));
446 QVERIFY(surfaceConfigureRequestedSpy.wait());
447 QCOMPARE(surfaceConfigureRequestedSpy.count(), 4);
448 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), tileSize);
449}
450
451void QuickTilingTest::testQuickTilingTouchMove_data()
452{
453 QTest::addColumn<QPoint>("targetPos");
454 QTest::addColumn<QuickTileMode>("expectedMode");
455
456 QTest::newRow("topRight") << QPoint(2559, 24) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Right);
457 QTest::newRow("right") << QPoint(2559, 512) << QuickTileMode(QuickTileFlag::Right);
458 QTest::newRow("bottomRight") << QPoint(2559, 1023) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Right);
459 QTest::newRow("bottomLeft") << QPoint(0, 1023) << QuickTileMode(QuickTileFlag::Bottom | QuickTileFlag::Left);
460 QTest::newRow("Left") << QPoint(0, 512) << QuickTileMode(QuickTileFlag::Left);
461 QTest::newRow("topLeft") << QPoint(0, 24) << QuickTileMode(QuickTileFlag::Top | QuickTileFlag::Left);
462}
463
464void QuickTilingTest::testQuickTilingTouchMove()
465{
466 // test verifies that touch on decoration also allows quick tiling
467 // see BUG: 390113
468 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
469 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get(), Test::CreationSetup::CreateOnly));
470 std::unique_ptr<Test::XdgToplevelDecorationV1> deco(Test::createXdgToplevelDecorationV1(shellSurface.get()));
471
472 QSignalSpy decorationConfigureRequestedSpy(deco.get(), &Test::XdgToplevelDecorationV1::configureRequested);
473 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
474 QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
475
476 // wait for the initial configure event
477 surface->commit(KWayland::Client::Surface::CommitFlag::None);
478 QVERIFY(surfaceConfigureRequestedSpy.wait());
479 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
480
481 // let's render
482 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
483 auto window = Test::renderAndWaitForShown(surface.get(), QSize(1000, 50), Qt::blue);
484
485 QVERIFY(window);
486 QVERIFY(window->isDecorated());
487 const auto decoration = window->decoration();
488 QCOMPARE(workspace()->activeWindow(), window);
489 QCOMPARE(window->frameGeometry(), QRect(-decoration->borderLeft(), 0, 1000 + decoration->borderLeft() + decoration->borderRight(), 50 + decoration->borderTop() + decoration->borderBottom()));
490 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
491 QCOMPARE(window->maximizeMode(), MaximizeRestore);
492
493 // we have to receive a configure event when the window becomes active
494 QVERIFY(surfaceConfigureRequestedSpy.wait());
495 QTRY_COMPARE(surfaceConfigureRequestedSpy.count(), 2);
496
497 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
498
499 // Note that interactive move will be started with a delay.
500 quint32 timestamp = 1;
501 QSignalSpy interactiveMoveResizeStartedSpy(window, &Window::interactiveMoveResizeStarted);
502 Test::touchDown(0, QPointF(window->frameGeometry().center().x(), window->frameGeometry().y() + decoration->borderTop() / 2), timestamp++);
503 QVERIFY(interactiveMoveResizeStartedSpy.wait());
504 QCOMPARE(window, workspace()->moveResizeWindow());
505
506 QFETCH(QPoint, targetPos);
507 Test::touchMotion(0, targetPos, timestamp++);
508 Test::touchUp(0, timestamp++);
509 QVERIFY(!workspace()->moveResizeWindow());
510
511 // When there are no borders, there is no change to them when quick-tiling.
512 // TODO: we should test both cases with fixed fake decoration for autotests.
513 const bool hasBorders = Workspace::self()->decorationBridge()->settings()->borderSize() != KDecoration2::BorderSize::None;
514
515 QCOMPARE(quickTileChangedSpy.count(), 1);
516 QTEST(window->quickTileMode(), "expectedMode");
517 QVERIFY(surfaceConfigureRequestedSpy.wait());
518 QTRY_COMPARE(surfaceConfigureRequestedSpy.count(), hasBorders ? 4 : 3);
519 QCOMPARE(false, toplevelConfigureRequestedSpy.last().first().toSize().isEmpty());
520}
521
522void QuickTilingTest::testX11QuickTiling_data()
523{
524 QTest::addColumn<QuickTileMode>("mode");
525 QTest::addColumn<QRectF>("expectedGeometry");
526 QTest::addColumn<int>("screenId");
527 QTest::addColumn<QuickTileMode>("modeAfterToggle");
528
529#define FLAG(name) QuickTileMode(QuickTileFlag::name)
530
531 QTest::newRow("left") << FLAG(Left) << QRectF(0, 0, 640, 1024) << 0 << QuickTileMode();
532 QTest::newRow("top") << FLAG(Top) << QRectF(0, 0, 1280, 512) << 0 << QuickTileMode();
533 QTest::newRow("right") << FLAG(Right) << QRectF(640, 0, 640, 1024) << 1 << FLAG(Left);
534 QTest::newRow("bottom") << FLAG(Bottom) << QRectF(0, 512, 1280, 512) << 0 << QuickTileMode();
535
536 QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRectF(0, 0, 640, 512) << 0 << QuickTileMode();
537 QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRectF(640, 0, 640, 512) << 1 << (FLAG(Left) | FLAG(Top));
538 QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRectF(0, 512, 640, 512) << 0 << QuickTileMode();
539 QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRectF(640, 512, 640, 512) << 1 << (FLAG(Left) | FLAG(Bottom));
540
541 QTest::newRow("maximize") << FLAG(Maximize) << QRectF(0, 0, 1280, 1024) << 0 << QuickTileMode();
542
543#undef FLAG
544}
545void QuickTilingTest::testX11QuickTiling()
546{
548 QVERIFY(!xcb_connection_has_error(c.get()));
549 const QRect windowGeometry(0, 0, 100, 200);
550 xcb_window_t windowId = xcb_generate_id(c.get());
551 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
552 windowGeometry.x(),
553 windowGeometry.y(),
554 windowGeometry.width(),
555 windowGeometry.height(),
556 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
557 xcb_size_hints_t hints;
558 memset(&hints, 0, sizeof(hints));
559 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
560 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
561 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
562 xcb_map_window(c.get(), windowId);
563 xcb_flush(c.get());
564
565 // we should get a window for it
566 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
567 QVERIFY(windowCreatedSpy.wait());
568 X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
569 QVERIFY(window);
570 QCOMPARE(window->window(), windowId);
571
572 // now quick tile
573 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
574 const QRectF origGeo = window->frameGeometry();
575 QFETCH(QuickTileMode, mode);
576 window->setQuickTileMode(mode, true);
577 QCOMPARE(window->quickTileMode(), mode);
578 QTEST(window->frameGeometry(), "expectedGeometry");
579 QCOMPARE(window->geometryRestore(), origGeo);
580 QEXPECT_FAIL("maximize", "For maximize we get two changed signals", Continue);
581 QCOMPARE(quickTileChangedSpy.count(), 1);
582
583 // quick tile to same edge again should also act like send to screen
584 // if screen is on the same edge
585 const auto outputs = workspace()->outputs();
586 QCOMPARE(window->output(), outputs[0]);
587 window->setQuickTileMode(mode, true);
588 QFETCH(int, screenId);
589 QCOMPARE(window->output(), outputs[screenId]);
590 QTEST(window->quickTileMode(), "modeAfterToggle");
591 QCOMPARE(window->geometryRestore(), origGeo);
592
593 // and destroy the window again
594 xcb_unmap_window(c.get(), windowId);
595 xcb_destroy_window(c.get(), windowId);
596 xcb_flush(c.get());
597 c.reset();
598
599 QSignalSpy windowClosedSpy(window, &X11Window::closed);
600 QVERIFY(windowClosedSpy.wait());
601}
602
603void QuickTilingTest::testX11QuickTilingAfterVertMaximize_data()
604{
605 QTest::addColumn<QuickTileMode>("mode");
606 QTest::addColumn<QRectF>("expectedGeometry");
607
608#define FLAG(name) QuickTileMode(QuickTileFlag::name)
609
610 QTest::newRow("left") << FLAG(Left) << QRectF(0, 0, 640, 1024);
611 QTest::newRow("top") << FLAG(Top) << QRectF(0, 0, 1280, 512);
612 QTest::newRow("right") << FLAG(Right) << QRectF(640, 0, 640, 1024);
613 QTest::newRow("bottom") << FLAG(Bottom) << QRectF(0, 512, 1280, 512);
614
615 QTest::newRow("top left") << (FLAG(Left) | FLAG(Top)) << QRectF(0, 0, 640, 512);
616 QTest::newRow("top right") << (FLAG(Right) | FLAG(Top)) << QRectF(640, 0, 640, 512);
617 QTest::newRow("bottom left") << (FLAG(Left) | FLAG(Bottom)) << QRectF(0, 512, 640, 512);
618 QTest::newRow("bottom right") << (FLAG(Right) | FLAG(Bottom)) << QRectF(640, 512, 640, 512);
619
620 QTest::newRow("maximize") << FLAG(Maximize) << QRectF(0, 0, 1280, 1024);
621
622#undef FLAG
623}
624
625void QuickTilingTest::testX11QuickTilingAfterVertMaximize()
626{
628 QVERIFY(!xcb_connection_has_error(c.get()));
629 const QRect windowGeometry(0, 0, 100, 200);
630 xcb_window_t windowId = xcb_generate_id(c.get());
631 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId, rootWindow(),
632 windowGeometry.x(),
633 windowGeometry.y(),
634 windowGeometry.width(),
635 windowGeometry.height(),
636 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0, nullptr);
637 xcb_size_hints_t hints;
638 memset(&hints, 0, sizeof(hints));
639 xcb_icccm_size_hints_set_position(&hints, 1, windowGeometry.x(), windowGeometry.y());
640 xcb_icccm_size_hints_set_size(&hints, 1, windowGeometry.width(), windowGeometry.height());
641 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
642 xcb_map_window(c.get(), windowId);
643 xcb_flush(c.get());
644
645 // we should get a window for it
646 QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
647 QVERIFY(windowCreatedSpy.wait());
648 X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
649 QVERIFY(window);
650 QCOMPARE(window->window(), windowId);
651
652 const QRectF origGeo = window->frameGeometry();
653 QCOMPARE(window->maximizeMode(), MaximizeRestore);
654 // vertically maximize the window
655 window->maximize(window->maximizeMode() ^ MaximizeVertical);
656 QCOMPARE(window->frameGeometry().width(), origGeo.width());
657 QCOMPARE(window->height(), window->output()->geometry().height());
658 QCOMPARE(window->geometryRestore(), origGeo);
659
660 // now quick tile
661 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
662 QFETCH(QuickTileMode, mode);
663 window->setQuickTileMode(mode, true);
664 QCOMPARE(window->quickTileMode(), mode);
665 QTEST(window->frameGeometry(), "expectedGeometry");
666 QEXPECT_FAIL("", "We get two changed events", Continue);
667 QCOMPARE(quickTileChangedSpy.count(), 1);
668
669 // and destroy the window again
670 xcb_unmap_window(c.get(), windowId);
671 xcb_destroy_window(c.get(), windowId);
672 xcb_flush(c.get());
673 c.reset();
674
675 QSignalSpy windowClosedSpy(window, &X11Window::closed);
676 QVERIFY(windowClosedSpy.wait());
677}
678
679void QuickTilingTest::testShortcut_data()
680{
681 QTest::addColumn<QStringList>("shortcutList");
682 QTest::addColumn<QuickTileMode>("expectedMode");
683 QTest::addColumn<QRect>("expectedGeometry");
684
685#define FLAG(name) QuickTileMode(QuickTileFlag::name)
686 QTest::newRow("top") << QStringList{QStringLiteral("Window Quick Tile Top")} << FLAG(Top) << QRect(0, 0, 1280, 512);
687 QTest::newRow("bottom") << QStringList{QStringLiteral("Window Quick Tile Bottom")} << FLAG(Bottom) << QRect(0, 512, 1280, 512);
688 QTest::newRow("top right") << QStringList{QStringLiteral("Window Quick Tile Top Right")} << (FLAG(Top) | FLAG(Right)) << QRect(640, 0, 640, 512);
689 QTest::newRow("top left") << QStringList{QStringLiteral("Window Quick Tile Top Left")} << (FLAG(Top) | FLAG(Left)) << QRect(0, 0, 640, 512);
690 QTest::newRow("bottom right") << QStringList{QStringLiteral("Window Quick Tile Bottom Right")} << (FLAG(Bottom) | FLAG(Right)) << QRect(640, 512, 640, 512);
691 QTest::newRow("bottom left") << QStringList{QStringLiteral("Window Quick Tile Bottom Left")} << (FLAG(Bottom) | FLAG(Left)) << QRect(0, 512, 640, 512);
692 QTest::newRow("left") << QStringList{QStringLiteral("Window Quick Tile Left")} << FLAG(Left) << QRect(0, 0, 640, 1024);
693 QTest::newRow("right") << QStringList{QStringLiteral("Window Quick Tile Right")} << FLAG(Right) << QRect(640, 0, 640, 1024);
694
695 // Test combined actions for corner tiling
696 QTest::newRow("top left combined") << QStringList{QStringLiteral("Window Quick Tile Left"), QStringLiteral("Window Quick Tile Top")} << (FLAG(Top) | FLAG(Left)) << QRect(0, 0, 640, 512);
697 QTest::newRow("top right combined") << QStringList{QStringLiteral("Window Quick Tile Right"), QStringLiteral("Window Quick Tile Top")} << (FLAG(Top) | FLAG(Right)) << QRect(640, 0, 640, 512);
698 QTest::newRow("bottom left combined") << QStringList{QStringLiteral("Window Quick Tile Left"), QStringLiteral("Window Quick Tile Bottom")} << (FLAG(Bottom) | FLAG(Left)) << QRect(0, 512, 640, 512);
699 QTest::newRow("bottom right combined") << QStringList{QStringLiteral("Window Quick Tile Right"), QStringLiteral("Window Quick Tile Bottom")} << (FLAG(Bottom) | FLAG(Right)) << QRect(640, 512, 640, 512);
700#undef FLAG
701}
702
703void QuickTilingTest::testShortcut()
704{
705#if !KWIN_BUILD_GLOBALSHORTCUTS
706 QSKIP("Can't test shortcuts without shortcuts");
707 return;
708#endif
709
710 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
711 QVERIFY(surface != nullptr);
712 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
713 QVERIFY(shellSurface != nullptr);
714
715 // Map the window.
716 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
717 QVERIFY(window);
718 QCOMPARE(workspace()->activeWindow(), window);
719 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
720 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
721
722 // We have to receive a configure event when the window becomes active.
723 QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
724 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
725 QVERIFY(surfaceConfigureRequestedSpy.wait());
726 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
727
728 QFETCH(QStringList, shortcutList);
729 QFETCH(QRect, expectedGeometry);
730
731 const int numberOfQuickTileActions = shortcutList.count();
732
733 for (QString shortcut : shortcutList) {
734 // invoke global shortcut through dbus
735 auto msg = QDBusMessage::createMethodCall(
736 QStringLiteral("org.kde.kglobalaccel"),
737 QStringLiteral("/component/kwin"),
738 QStringLiteral("org.kde.kglobalaccel.Component"),
739 QStringLiteral("invokeShortcut"));
740 msg.setArguments(QList<QVariant>{shortcut});
741 QDBusConnection::sessionBus().asyncCall(msg);
742 }
743
744 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
745 QTRY_COMPARE(quickTileChangedSpy.count(), numberOfQuickTileActions);
746 // at this point the geometry did not yet change
747 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
748 // but quick tile mode already changed
749 QTEST(window->quickTileMode(), "expectedMode");
750
751 // but we got requested a new geometry
752 QVERIFY(surfaceConfigureRequestedSpy.wait());
753 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
754 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), expectedGeometry.size());
755
756 // attach a new image
757 QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
758 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
759 Test::render(surface.get(), expectedGeometry.size(), Qt::red);
760
761 QVERIFY(frameGeometryChangedSpy.wait());
762 QEXPECT_FAIL("maximize", "Geometry changed called twice for maximize", Continue);
763 QCOMPARE(frameGeometryChangedSpy.count(), 1);
764 QCOMPARE(window->frameGeometry(), expectedGeometry);
765}
766
767void QuickTilingTest::testScript_data()
768{
769 QTest::addColumn<QString>("action");
770 QTest::addColumn<QuickTileMode>("expectedMode");
771 QTest::addColumn<QRect>("expectedGeometry");
772
773#define FLAG(name) QuickTileMode(QuickTileFlag::name)
774 QTest::newRow("top") << QStringLiteral("Top") << FLAG(Top) << QRect(0, 0, 1280, 512);
775 QTest::newRow("bottom") << QStringLiteral("Bottom") << FLAG(Bottom) << QRect(0, 512, 1280, 512);
776 QTest::newRow("top right") << QStringLiteral("TopRight") << (FLAG(Top) | FLAG(Right)) << QRect(640, 0, 640, 512);
777 QTest::newRow("top left") << QStringLiteral("TopLeft") << (FLAG(Top) | FLAG(Left)) << QRect(0, 0, 640, 512);
778 QTest::newRow("bottom right") << QStringLiteral("BottomRight") << (FLAG(Bottom) | FLAG(Right)) << QRect(640, 512, 640, 512);
779 QTest::newRow("bottom left") << QStringLiteral("BottomLeft") << (FLAG(Bottom) | FLAG(Left)) << QRect(0, 512, 640, 512);
780 QTest::newRow("left") << QStringLiteral("Left") << FLAG(Left) << QRect(0, 0, 640, 1024);
781 QTest::newRow("right") << QStringLiteral("Right") << FLAG(Right) << QRect(640, 0, 640, 1024);
782#undef FLAG
783}
784
785void QuickTilingTest::testScript()
786{
787 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface());
788 QVERIFY(surface != nullptr);
789 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get()));
790 QVERIFY(shellSurface != nullptr);
791
792 // Map the window.
793 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue);
794 QVERIFY(window);
795 QCOMPARE(workspace()->activeWindow(), window);
796 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
797 QCOMPARE(window->quickTileMode(), QuickTileMode(QuickTileFlag::None));
798
799 // We have to receive a configure event upon the window becoming active.
800 QSignalSpy toplevelConfigureRequestedSpy(shellSurface.get(), &Test::XdgToplevel::configureRequested);
801 QSignalSpy surfaceConfigureRequestedSpy(shellSurface->xdgSurface(), &Test::XdgSurface::configureRequested);
802 QVERIFY(surfaceConfigureRequestedSpy.wait());
803 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
804
805 QSignalSpy quickTileChangedSpy(window, &Window::quickTileModeChanged);
806 QSignalSpy frameGeometryChangedSpy(window, &Window::frameGeometryChanged);
807
808 QVERIFY(Scripting::self());
809 QTemporaryFile tmpFile;
810 QVERIFY(tmpFile.open());
811 QTextStream out(&tmpFile);
812
813 QFETCH(QString, action);
814 out << "workspace.slotWindowQuickTile" << action << "()";
815 out.flush();
816
817 QFETCH(QuickTileMode, expectedMode);
818 QFETCH(QRect, expectedGeometry);
819
820 const int id = Scripting::self()->loadScript(tmpFile.fileName());
821 QVERIFY(id != -1);
822 QVERIFY(Scripting::self()->isScriptLoaded(tmpFile.fileName()));
823 auto s = Scripting::self()->findScript(tmpFile.fileName());
824 QVERIFY(s);
825 QSignalSpy runningChangedSpy(s, &AbstractScript::runningChanged);
826 s->run();
827
828 QVERIFY(quickTileChangedSpy.wait());
829 QCOMPARE(quickTileChangedSpy.count(), 1);
830
831 QCOMPARE(runningChangedSpy.count(), 1);
832 QCOMPARE(runningChangedSpy.first().first().toBool(), true);
833
834 // at this point the geometry did not yet change
835 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
836 // but quick tile mode already changed
837 QCOMPARE(window->quickTileMode(), expectedMode);
838
839 // but we got requested a new geometry
840 QVERIFY(surfaceConfigureRequestedSpy.wait());
841 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
842 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), expectedGeometry.size());
843
844 // attach a new image
845 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
846 Test::render(surface.get(), expectedGeometry.size(), Qt::red);
847
848 QVERIFY(frameGeometryChangedSpy.wait());
849 QEXPECT_FAIL("maximize", "Geometry changed called twice for maximize", Continue);
850 QCOMPARE(frameGeometryChangedSpy.count(), 1);
851 QCOMPARE(window->frameGeometry(), expectedGeometry);
852}
853
854}
855
857#include "quick_tiling_test.moc"
void runningChanged(bool)
static Cursors * self()
Definition cursor.cpp:35
std::unique_ptr< KDecoration2::DecorationSettingsPrivate > settings(KDecoration2::DecorationSettings *parent) override
PointerInputRedirection * pointer() const
Definition input.h:220
@ UnrestrictedMoveOp
Definition options.h:405
void warp(const QPointF &pos)
AbstractScript * findScript(const QString &pluginName) const
Q_SCRIPTABLE Q_INVOKABLE int loadScript(const QString &filePath, const QString &pluginName=QString())
static Scripting * self()
Definition scripting.h:393
void configureRequested(quint32 serial)
void configureRequested(QtWayland::zxdg_toplevel_decoration_v1::mode mode)
void configureRequested(const QSize &size, KWin::Test::XdgToplevel::States states)
void interactiveMoveResizeStarted()
void maximizedChanged()
void quickTileModeChanged()
void frameGeometryChanged(const QRectF &oldGeometry)
void performWindowOperation(KWin::Window *window, Options::WindowOperation op)
Decoration::DecorationBridge * decorationBridge() const
static Workspace * self()
Definition workspace.h:91
void windowAdded(KWin::Window *)
QList< Output * > outputs() const
Definition workspace.h:762
void setActiveOutput(Output *output)
Q_DECLARE_METATYPE(KWin::SwitchEvent::State)
#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 keyboardKeyReleased(quint32 key, quint32 time)
void destroyWaylandConnection()
void setOutputConfig(const QList< QRect > &geometries)
void touchDown(qint32 id, const QPointF &pos, quint32 time)
void keyboardKeyPressed(quint32 key, quint32 time)
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
void touchMotion(qint32 id, const QPointF &pos, quint32 time)
KWayland::Client::Compositor * waylandCompositor()
void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32_Premultiplied)
void pointerButtonPressed(quint32 button, quint32 time)
XcbConnectionPtr createX11Connection()
QList< KWayland::Client::Output * > outputs
void pointerMotion(const QPointF &position, quint32 time)
std::unique_ptr< KWayland::Client::Surface > createSurface()
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
XdgToplevelDecorationV1 * createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent=nullptr)
KWayland::Client::ConnectionThread * waylandConnection()
void pointerButtonReleased(quint32 button, quint32 time)
void touchUp(qint32 id, quint32 time)
std::unique_ptr< xcb_connection_t, XcbConnectionDeleter > XcbConnectionPtr
KWIN_EXPORT xcb_window_t rootWindow()
Definition xcb.h:24
@ None
Definition options.h:37
MaximizeMode
Definition common.h:74
@ MaximizeVertical
The window is maximized vertically.
Definition common.h:76
@ MaximizeRestore
The window is not maximized in any direction.
Definition common.h:75
@ MaximizeFull
Equal to MaximizeVertical | MaximizeHorizontal.
Definition common.h:79
WaylandServer * waylandServer()
Workspace * workspace()
Definition workspace.h:830
InputRedirection * input()
Definition input.h:549
#define FLAG(name)