24#include <KWayland/Client/compositor.h>
25#include <KWayland/Client/connection_thread.h>
26#include <KWayland/Client/keyboard.h>
27#include <KWayland/Client/pointer.h>
28#include <KWayland/Client/seat.h>
29#include <KWayland/Client/shm_pool.h>
30#include <KWayland/Client/surface.h>
32#include <KDecoration2/Decoration>
33#include <KDecoration2/DecorationSettings>
37#include <linux/input.h>
44static const QString s_socketName = QStringLiteral(
"wayland_test_kwin_decoration_input-0");
55 void testDoubleClickOnAllDesktops_data();
56 void testDoubleClickOnAllDesktops();
57 void testDoubleClickClose();
58 void testDoubleTap_data();
61 void testPressToMove_data();
62 void testPressToMove();
63 void testTapToMove_data();
65 void testResizeOutsideWindow_data();
66 void testResizeOutsideWindow();
67 void testModifierClickUnrestrictedMove_data();
68 void testModifierClickUnrestrictedMove();
69 void testModifierScrollOpacity_data();
70 void testModifierScrollOpacity();
71 void testTouchEvents();
72 void testTooltipDoesntEatKeyEvents();
75 std::tuple<Window *, std::unique_ptr<KWayland::Client::Surface>,
Test::XdgToplevel *> showWindow();
78#define MOTION(target) Test::pointerMotion(target, timestamp++)
80#define PRESS Test::pointerButtonPressed(BTN_LEFT, timestamp++)
82#define RELEASE Test::pointerButtonReleased(BTN_LEFT, timestamp++)
84std::tuple<Window *, std::unique_ptr<KWayland::Client::Surface>, Test::XdgToplevel *> DecorationInputTest::showWindow()
86#define VERIFY(statement) \
87 if (!QTest::qVerify((statement), #statement, "", __FILE__, __LINE__)) \
88 return {nullptr, nullptr, nullptr};
89#define COMPARE(actual, expected) \
90 if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__)) \
91 return {nullptr, nullptr, nullptr};
103 decoration->set_mode(Test::XdgToplevelDecorationV1::mode_server_side);
104 surface->commit(KWayland::Client::Surface::CommitFlag::None);
105 VERIFY(surfaceConfigureRequestedSpy.wait());
106 COMPARE(decorationConfigureRequestedSpy.last().at(0).value<Test::XdgToplevelDecorationV1::mode>(), Test::XdgToplevelDecorationV1::mode_server_side);
109 shellSurface->xdgSurface()->ack_configure(surfaceConfigureRequestedSpy.last().at(0).value<quint32>());
117 return {window, std::move(surface), shellSurface};
120void DecorationInputTest::initTestCase()
122 qRegisterMetaType<KWin::Window *>();
123 qRegisterMetaType<KWin::InternalWindow *>();
127 QRect(0, 0, 1280, 1024),
128 QRect(1280, 0, 1280, 1024),
132 KSharedConfig::Ptr config = KSharedConfig::openConfig(QString(), KConfig::SimpleConfig);
133 config->group(QStringLiteral(
"MouseBindings")).writeEntry(
"CommandTitlebarWheel", QStringLiteral(
"above/below"));
134 config->group(QStringLiteral(
"Windows")).writeEntry(
"TitlebarDoubleClickCommand", QStringLiteral(
"OnAllDesktops"));
135 config->group(QStringLiteral(
"Desktops")).writeEntry(
"Number", 2);
138 kwinApp()->setConfig(config);
141 QVERIFY(applicationStartedSpy.wait());
144 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024));
145 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024));
146 setenv(
"QT_QPA_PLATFORM",
"wayland",
true);
149void DecorationInputTest::init()
158void DecorationInputTest::cleanup()
163void DecorationInputTest::testAxis_data()
165 QTest::addColumn<QPoint>(
"decoPoint");
166 QTest::addColumn<Qt::WindowFrameSection>(
"expectedSection");
168 QTest::newRow(
"topLeft") << QPoint(0, 0) << Qt::TopLeftSection;
169 QTest::newRow(
"top") << QPoint(250, 0) << Qt::TopSection;
170 QTest::newRow(
"topRight") << QPoint(499, 0) << Qt::TopRightSection;
173void DecorationInputTest::testAxis()
175 static constexpr double oneTick = 15;
177 const auto [window, surface, shellSurface] = showWindow();
179 QVERIFY(window->isDecorated());
180 QVERIFY(!window->noBorder());
181 QCOMPARE(window->titlebarPosition(), Qt::TopEdge);
182 QVERIFY(!window->keepAbove());
183 QVERIFY(!window->keepBelow());
185 quint32 timestamp = 1;
186 MOTION(QPoint(window->frameGeometry().center().x(), window->frameMargins().top() / 2.0));
187 QVERIFY(
input()->pointer()->decoration());
188 QCOMPARE(
input()->pointer()->decoration()->decoration()->sectionUnderMouse(), Qt::TitleBarArea);
193 QVERIFY(window->keepBelow());
194 QVERIFY(!window->keepAbove());
196 QVERIFY(!window->keepBelow());
197 QVERIFY(!window->keepAbove());
199 QVERIFY(!window->keepBelow());
200 QVERIFY(window->keepAbove());
203 window->move(QPoint(0, 0));
204 QFETCH(QPoint, decoPoint);
206 QVERIFY(
input()->pointer()->decoration());
207 QCOMPARE(
input()->pointer()->decoration()->window(), window);
208 QTEST(
input()->pointer()->decoration()->decoration()->sectionUnderMouse(),
"expectedSection");
210 QVERIFY(!window->keepBelow());
211 QVERIFY(!window->keepAbove());
214void DecorationInputTest::testDoubleClickOnAllDesktops_data()
216 QTest::addColumn<QPoint>(
"decoPoint");
217 QTest::addColumn<Qt::WindowFrameSection>(
"expectedSection");
219 QTest::newRow(
"topLeft") << QPoint(0, 0) << Qt::TopLeftSection;
220 QTest::newRow(
"top") << QPoint(250, 0) << Qt::TopSection;
221 QTest::newRow(
"topRight") << QPoint(499, 0) << Qt::TopRightSection;
224void KWin::DecorationInputTest::testDoubleClickOnAllDesktops()
226 KConfigGroup group = kwinApp()->config()->group(QStringLiteral(
"Windows"));
227 group.writeEntry(
"TitlebarDoubleClickCommand", QStringLiteral(
"OnAllDesktops"));
231 const auto [window, surface, shellSurface] = showWindow();
233 QVERIFY(window->isDecorated());
234 QVERIFY(!window->noBorder());
235 QVERIFY(!window->isOnAllDesktops());
236 quint32 timestamp = 1;
237 MOTION(QPoint(window->frameGeometry().center().x(), window->frameMargins().top() / 2.0));
244 QVERIFY(window->isOnAllDesktops());
248 QVERIFY(window->isOnAllDesktops());
251 QVERIFY(!window->isOnAllDesktops());
254 window->move(QPoint(0, 0));
255 QFETCH(QPoint, decoPoint);
257 QVERIFY(
input()->pointer()->decoration());
258 QCOMPARE(
input()->pointer()->decoration()->window(), window);
259 QTEST(
input()->pointer()->decoration()->decoration()->sectionUnderMouse(),
"expectedSection");
263 QVERIFY(!window->isOnAllDesktops());
266 QVERIFY(window->isOnAllDesktops());
269void DecorationInputTest::testDoubleClickClose()
272 KConfigGroup group = kwinApp()->config()->group(QStringLiteral(
"Windows"));
273 group.writeEntry(
"TitlebarDoubleClickCommand", QStringLiteral(
"Close"));
277 auto [window, surface, shellSurface] = showWindow();
279 QVERIFY(window->isDecorated());
280 quint32 timestamp = 1;
281 MOTION(QPoint(window->frameGeometry().center().x(), window->frameMargins().top() / 2.0));
293 QVERIFY(closedSpy.wait());
296 QVERIFY(window->isDeleted());
300void DecorationInputTest::testDoubleTap_data()
302 QTest::addColumn<QPoint>(
"decoPoint");
303 QTest::addColumn<Qt::WindowFrameSection>(
"expectedSection");
305 QTest::newRow(
"topLeft") << QPoint(10, 10) << Qt::TopLeftSection;
306 QTest::newRow(
"top") << QPoint(260, 10) << Qt::TopSection;
307 QTest::newRow(
"topRight") << QPoint(509, 10) << Qt::TopRightSection;
310void KWin::DecorationInputTest::testDoubleTap()
312 KConfigGroup group = kwinApp()->config()->group(QStringLiteral(
"Windows"));
313 group.writeEntry(
"TitlebarDoubleClickCommand", QStringLiteral(
"OnAllDesktops"));
317 const auto [window, surface, shellSurface] = showWindow();
319 QVERIFY(window->isDecorated());
320 QVERIFY(!window->noBorder());
321 QVERIFY(!window->isOnAllDesktops());
322 quint32 timestamp = 1;
323 const QPoint tapPoint(window->frameGeometry().center().x(), window->frameMargins().top() / 2.0);
330 QVERIFY(window->isOnAllDesktops());
334 QVERIFY(window->isOnAllDesktops());
337 QVERIFY(!window->isOnAllDesktops());
343 window->move(QPoint(10, 10));
344 QFETCH(QPoint, decoPoint);
347 QVERIFY(
input()->touch()->decoration());
348 QCOMPARE(
input()->touch()->decoration()->window(), window);
349 QTEST(
input()->touch()->decoration()->decoration()->sectionUnderMouse(),
"expectedSection");
351 QVERIFY(!window->isOnAllDesktops());
354 QVERIFY(window->isOnAllDesktops());
357void DecorationInputTest::testHover()
359 const auto [window, surface, shellSurface] = showWindow();
361 QVERIFY(window->isDecorated());
362 QVERIFY(!window->noBorder());
365 window->move(QPoint(20, 0));
367 quint32 timestamp = 1;
368 MOTION(QPoint(window->frameGeometry().center().x(), window->frameMargins().top() / 2.0));
369 QCOMPARE(window->cursor(), CursorShape(Qt::ArrowCursor));
378 auto deviation = [hasBorders] {
379 return hasBorders ? -1 : 0;
382 MOTION(QPoint(window->frameGeometry().x(), 0));
384 MOTION(QPoint(window->frameGeometry().x() + window->frameGeometry().width() / 2, 0));
386 MOTION(QPoint(window->frameGeometry().x() + window->frameGeometry().width() - 1, 0));
388 MOTION(QPoint(window->frameGeometry().x() + window->frameGeometry().width() + deviation(), window->height() / 2));
390 MOTION(QPoint(window->frameGeometry().x() + window->frameGeometry().width() + deviation(), window->height() - 1));
392 MOTION(QPoint(window->frameGeometry().x() + window->frameGeometry().width() / 2, window->height() + deviation()));
394 MOTION(QPoint(window->frameGeometry().x(), window->height() + deviation()));
396 MOTION(QPoint(window->frameGeometry().x() - 1, window->height() / 2));
399 MOTION(window->frameGeometry().center());
400 QEXPECT_FAIL(
"",
"Cursor not set back on leave", Continue);
401 QCOMPARE(window->cursor(), CursorShape(Qt::ArrowCursor));
404void DecorationInputTest::testPressToMove_data()
406 QTest::addColumn<QPoint>(
"offset");
407 QTest::addColumn<QPoint>(
"offset2");
408 QTest::addColumn<QPoint>(
"offset3");
410 QTest::newRow(
"To right") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0);
411 QTest::newRow(
"To left") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0);
412 QTest::newRow(
"To bottom") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30);
413 QTest::newRow(
"To top") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30);
416void DecorationInputTest::testPressToMove()
418 const auto [window, surface, shellSurface] = showWindow();
420 QVERIFY(window->isDecorated());
421 QVERIFY(!window->noBorder());
422 window->move(
workspace()->activeOutput()->geometry().center() - QPoint(window->width() / 2, window->height() / 2));
426 quint32 timestamp = 1;
427 MOTION(QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0));
428 QCOMPARE(window->cursor(), CursorShape(Qt::ArrowCursor));
431 QVERIFY(!window->isInteractiveMove());
432 QFETCH(QPoint, offset);
433 MOTION(QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0) + offset);
434 const QPointF oldPos = window->pos();
435 QVERIFY(window->isInteractiveMove());
436 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
439 QTRY_VERIFY(!window->isInteractiveMove());
440 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
441 QEXPECT_FAIL(
"",
"Just trigger move doesn't move the window", Continue);
442 QCOMPARE(window->pos(), oldPos + offset);
446 QVERIFY(!window->isInteractiveMove());
447 QFETCH(QPoint, offset2);
448 MOTION(QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0) + offset2);
449 QVERIFY(window->isInteractiveMove());
450 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 2);
451 QFETCH(QPoint, offset3);
452 MOTION(QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0) + offset3);
455 QTRY_VERIFY(!window->isInteractiveMove());
456 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 2);
458 QCOMPARE(window->pos(), oldPos + offset2 + offset3);
461void DecorationInputTest::testTapToMove_data()
463 QTest::addColumn<QPoint>(
"offset");
464 QTest::addColumn<QPoint>(
"offset2");
465 QTest::addColumn<QPoint>(
"offset3");
467 QTest::newRow(
"To right") << QPoint(10, 0) << QPoint(20, 0) << QPoint(30, 0);
468 QTest::newRow(
"To left") << QPoint(-10, 0) << QPoint(-20, 0) << QPoint(-30, 0);
469 QTest::newRow(
"To bottom") << QPoint(0, 10) << QPoint(0, 20) << QPoint(0, 30);
470 QTest::newRow(
"To top") << QPoint(0, -10) << QPoint(0, -20) << QPoint(0, -30);
473void DecorationInputTest::testTapToMove()
475 const auto [window, surface, shellSurface] = showWindow();
477 QVERIFY(window->isDecorated());
478 QVERIFY(!window->noBorder());
479 window->move(
workspace()->activeOutput()->geometry().center() - QPoint(window->width() / 2, window->height() / 2));
483 quint32 timestamp = 1;
484 QPoint p = QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0);
487 QVERIFY(!window->isInteractiveMove());
488 QFETCH(QPoint, offset);
489 QCOMPARE(
input()->touch()->decorationPressId(), 0);
491 const QPointF oldPos = window->pos();
492 QVERIFY(window->isInteractiveMove());
493 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 1);
496 QTRY_VERIFY(!window->isInteractiveMove());
497 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 1);
498 QEXPECT_FAIL(
"",
"Just trigger move doesn't move the window", Continue);
499 QCOMPARE(window->pos(), oldPos + offset);
503 QCOMPARE(
input()->touch()->decorationPressId(), 1);
504 QVERIFY(!window->isInteractiveMove());
505 QFETCH(QPoint, offset2);
506 Test::touchMotion(1, QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0) + offset2, timestamp++);
507 QVERIFY(window->isInteractiveMove());
508 QCOMPARE(interactiveMoveResizeStartedSpy.count(), 2);
509 QFETCH(QPoint, offset3);
510 Test::touchMotion(1, QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0) + offset3, timestamp++);
513 QTRY_VERIFY(!window->isInteractiveMove());
514 QCOMPARE(interactiveMoveResizeFinishedSpy.count(), 2);
516 QCOMPARE(window->pos(), oldPos + offset2 + offset3);
519void DecorationInputTest::testResizeOutsideWindow_data()
521 QTest::addColumn<Qt::Edge>(
"edge");
522 QTest::addColumn<Qt::CursorShape>(
"expectedCursor");
524 QTest::newRow(
"left") << Qt::LeftEdge << Qt::SizeHorCursor;
525 QTest::newRow(
"right") << Qt::RightEdge << Qt::SizeHorCursor;
526 QTest::newRow(
"bottom") << Qt::BottomEdge << Qt::SizeVerCursor;
529void DecorationInputTest::testResizeOutsideWindow()
534 kwinApp()->config()->group(QStringLiteral(
"org.kde.kdecoration2")).writeEntry(
"BorderSize", QStringLiteral(
"None"));
535 kwinApp()->config()->sync();
539 const auto [window, surface, shellSurface] = showWindow();
541 QVERIFY(window->isDecorated());
542 QVERIFY(!window->noBorder());
543 window->move(
workspace()->activeOutput()->geometry().center() - QPoint(window->width() / 2, window->height() / 2));
547 quint32 timestamp = 1;
548 QFETCH(Qt::Edge, edge);
551 MOTION(QPoint(window->frameGeometry().x() - 1, window->frameGeometry().center().y()));
554 MOTION(QPoint(window->frameGeometry().x() + window->frameGeometry().width() + 1, window->frameGeometry().center().y()));
557 MOTION(QPoint(window->frameGeometry().center().x(), window->frameGeometry().y() + window->frameGeometry().height() + 1));
566 QVERIFY(!window->isInteractiveResize());
567 QVERIFY(interactiveMoveResizeStartedSpy.wait());
568 QVERIFY(window->isInteractiveResize());
571 QVERIFY(!window->isInteractiveResize());
574void DecorationInputTest::testModifierClickUnrestrictedMove_data()
576 QTest::addColumn<int>(
"modifierKey");
577 QTest::addColumn<int>(
"mouseButton");
578 QTest::addColumn<QString>(
"modKey");
579 QTest::addColumn<bool>(
"capsLock");
581 const QString alt = QStringLiteral(
"Alt");
582 const QString meta = QStringLiteral(
"Meta");
584 QTest::newRow(
"Left Alt + Left Click") << KEY_LEFTALT << BTN_LEFT << alt <<
false;
585 QTest::newRow(
"Left Alt + Right Click") << KEY_LEFTALT << BTN_RIGHT << alt <<
false;
586 QTest::newRow(
"Left Alt + Middle Click") << KEY_LEFTALT << BTN_MIDDLE << alt <<
false;
587 QTest::newRow(
"Right Alt + Left Click") << KEY_RIGHTALT << BTN_LEFT << alt <<
false;
588 QTest::newRow(
"Right Alt + Right Click") << KEY_RIGHTALT << BTN_RIGHT << alt <<
false;
589 QTest::newRow(
"Right Alt + Middle Click") << KEY_RIGHTALT << BTN_MIDDLE << alt <<
false;
591 QTest::newRow(
"Left Meta + Left Click") << KEY_LEFTMETA << BTN_LEFT << meta <<
false;
592 QTest::newRow(
"Left Meta + Right Click") << KEY_LEFTMETA << BTN_RIGHT << meta <<
false;
593 QTest::newRow(
"Left Meta + Middle Click") << KEY_LEFTMETA << BTN_MIDDLE << meta <<
false;
594 QTest::newRow(
"Right Meta + Left Click") << KEY_RIGHTMETA << BTN_LEFT << meta <<
false;
595 QTest::newRow(
"Right Meta + Right Click") << KEY_RIGHTMETA << BTN_RIGHT << meta <<
false;
596 QTest::newRow(
"Right Meta + Middle Click") << KEY_RIGHTMETA << BTN_MIDDLE << meta <<
false;
599 QTest::newRow(
"Left Alt + Left Click/CapsLock") << KEY_LEFTALT << BTN_LEFT << alt <<
true;
600 QTest::newRow(
"Left Alt + Right Click/CapsLock") << KEY_LEFTALT << BTN_RIGHT << alt <<
true;
601 QTest::newRow(
"Left Alt + Middle Click/CapsLock") << KEY_LEFTALT << BTN_MIDDLE << alt <<
true;
602 QTest::newRow(
"Right Alt + Left Click/CapsLock") << KEY_RIGHTALT << BTN_LEFT << alt <<
true;
603 QTest::newRow(
"Right Alt + Right Click/CapsLock") << KEY_RIGHTALT << BTN_RIGHT << alt <<
true;
604 QTest::newRow(
"Right Alt + Middle Click/CapsLock") << KEY_RIGHTALT << BTN_MIDDLE << alt <<
true;
606 QTest::newRow(
"Left Meta + Left Click/CapsLock") << KEY_LEFTMETA << BTN_LEFT << meta <<
true;
607 QTest::newRow(
"Left Meta + Right Click/CapsLock") << KEY_LEFTMETA << BTN_RIGHT << meta <<
true;
608 QTest::newRow(
"Left Meta + Middle Click/CapsLock") << KEY_LEFTMETA << BTN_MIDDLE << meta <<
true;
609 QTest::newRow(
"Right Meta + Left Click/CapsLock") << KEY_RIGHTMETA << BTN_LEFT << meta <<
true;
610 QTest::newRow(
"Right Meta + Right Click/CapsLock") << KEY_RIGHTMETA << BTN_RIGHT << meta <<
true;
611 QTest::newRow(
"Right Meta + Middle Click/CapsLock") << KEY_RIGHTMETA << BTN_MIDDLE << meta <<
true;
614void DecorationInputTest::testModifierClickUnrestrictedMove()
619 QFETCH(QString, modKey);
620 KConfigGroup group = kwinApp()->config()->group(QStringLiteral(
"MouseBindings"));
621 group.writeEntry(
"CommandAllKey", modKey);
622 group.writeEntry(
"CommandAll1",
"Move");
623 group.writeEntry(
"CommandAll2",
"Move");
624 group.writeEntry(
"CommandAll3",
"Move");
633 const auto [window, surface, shellSurface] = showWindow();
635 QVERIFY(window->isDecorated());
636 QVERIFY(!window->noBorder());
637 window->move(
workspace()->activeOutput()->geometry().center() - QPoint(window->width() / 2, window->height() / 2));
639 input()->
pointer()->
warp(QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0));
642 quint32 timestamp = 1;
643 QFETCH(
bool, capsLock);
647 QFETCH(
int, modifierKey);
648 QFETCH(
int, mouseButton);
650 QVERIFY(!window->isInteractiveMove());
652 QVERIFY(window->isInteractiveMove());
655 QVERIFY(window->isInteractiveMove());
658 QVERIFY(!window->isInteractiveMove());
664void DecorationInputTest::testModifierScrollOpacity_data()
666 QTest::addColumn<int>(
"modifierKey");
667 QTest::addColumn<QString>(
"modKey");
668 QTest::addColumn<bool>(
"capsLock");
670 const QString alt = QStringLiteral(
"Alt");
671 const QString meta = QStringLiteral(
"Meta");
673 QTest::newRow(
"Left Alt") << KEY_LEFTALT << alt <<
false;
674 QTest::newRow(
"Right Alt") << KEY_RIGHTALT << alt <<
false;
675 QTest::newRow(
"Left Meta") << KEY_LEFTMETA << meta <<
false;
676 QTest::newRow(
"Right Meta") << KEY_RIGHTMETA << meta <<
false;
677 QTest::newRow(
"Left Alt/CapsLock") << KEY_LEFTALT << alt <<
true;
678 QTest::newRow(
"Right Alt/CapsLock") << KEY_RIGHTALT << alt <<
true;
679 QTest::newRow(
"Left Meta/CapsLock") << KEY_LEFTMETA << meta <<
true;
680 QTest::newRow(
"Right Meta/CapsLock") << KEY_RIGHTMETA << meta <<
true;
683void DecorationInputTest::testModifierScrollOpacity()
688 QFETCH(QString, modKey);
689 KConfigGroup group = kwinApp()->config()->group(QStringLiteral(
"MouseBindings"));
690 group.writeEntry(
"CommandAllKey", modKey);
691 group.writeEntry(
"CommandAllWheel",
"change opacity");
695 const auto [window, surface, shellSurface] = showWindow();
697 QVERIFY(window->isDecorated());
698 QVERIFY(!window->noBorder());
699 window->move(
workspace()->activeOutput()->geometry().center() - QPoint(window->width() / 2, window->height() / 2));
701 input()->
pointer()->
warp(QPoint(window->frameGeometry().center().x(), window->y() + window->frameMargins().top() / 2.0));
703 window->setOpacity(0.5);
704 QCOMPARE(window->opacity(), 0.5);
707 quint32 timestamp = 1;
708 QFETCH(
bool, capsLock);
712 QFETCH(
int, modifierKey);
715 QCOMPARE(window->opacity(), 0.6);
717 QCOMPARE(window->opacity(), 0.5);
736 if (event->type() == QEvent::HoverMove) {
738 }
else if (event->type() == QEvent::HoverLeave) {
749void DecorationInputTest::testTouchEvents()
753 const auto [window, surface, shellSurface] = showWindow();
755 QVERIFY(window->isDecorated());
756 QVERIFY(!window->noBorder());
759 window->decoration()->installEventFilter(&helper);
763 quint32 timestamp = 1;
764 const QPoint tapPoint(window->frameGeometry().center().x(), window->frameMargins().top() / 2.0);
766 QVERIFY(!
input()->touch()->decoration());
768 QVERIFY(
input()->touch()->decoration());
769 QCOMPARE(
input()->touch()->decoration()->decoration(), window->decoration());
770 QCOMPARE(hoverMoveSpy.count(), 1);
771 QCOMPARE(hoverLeaveSpy.count(), 0);
773 QCOMPARE(hoverMoveSpy.count(), 1);
774 QCOMPARE(hoverLeaveSpy.count(), 1);
776 QCOMPARE(window->isInteractiveMove(),
false);
780 QCOMPARE(hoverMoveSpy.count(), 2);
782 QCOMPARE(hoverMoveSpy.count(), 3);
783 QCOMPARE(hoverLeaveSpy.count(), 1);
785 QCOMPARE(hoverMoveSpy.count(), 3);
786 QCOMPARE(hoverLeaveSpy.count(), 2);
789void DecorationInputTest::testTooltipDoesntEatKeyEvents()
797 QSignalSpy enteredSpy(keyboard, &KWayland::Client::Keyboard::entered);
799 const auto [window, surface, shellSurface] = showWindow();
801 QVERIFY(window->isDecorated());
802 QVERIFY(!window->noBorder());
803 QVERIFY(enteredSpy.wait());
805 QSignalSpy keyEvent(keyboard, &KWayland::Client::Keyboard::keyChanged);
806 QVERIFY(keyEvent.isValid());
809 window->decoratedClient()->requestShowToolTip(QStringLiteral(
"test"));
811 QVERIFY(windowAddedSpy.wait());
812 InternalWindow *internal = windowAddedSpy.first().first().value<InternalWindow *>();
813 QVERIFY(internal->isInternal());
814 QVERIFY(internal->handle()->flags().testFlag(Qt::ToolTip));
817 quint32 timestamp = 0;
819 QVERIFY(keyEvent.wait());
821 QVERIFY(keyEvent.wait());
823 window->decoratedClient()->requestHideToolTip();
830#include "decoration_input_test.moc"
std::unique_ptr< KDecoration2::DecorationSettingsPrivate > settings(KDecoration2::DecorationSettings *parent) override
bool eventFilter(QObject *watched, QEvent *event) override
~EventHelper() override=default
Qt::KeyboardModifier commandAllModifier() const
void configureRequested(quint32 serial)
void configureRequested(QtWayland::zxdg_toplevel_decoration_v1::mode mode)
void interactiveMoveResizeStarted()
void interactiveMoveResizeFinished()
Decoration::DecorationBridge * decorationBridge() const
static Workspace * self()
void windowAdded(KWin::Window *)
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 keyboardKeyReleased(quint32 key, quint32 time)
void destroyWaylandConnection()
void setOutputConfig(const QList< QRect > &geometries)
void touchDown(qint32 id, const QPointF &pos, quint32 time)
void pointerAxisVertical(qreal delta, quint32 time, qint32 discreteDelta=0, InputRedirection::PointerAxisSource source=InputRedirection::PointerAxisSourceUnknown)
void keyboardKeyPressed(quint32 key, quint32 time)
bool setupWaylandConnection(AdditionalWaylandInterfaces flags=AdditionalWaylandInterfaces())
void touchMotion(qint32 id, const QPointF &pos, quint32 time)
KWayland::Client::Seat * waylandSeat()
void pointerButtonPressed(quint32 button, quint32 time)
QList< KWayland::Client::Output * > outputs
std::unique_ptr< KWayland::Client::Surface > createSurface()
XdgToplevel * createXdgToplevelSurface(KWayland::Client::Surface *surface, QObject *parent=nullptr)
XdgToplevelDecorationV1 * createXdgToplevelDecorationV1(XdgToplevel *toplevel, QObject *parent=nullptr)
bool waitForWaylandPointer()
void pointerButtonReleased(quint32 button, quint32 time)
void touchUp(qint32 id, quint32 time)
bool waitForWindowClosed(Window *window)
WaylandServer * waylandServer()
InputRedirection * input()