22#include <KWayland/Client/compositor.h>
23#include <KWayland/Client/connection_thread.h>
24#include <KWayland/Client/pointer.h>
25#include <KWayland/Client/seat.h>
26#include <KWayland/Client/surface.h>
28#include <linux/input.h>
29#include <xcb/xcb_icccm.h>
37static const QString s_socketName = QStringLiteral(
"wayland_test_kwin_quick_tiling-0");
48 void testPackTo_data();
50 void testPackAgainstClient_data();
51 void testPackAgainstClient();
52 void testGrowShrink_data();
53 void testGrowShrink();
54 void testPointerMoveEnd_data();
55 void testPointerMoveEnd();
56 void testClientSideMove();
58 void testAdjustClientGeometryOfHiddenX11Panel_data();
59 void testAdjustClientGeometryOfHiddenX11Panel();
60 void testAdjustClientGeometryOfHiddenWaylandPanel_data();
61 void testAdjustClientGeometryOfHiddenWaylandPanel();
62 void testResizeForVirtualKeyboard_data();
63 void testResizeForVirtualKeyboard();
64 void testResizeForVirtualKeyboardWithMaximize();
65 void testResizeForVirtualKeyboardWithFullScreen();
66 void testDestroyMoveClient();
67 void testDestroyResizeClient();
68 void testCancelInteractiveMoveResize_data();
69 void testCancelInteractiveMoveResize();
72 KWayland::Client::ConnectionThread *m_connection =
nullptr;
73 KWayland::Client::Compositor *m_compositor =
nullptr;
76void MoveResizeWindowTest::initTestCase()
78 qRegisterMetaType<KWin::Window *>();
79 qRegisterMetaType<KWin::MaximizeMode>(
"MaximizeMode");
84 QVERIFY(applicationStartedSpy.wait());
86 QCOMPARE(outputs.count(), 1);
87 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
90void MoveResizeWindowTest::init()
100void MoveResizeWindowTest::cleanup()
105void MoveResizeWindowTest::testMove()
108 QVERIFY(surface !=
nullptr);
111 QVERIFY(shellSurface !=
nullptr);
116 QCOMPARE(
workspace()->activeWindow(), window);
117 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
124 QVERIFY(
workspace()->moveResizeWindow() ==
nullptr);
125 QCOMPARE(window->isInteractiveMove(),
false);
127 QCOMPARE(
workspace()->moveResizeWindow(), window);
128 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
129 QCOMPARE(moveResizedChangedSpy.count(), 1);
130 QCOMPARE(window->isInteractiveMove(),
true);
131 QCOMPARE(window->geometryRestore(), QRect());
135 window->keyPressEvent(Qt::Key_Right);
136 window->updateInteractiveMoveResize(
Cursors::self()->mouse()->pos());
137 QCOMPARE(
Cursors::self()->mouse()->pos(), cursorPos + QPoint(8, 0));
138 QEXPECT_FAIL(
"",
"First event is ignored", Continue);
139 QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
140 interactiveMoveResizeSteppedSpy.clear();
142 window->keyPressEvent(Qt::Key_Right);
143 window->updateInteractiveMoveResize(
Cursors::self()->mouse()->pos());
144 QCOMPARE(
Cursors::self()->mouse()->pos(), cursorPos + QPoint(16, 0));
145 QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
147 window->keyPressEvent(Qt::Key_Down | Qt::ALT);
148 window->updateInteractiveMoveResize(
Cursors::self()->mouse()->pos());
149 QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2);
150 QCOMPARE(window->frameGeometry(), QRect(16, 32, 100, 50));
151 QCOMPARE(
Cursors::self()->mouse()->pos(), cursorPos + QPoint(16, 32));
154 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 0);
155 window->keyPressEvent(Qt::Key_Enter);
156 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
157 QCOMPARE(moveResizedChangedSpy.count(), 2);
158 QCOMPARE(window->frameGeometry(), QRect(16, 32, 100, 50));
159 QCOMPARE(window->isInteractiveMove(),
false);
160 QVERIFY(
workspace()->moveResizeWindow() ==
nullptr);
165void MoveResizeWindowTest::testResize()
170 QVERIFY(surface !=
nullptr);
173 QVERIFY(shellSurface !=
nullptr);
176 Test::XdgToplevel::States states;
179 surface->commit(KWayland::Client::Surface::CommitFlag::None);
180 QVERIFY(surfaceConfigureRequestedSpy.wait());
181 QCOMPARE(surfaceConfigureRequestedSpy.count(), 1);
182 QCOMPARE(toplevelConfigureRequestedSpy.count(), 1);
183 states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
188 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
192 QVERIFY(surfaceConfigureRequestedSpy.wait());
193 QCOMPARE(surfaceConfigureRequestedSpy.count(), 2);
194 QCOMPARE(toplevelConfigureRequestedSpy.count(), 2);
195 states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
200 QCOMPARE(
workspace()->activeWindow(), window);
201 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
209 QCOMPARE(
workspace()->moveResizeWindow(),
nullptr);
210 QCOMPARE(window->isInteractiveMove(),
false);
211 QCOMPARE(window->isInteractiveResize(),
false);
213 QCOMPARE(
workspace()->moveResizeWindow(), window);
214 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
215 QCOMPARE(moveResizedChangedSpy.count(), 1);
216 QCOMPARE(window->isInteractiveResize(),
true);
217 QCOMPARE(window->geometryRestore(), QRect());
218 QVERIFY(surfaceConfigureRequestedSpy.wait());
219 QCOMPARE(surfaceConfigureRequestedSpy.count(), 3);
220 QCOMPARE(toplevelConfigureRequestedSpy.count(), 3);
221 states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
227 window->keyPressEvent(Qt::Key_Right);
228 window->updateInteractiveMoveResize(
Cursors::self()->mouse()->pos());
229 QCOMPARE(
Cursors::self()->mouse()->pos(), cursorPos + QPoint(8, 0));
232 QVERIFY(surfaceConfigureRequestedSpy.wait());
233 QCOMPARE(surfaceConfigureRequestedSpy.count(), 4);
234 QCOMPARE(toplevelConfigureRequestedSpy.count(), 4);
235 states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
238 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), QSize(108, 50));
239 QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
242 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
244 QVERIFY(frameGeometryChangedSpy.wait());
245 QCOMPARE(window->frameGeometry(), QRect(0, 0, 108, 50));
246 QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
249 window->keyPressEvent(Qt::Key_Down);
250 window->updateInteractiveMoveResize(
Cursors::self()->mouse()->pos());
251 QCOMPARE(
Cursors::self()->mouse()->pos(), cursorPos + QPoint(8, 8));
254 QVERIFY(surfaceConfigureRequestedSpy.wait());
255 QCOMPARE(surfaceConfigureRequestedSpy.count(), 5);
256 QCOMPARE(toplevelConfigureRequestedSpy.count(), 5);
257 states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
260 QCOMPARE(toplevelConfigureRequestedSpy.last().at(0).toSize(), QSize(108, 58));
263 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
265 QVERIFY(frameGeometryChangedSpy.wait());
266 QCOMPARE(window->frameGeometry(), QRect(0, 0, 108, 58));
267 QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 2);
270 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 0);
271 window->keyPressEvent(Qt::Key_Enter);
272 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
273 QCOMPARE(moveResizedChangedSpy.count(), 2);
274 QCOMPARE(window->isInteractiveResize(),
false);
275 QCOMPARE(
workspace()->moveResizeWindow(),
nullptr);
276 QVERIFY(surfaceConfigureRequestedSpy.wait());
277 QCOMPARE(surfaceConfigureRequestedSpy.count(), 6);
278 QCOMPARE(toplevelConfigureRequestedSpy.count(), 6);
279 states = toplevelConfigureRequestedSpy.last().at(1).value<Test::XdgToplevel::States>();
284 shellSurface.reset();
288void MoveResizeWindowTest::testPackTo_data()
290 QTest::addColumn<QString>(
"methodCall");
291 QTest::addColumn<QRectF>(
"expectedGeometry");
293 QTest::newRow(
"left") << QStringLiteral(
"slotWindowMoveLeft") << QRectF(0, 487, 100, 50);
294 QTest::newRow(
"up") << QStringLiteral(
"slotWindowMoveUp") << QRectF(590, 0, 100, 50);
295 QTest::newRow(
"right") << QStringLiteral(
"slotWindowMoveRight") << QRectF(1180, 487, 100, 50);
296 QTest::newRow(
"down") << QStringLiteral(
"slotWindowMoveDown") << QRectF(590, 974, 100, 50);
299void MoveResizeWindowTest::testPackTo()
302 QVERIFY(surface !=
nullptr);
305 QVERIFY(shellSurface !=
nullptr);
310 QCOMPARE(
workspace()->activeWindow(), window);
311 QCOMPARE(window->frameGeometry(), QRect(0, 0, 100, 50));
315 QCOMPARE(window->frameGeometry(), QRect(590, 487, 100, 50));
317 QFETCH(QString, methodCall);
318 QMetaObject::invokeMethod(
workspace(), methodCall.toLocal8Bit().constData());
319 QTEST(window->frameGeometry(),
"expectedGeometry");
324void MoveResizeWindowTest::testPackAgainstClient_data()
326 QTest::addColumn<QString>(
"methodCall");
327 QTest::addColumn<QRectF>(
"expectedGeometry");
329 QTest::newRow(
"left") << QStringLiteral(
"slotWindowMoveLeft") << QRectF(10, 487, 100, 50);
330 QTest::newRow(
"up") << QStringLiteral(
"slotWindowMoveUp") << QRectF(590, 10, 100, 50);
331 QTest::newRow(
"right") << QStringLiteral(
"slotWindowMoveRight") << QRectF(1170, 487, 100, 50);
332 QTest::newRow(
"down") << QStringLiteral(
"slotWindowMoveDown") << QRectF(590, 964, 100, 50);
335void MoveResizeWindowTest::testPackAgainstClient()
338 QVERIFY(surface1 !=
nullptr);
340 QVERIFY(surface2 !=
nullptr);
342 QVERIFY(surface3 !=
nullptr);
344 QVERIFY(surface4 !=
nullptr);
347 QVERIFY(shellSurface1 !=
nullptr);
349 QVERIFY(shellSurface2 !=
nullptr);
351 QVERIFY(shellSurface3 !=
nullptr);
353 QVERIFY(shellSurface4 !=
nullptr);
354 auto renderWindow = [](KWayland::Client::Surface *surface,
const QString &methodCall,
const QRect &expectedGeometry) {
359 QCOMPARE(
workspace()->activeWindow(), window);
360 QCOMPARE(window->frameGeometry().size(), QSize(10, 10));
363 QCOMPARE(window->frameGeometry(), QRect(635, 507, 10, 10));
364 QMetaObject::invokeMethod(
workspace(), methodCall.toLocal8Bit().constData());
365 QCOMPARE(window->frameGeometry(), expectedGeometry);
367 renderWindow(surface1.get(), QStringLiteral(
"slotWindowMoveLeft"), QRect(0, 507, 10, 10));
368 renderWindow(surface2.get(), QStringLiteral(
"slotWindowMoveUp"), QRect(635, 0, 10, 10));
369 renderWindow(surface3.get(), QStringLiteral(
"slotWindowMoveRight"), QRect(1270, 507, 10, 10));
370 renderWindow(surface4.get(), QStringLiteral(
"slotWindowMoveDown"), QRect(635, 1014, 10, 10));
373 QVERIFY(surface !=
nullptr);
375 QVERIFY(shellSurface !=
nullptr);
379 QCOMPARE(
workspace()->activeWindow(), window);
382 QCOMPARE(window->frameGeometry(), QRect(590, 487, 100, 50));
384 QFETCH(QString, methodCall);
385 QMetaObject::invokeMethod(
workspace(), methodCall.toLocal8Bit().constData());
386 QTEST(window->frameGeometry(),
"expectedGeometry");
389void MoveResizeWindowTest::testGrowShrink_data()
391 QTest::addColumn<QString>(
"methodCall");
392 QTest::addColumn<QRectF>(
"expectedGeometry");
394 QTest::newRow(
"grow vertical") << QStringLiteral(
"slotWindowExpandVertical") << QRectF(590, 487, 100, 537);
395 QTest::newRow(
"grow horizontal") << QStringLiteral(
"slotWindowExpandHorizontal") << QRectF(590, 487, 690, 50);
396 QTest::newRow(
"shrink vertical") << QStringLiteral(
"slotWindowShrinkVertical") << QRectF(590, 487, 100, 23);
397 QTest::newRow(
"shrink horizontal") << QStringLiteral(
"slotWindowShrinkHorizontal") << QRectF(590, 487, 40, 50);
400void MoveResizeWindowTest::testGrowShrink()
404 QVERIFY(surface1 !=
nullptr);
406 QVERIFY(shellSurface1 !=
nullptr);
407 Test::render(surface1.get(), QSize(650, 514), Qt::blue);
413 QVERIFY(surface !=
nullptr);
416 QVERIFY(shellSurface !=
nullptr);
421 QVERIFY(toplevelConfigureRequestedSpy.wait());
424 QCOMPARE(
workspace()->activeWindow(), window);
428 QCOMPARE(window->frameGeometry(), QRect(590, 487, 100, 50));
430 QFETCH(QString, methodCall);
431 QMetaObject::invokeMethod(
workspace(), methodCall.toLocal8Bit().constData());
432 QVERIFY(surfaceConfigureRequestedSpy.wait());
433 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::red);
436 m_connection->flush();
437 QVERIFY(frameGeometryChangedSpy.wait());
438 QTEST(window->frameGeometry(),
"expectedGeometry");
441void MoveResizeWindowTest::testPointerMoveEnd_data()
443 QTest::addColumn<int>(
"additionalButton");
445 QTest::newRow(
"BTN_RIGHT") << BTN_RIGHT;
446 QTest::newRow(
"BTN_MIDDLE") << BTN_MIDDLE;
447 QTest::newRow(
"BTN_SIDE") << BTN_SIDE;
448 QTest::newRow(
"BTN_EXTRA") << BTN_EXTRA;
449 QTest::newRow(
"BTN_FORWARD") << BTN_FORWARD;
450 QTest::newRow(
"BTN_BACK") << BTN_BACK;
451 QTest::newRow(
"BTN_TASK") << BTN_TASK;
452 for (
int i = BTN_TASK + 1; i < BTN_JOYSTICK; i++) {
453 QTest::newRow(QByteArray::number(i, 16).constData()) << i;
457void MoveResizeWindowTest::testPointerMoveEnd()
462 QVERIFY(surface !=
nullptr);
465 QVERIFY(shellSurface !=
nullptr);
470 QCOMPARE(window,
workspace()->activeWindow());
471 QVERIFY(!window->isInteractiveMove());
474 quint32 timestamp = 1;
476 QVERIFY(!window->isInteractiveMove());
478 QVERIFY(window->isInteractiveMove());
481 QFETCH(
int, additionalButton);
483 QVERIFY(window->isInteractiveMove());
487 QVERIFY(window->isInteractiveMove());
491 QVERIFY(!window->isInteractiveMove());
495void MoveResizeWindowTest::testClientSideMove()
498 std::unique_ptr<KWayland::Client::Pointer> pointer(
Test::waylandSeat()->createPointer());
499 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered);
500 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left);
501 QSignalSpy buttonSpy(pointer.get(), &KWayland::Client::Pointer::buttonStateChanged);
509 const QRectF startGeometry = window->frameGeometry();
511 QVERIFY(pointerEnteredSpy.wait());
512 QCOMPARE(pointerEnteredSpy.first().last().toPoint(), QPoint(50, 25));
514 quint32 timestamp = 1;
516 QVERIFY(buttonSpy.wait());
518 shellSurface->move(*
Test::waylandSeat(), buttonSpy.first().first().value<quint32>());
519 QVERIFY(interactiveMoveResizeStartedSpy.wait());
520 QCOMPARE(window->isInteractiveMove(),
true);
521 QVERIFY(pointerLeftSpy.wait());
525 const QPointF startPoint = startGeometry.center();
526 const int dragDistance = QApplication::startDragDistance();
528 Test::pointerMotion(startPoint + QPoint(dragDistance, dragDistance) + QPoint(6, 6), timestamp++);
529 QCOMPARE(clientMoveStepSpy.count(), 1);
533 QVERIFY(pointerEnteredSpy.wait());
534 QCOMPARE(window->isInteractiveMove(),
false);
535 QCOMPARE(window->frameGeometry(), startGeometry.translated(QPoint(dragDistance, dragDistance) + QPoint(6, 6)));
536 QCOMPARE(pointerEnteredSpy.last().last().toPoint(), QPoint(50, 25));
539void MoveResizeWindowTest::testNetMove()
544 QVERIFY(!xcb_connection_has_error(c.get()));
546 xcb_window_t windowId = xcb_generate_id(c.get());
547 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId,
rootWindow(),
549 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0,
nullptr);
550 xcb_size_hints_t hints;
551 memset(&hints, 0,
sizeof(hints));
552 xcb_icccm_size_hints_set_position(&hints, 1, 0, 0);
553 xcb_icccm_size_hints_set_size(&hints, 1, 100, 100);
554 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
556 NETWinInfo winInfo(c.get(), windowId,
rootWindow(), NET::WMWindowType, NET::Properties2());
557 winInfo.setWindowType(NET::Override);
558 xcb_map_window(c.get(), windowId);
562 QVERIFY(windowCreatedSpy.wait());
563 X11Window *window = windowCreatedSpy.first().first().value<X11Window *>();
565 QCOMPARE(window->window(), windowId);
566 const QRectF origGeo = window->frameGeometry();
570 QVERIFY(!exclusiveContains(origGeo,
Cursors::self()->mouse()->pos()));
575 QVERIFY(!
workspace()->moveResizeWindow());
578 NETRootInfo root(c.get(), NET::Properties());
579 root.moveResizeRequest(windowId, origGeo.center().x(), origGeo.center().y(), NET::Move, XCB_BUTTON_INDEX_1);
582 QVERIFY(interactiveMoveResizeStartedSpy.wait());
583 QCOMPARE(
workspace()->moveResizeWindow(), window);
584 QVERIFY(window->isInteractiveMove());
585 QCOMPARE(window->geometryRestore(), origGeo);
590 QCOMPARE(interactiveMoveResizeSteppedSpy.count(), 1);
591 QCOMPARE(interactiveMoveResizeSteppedSpy.first().last(), origGeo.translated(10, 10));
594 root.moveResizeRequest(windowId, window->frameGeometry().center().x(), window->frameGeometry().center().y(), NET::MoveResizeCancel, XCB_BUTTON_INDEX_1);
596 QVERIFY(interactiveMoveResizeFinishedSpy.wait());
599 xcb_unmap_window(c.get(), windowId);
600 xcb_destroy_window(c.get(), windowId);
605 QVERIFY(windowClosedSpy.wait());
608void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel_data()
610 QTest::addColumn<QRect>(
"panelGeometry");
611 QTest::addColumn<QPoint>(
"targetPoint");
612 QTest::addColumn<QPoint>(
"expectedAdjustedPoint");
613 QTest::addColumn<quint32>(
"hideLocation");
615 QTest::newRow(
"top") << QRect(0, 0, 100, 20) << QPoint(50, 25) << QPoint(50, 20) << 0u;
616 QTest::newRow(
"bottom") << QRect(0, 1024 - 20, 100, 20) << QPoint(50, 1024 - 25 - 50) << QPoint(50, 1024 - 20 - 50) << 2u;
617 QTest::newRow(
"left") << QRect(0, 0, 20, 100) << QPoint(25, 50) << QPoint(20, 50) << 3u;
618 QTest::newRow(
"right") << QRect(1280 - 20, 0, 20, 100) << QPoint(1280 - 25 - 100, 50) << QPoint(1280 - 20 - 100, 50) << 1u;
621void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenX11Panel()
628 QVERIFY(!xcb_connection_has_error(c.get()));
630 xcb_window_t windowId = xcb_generate_id(c.get());
631 QFETCH(QRect, panelGeometry);
632 xcb_create_window(c.get(), XCB_COPY_FROM_PARENT, windowId,
rootWindow(),
633 panelGeometry.x(), panelGeometry.y(), panelGeometry.width(), panelGeometry.height(),
634 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, XCB_COPY_FROM_PARENT, 0,
nullptr);
635 xcb_size_hints_t hints;
636 memset(&hints, 0,
sizeof(hints));
637 xcb_icccm_size_hints_set_position(&hints, 1, panelGeometry.x(), panelGeometry.y());
638 xcb_icccm_size_hints_set_size(&hints, 1, panelGeometry.width(), panelGeometry.height());
639 xcb_icccm_set_wm_normal_hints(c.get(), windowId, &hints);
640 NETWinInfo winInfo(c.get(), windowId,
rootWindow(), NET::WMWindowType, NET::Properties2());
641 winInfo.setWindowType(NET::Dock);
642 xcb_map_window(c.get(), windowId);
646 QVERIFY(windowCreatedSpy.wait());
647 X11Window *panel = windowCreatedSpy.first().first().value<X11Window *>();
649 QCOMPARE(panel->window(), windowId);
650 QCOMPARE(panel->frameGeometry(), panelGeometry);
651 QVERIFY(panel->isDock());
655 QVERIFY(surface !=
nullptr);
658 QVERIFY(shellSurface !=
nullptr);
662 QVERIFY(testWindow->isMovable());
664 QFETCH(QPoint, targetPoint);
665 QTEST(
Workspace::self()->adjustWindowPosition(testWindow, targetPoint,
false).toPoint(),
"expectedAdjustedPoint");
669 QFETCH(quint32, hideLocation);
670 xcb_change_property(c.get(), XCB_PROP_MODE_REPLACE, windowId,
atoms->
kde_screen_edge_show, XCB_ATOM_CARDINAL, 32, 1, &hideLocation);
672 QVERIFY(panelHiddenSpy.wait());
675 QCOMPARE(
Workspace::self()->adjustWindowPosition(testWindow, targetPoint,
false), targetPoint);
678 xcb_unmap_window(c.get(), windowId);
679 xcb_destroy_window(c.get(), windowId);
684 QVERIFY(panelClosedSpy.wait());
687 QCOMPARE(
Workspace::self()->adjustWindowPosition(testWindow, targetPoint,
false), targetPoint);
691 shellSurface.reset();
693 QVERIFY(windowClosedSpy.wait());
696void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenWaylandPanel_data()
698 QTest::addColumn<uint32_t>(
"anchor");
699 QTest::addColumn<QRect>(
"panelGeometry");
700 QTest::addColumn<QPoint>(
"targetPoint");
701 QTest::addColumn<QPoint>(
"expectedAdjustedPoint");
703 QTest::newRow(
"top") << uint32_t(Test::LayerSurfaceV1::anchor_top) << QRect(0, 0, 1280, 20) << QPoint(50, 25) << QPoint(50, 20);
704 QTest::newRow(
"bottom") << uint32_t(Test::LayerSurfaceV1::anchor_bottom) << QRect(0, 1024 - 20, 1280, 20) << QPoint(50, 1024 - 25 - 50) << QPoint(50, 1024 - 20 - 50);
705 QTest::newRow(
"left") << uint32_t(Test::LayerSurfaceV1::anchor_left) << QRect(0, 0, 20, 1024) << QPoint(25, 50) << QPoint(20, 50);
706 QTest::newRow(
"right") << uint32_t(Test::LayerSurfaceV1::anchor_right) << QRect(1280 - 20, 0, 20, 1024) << QPoint(1280 - 25 - 100, 50) << QPoint(1280 - 20 - 100, 50);
709void MoveResizeWindowTest::testAdjustClientGeometryOfHiddenWaylandPanel()
716 std::unique_ptr<Test::LayerSurfaceV1> panelShellSurface(
Test::createLayerSurfaceV1(panelSurface.get(), QStringLiteral(
"dock")));
717 QFETCH(QRect, panelGeometry);
718 QFETCH(uint32_t, anchor);
719 panelShellSurface->set_anchor(anchor);
720 panelShellSurface->set_size(panelGeometry.width(), panelGeometry.height());
721 panelSurface->commit(KWayland::Client::Surface::CommitFlag::None);
725 QVERIFY(panelConfigureRequestedSpy.wait());
728 QCOMPARE(panel->frameGeometry(), panelGeometry);
729 QVERIFY(panel->isDock());
733 QVERIFY(surface !=
nullptr);
736 QVERIFY(shellSurface !=
nullptr);
740 QVERIFY(testWindow->isMovable());
742 QFETCH(QPoint, targetPoint);
743 QTEST(
Workspace::self()->adjustWindowPosition(testWindow, targetPoint,
false).toPoint(),
"expectedAdjustedPoint");
746 panel->setHidden(
true);
749 QCOMPARE(
Workspace::self()->adjustWindowPosition(testWindow, targetPoint,
false), targetPoint);
753 panelShellSurface.reset();
754 panelSurface.reset();
755 QVERIFY(panelClosedSpy.wait());
758 QCOMPARE(
Workspace::self()->adjustWindowPosition(testWindow, targetPoint,
false), targetPoint);
762 shellSurface.reset();
764 QVERIFY(windowClosedSpy.wait());
767void MoveResizeWindowTest::testResizeForVirtualKeyboard_data()
769 QTest::addColumn<QRect>(
"windowRect");
770 QTest::addColumn<QRect>(
"keyboardRect");
771 QTest::addColumn<QRect>(
"resizedWindowRect");
773 QTest::newRow(
"standard") << QRect(100, 300, 500, 800) << QRect(0, 100, 1280, 500) << QRect(100, 0, 500, 100);
774 QTest::newRow(
"same size") << QRect(100, 300, 500, 500) << QRect(0, 600, 1280, 400) << QRect(100, 100, 500, 500);
775 QTest::newRow(
"smaller width") << QRect(100, 300, 500, 800) << QRect(300, 100, 100, 500) << QRect(100, 0, 500, 100);
776 QTest::newRow(
"no height change") << QRect(100, 300, 500, 500) << QRect(0, 900, 1280, 124) << QRect(100, 300, 500, 500);
777 QTest::newRow(
"no width change") << QRect(100, 300, 500, 500) << QRect(0, 400, 100, 500) << QRect(100, 300, 500, 500);
780void MoveResizeWindowTest::testResizeForVirtualKeyboard()
783 QVERIFY(surface !=
nullptr);
786 QVERIFY(shellSurface !=
nullptr);
788 QFETCH(QRect, windowRect);
789 QFETCH(QRect, keyboardRect);
790 QFETCH(QRect, resizedWindowRect);
799 bool sizeChange = windowRect.size() != resizedWindowRect.size();
800 bool positionChange = windowRect.topLeft() != resizedWindowRect.topLeft();
809 QVERIFY(surfaceConfigureRequestedSpy.wait());
810 surfaceConfigureRequestedSpy.clear();
812 window->move(windowRect.topLeft());
815 QCOMPARE(window->frameGeometry(), windowRect);
816 window->setVirtualKeyboardGeometry(keyboardRect);
819 QVERIFY(surfaceConfigureRequestedSpy.wait());
820 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last()[0].toInt());
822 QVERIFY(surfaceConfigureRequestedSpy.count() == 0);
825 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
827 if (positionChange || sizeChange) {
828 QVERIFY(frameGeometryChangedSpy.count() > 0 || frameGeometryChangedSpy.wait());
829 frameGeometryChangedSpy.clear();
831 QVERIFY(frameGeometryChangedSpy.count() == 0);
834 QCOMPARE(window->frameGeometry(), resizedWindowRect);
835 window->setVirtualKeyboardGeometry(QRect());
838 QVERIFY(surfaceConfigureRequestedSpy.wait());
839 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last()[0].toInt());
842 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
844 if (positionChange || sizeChange) {
845 QVERIFY(frameGeometryChangedSpy.count() > 0 || frameGeometryChangedSpy.wait());
847 QVERIFY(frameGeometryChangedSpy.count() == 0);
850 QCOMPARE(window->frameGeometry(), windowRect);
853void MoveResizeWindowTest::testResizeForVirtualKeyboardWithMaximize()
856 QVERIFY(surface !=
nullptr);
859 QVERIFY(shellSurface !=
nullptr);
868 QVERIFY(surfaceConfigureRequestedSpy.wait());
870 window->move(QPoint(100, 300));
873 QCOMPARE(window->frameGeometry(), QRect(100, 300, 500, 800));
874 window->setVirtualKeyboardGeometry(QRect(0, 100, 1280, 500));
875 QVERIFY(surfaceConfigureRequestedSpy.wait());
877 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last()[0].toInt());
879 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
880 QVERIFY(frameGeometryChangedSpy.wait());
881 QCOMPARE(window->frameGeometry(), QRect(100, 0, 500, 100));
883 window->setMaximize(
true,
true);
884 QVERIFY(surfaceConfigureRequestedSpy.wait());
885 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last()[0].toInt());
886 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
887 QVERIFY(frameGeometryChangedSpy.wait());
888 QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
890 window->setVirtualKeyboardGeometry(QRect());
891 QVERIFY(!surfaceConfigureRequestedSpy.wait(10));
894 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
895 QVERIFY(!frameGeometryChangedSpy.wait(10));
898 QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
901void MoveResizeWindowTest::testResizeForVirtualKeyboardWithFullScreen()
904 QVERIFY(surface !=
nullptr);
907 QVERIFY(shellSurface !=
nullptr);
916 QVERIFY(surfaceConfigureRequestedSpy.wait());
918 window->move(QPoint(100, 300));
921 QCOMPARE(window->frameGeometry(), QRect(100, 300, 500, 800));
922 window->setVirtualKeyboardGeometry(QRect(0, 100, 1280, 500));
923 QVERIFY(surfaceConfigureRequestedSpy.wait());
925 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last()[0].toInt());
927 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
928 QVERIFY(frameGeometryChangedSpy.wait());
929 QCOMPARE(window->frameGeometry(), QRect(100, 0, 500, 100));
931 window->setFullScreen(
true);
932 QVERIFY(surfaceConfigureRequestedSpy.wait());
933 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last()[0].toInt());
934 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
935 QVERIFY(frameGeometryChangedSpy.wait());
936 QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
938 window->setVirtualKeyboardGeometry(QRect());
939 QVERIFY(!surfaceConfigureRequestedSpy.wait(10));
942 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
943 QVERIFY(!frameGeometryChangedSpy.wait(10));
945 QCOMPARE(window->frameGeometry(), QRect(0, 0, 1280, 1024));
948void MoveResizeWindowTest::testDestroyMoveClient()
955 QVERIFY(surface !=
nullptr);
957 QVERIFY(shellSurface !=
nullptr);
965 QCOMPARE(
workspace()->moveResizeWindow(),
nullptr);
966 QCOMPARE(window->isInteractiveMove(),
false);
967 QCOMPARE(window->isInteractiveResize(),
false);
969 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
970 QCOMPARE(
workspace()->moveResizeWindow(), window);
971 QCOMPARE(window->isInteractiveMove(),
true);
972 QCOMPARE(window->isInteractiveResize(),
false);
975 shellSurface.reset();
978 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
979 QCOMPARE(
workspace()->moveResizeWindow(),
nullptr);
982void MoveResizeWindowTest::testDestroyResizeClient()
989 QVERIFY(surface !=
nullptr);
991 QVERIFY(shellSurface !=
nullptr);
999 QCOMPARE(
workspace()->moveResizeWindow(),
nullptr);
1000 QCOMPARE(window->isInteractiveMove(),
false);
1001 QCOMPARE(window->isInteractiveResize(),
false);
1003 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
1004 QCOMPARE(
workspace()->moveResizeWindow(), window);
1005 QCOMPARE(window->isInteractiveMove(),
false);
1006 QCOMPARE(window->isInteractiveResize(),
true);
1009 shellSurface.reset();
1012 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
1013 QCOMPARE(
workspace()->moveResizeWindow(),
nullptr);
1016void MoveResizeWindowTest::testCancelInteractiveMoveResize_data()
1018 QTest::addColumn<QuickTileMode>(
"quickTileMode");
1019 QTest::addColumn<MaximizeMode>(
"maximizeMode");
1030void MoveResizeWindowTest::testCancelInteractiveMoveResize()
1037 QVERIFY(surface !=
nullptr);
1039 QVERIFY(shellSurface !=
nullptr);
1044 QFETCH(QuickTileMode, quickTileMode);
1049 window->setQuickTileMode(quickTileMode,
true);
1051 QCOMPARE(window->quickTileMode(), quickTileMode);
1052 QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
1056 QVERIFY(surfaceConfigureRequestedSpy.wait());
1057 Test::render(surface.get(), toplevelConfigureRequestedSpy.last().first().toSize(), Qt::blue);
1059 const QRectF geometry = window->moveResizeGeometry();
1060 const QRectF geometryRestore = window->geometryRestore();
1066 QCOMPARE(
workspace()->moveResizeWindow(),
nullptr);
1067 QCOMPARE(window->isInteractiveMove(),
false);
1068 QCOMPARE(window->isInteractiveResize(),
false);
1070 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
1071 QCOMPARE(
workspace()->moveResizeWindow(), window);
1072 QCOMPARE(window->isInteractiveMove(),
false);
1073 QCOMPARE(window->isInteractiveResize(),
true);
1076 QCOMPARE(window->quickTileMode(), QuickTileMode());
1080 window->keyPressEvent(Qt::Key::Key_Escape);
1081 QCOMPARE(window->moveResizeGeometry(), geometry);
1082 QCOMPARE(window->quickTileMode(), quickTileMode);
1083 QCOMPARE(window->requestedMaximizeMode(), maximizeMode);
1084 QCOMPARE(window->geometryRestore(), geometryRestore);
1089#include "move_resize_window_test.moc"
Xcb::Atom kde_screen_edge_show
void placeCentered(Window *c, const QRectF &area, PlacementPolicy next=PlacementUnknown)
void configureRequested(quint32 serial, const QSize &size)
void configureRequested(quint32 serial)
void configureRequested(const QSize &size, KWin::Test::XdgToplevel::States states)
void interactiveMoveResizeStarted()
void interactiveMoveResizeStepped(const QRectF &geometry)
void interactiveMoveResizeFinished()
void moveResizedChanged()
void frameGeometryChanged(const QRectF &oldGeometry)
void windowHidden(KWin::Window *window)
Placement * placement() const
static Workspace * self()
void windowAdded(KWin::Window *)
void slotWindowMoveDown()
void slotWindowMoveRight()
QList< Output * > outputs() const
void setActiveOutput(Output *output)
#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())
KWayland::Client::Compositor * waylandCompositor()
void render(KWayland::Client::Surface *surface, const QSize &size, const QColor &color, const QImage::Format &format=QImage::Format_ARGB32_Premultiplied)
KWayland::Client::Seat * waylandSeat()
LayerSurfaceV1 * createLayerSurfaceV1(KWayland::Client::Surface *surface, const QString &scope, KWayland::Client::Output *output=nullptr, LayerShellV1::layer layer=LayerShellV1::layer_top)
Window * waitForWaylandWindowShown(int timeout=5000)
void pointerButtonPressed(quint32 button, quint32 time)
XcbConnectionPtr createX11Connection()
void pointerMotion(const QPointF &position, quint32 time)
std::unique_ptr< KWayland::Client::Surface > createSurface()
void pointerMotionRelative(const QPointF &delta, quint32 time)
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
bool waitForWaylandPointer()
KWayland::Client::ConnectionThread * waylandConnection()
void pointerButtonReleased(quint32 button, quint32 time)
std::unique_ptr< xcb_connection_t, XcbConnectionDeleter > XcbConnectionPtr
bool waitForWindowClosed(Window *window)
KWIN_EXPORT xcb_window_t rootWindow()
@ MaximizeVertical
The window is maximized vertically.
@ MaximizeRestore
The window is not maximized in any direction.
@ MaximizeFull
Equal to MaximizeVertical | MaximizeHorizontal.
WaylandServer * waylandServer()
InputRedirection * input()
KWIN_EXPORT Atoms * atoms