File indexing completed on 2025-03-23 13:48:08
0001 /* 0002 KWin - the KDE window manager 0003 This file is part of the KDE project. 0004 0005 SPDX-FileCopyrightText: 2016 Martin Gräßlin <mgraesslin@kde.org> 0006 0007 SPDX-License-Identifier: GPL-2.0-or-later 0008 */ 0009 #include "kwin_wayland_test.h" 0010 0011 #include "core/output.h" 0012 #include "core/outputbackend.h" 0013 #include "cursor.h" 0014 #include "keyboard_input.h" 0015 #include "pointer_input.h" 0016 #include "wayland_server.h" 0017 #include "window.h" 0018 #include "workspace.h" 0019 0020 #include <KWayland/Client/compositor.h> 0021 #include <KWayland/Client/keyboard.h> 0022 #include <KWayland/Client/pointer.h> 0023 #include <KWayland/Client/seat.h> 0024 #include <KWayland/Client/shm_pool.h> 0025 #include <KWayland/Client/surface.h> 0026 #include <KWayland/Client/touch.h> 0027 0028 #include <linux/input.h> 0029 0030 using namespace KWin; 0031 0032 static const QString s_socketName = QStringLiteral("wayland_test_kwin_window_selection-0"); 0033 0034 class TestWindowSelection : public QObject 0035 { 0036 Q_OBJECT 0037 private Q_SLOTS: 0038 void initTestCase(); 0039 void init(); 0040 void cleanup(); 0041 0042 void testSelectOnWindowPointer(); 0043 void testSelectOnWindowKeyboard_data(); 0044 void testSelectOnWindowKeyboard(); 0045 void testSelectOnWindowTouch(); 0046 void testCancelOnWindowPointer(); 0047 void testCancelOnWindowKeyboard(); 0048 0049 void testSelectPointPointer(); 0050 void testSelectPointTouch(); 0051 }; 0052 0053 void TestWindowSelection::initTestCase() 0054 { 0055 qRegisterMetaType<KWin::Window *>(); 0056 QSignalSpy applicationStartedSpy(kwinApp(), &Application::started); 0057 QVERIFY(waylandServer()->init(s_socketName)); 0058 QMetaObject::invokeMethod(kwinApp()->outputBackend(), "setVirtualOutputs", Qt::DirectConnection, Q_ARG(QVector<QRect>, QVector<QRect>() << QRect(0, 0, 1280, 1024) << QRect(1280, 0, 1280, 1024))); 0059 qputenv("XKB_DEFAULT_RULES", "evdev"); 0060 0061 kwinApp()->start(); 0062 QVERIFY(applicationStartedSpy.wait()); 0063 const auto outputs = workspace()->outputs(); 0064 QCOMPARE(outputs.count(), 2); 0065 QCOMPARE(outputs[0]->geometry(), QRect(0, 0, 1280, 1024)); 0066 QCOMPARE(outputs[1]->geometry(), QRect(1280, 0, 1280, 1024)); 0067 } 0068 0069 void TestWindowSelection::init() 0070 { 0071 QVERIFY(Test::setupWaylandConnection(Test::AdditionalWaylandInterface::Seat)); 0072 QVERIFY(Test::waitForWaylandPointer()); 0073 0074 workspace()->setActiveOutput(QPoint(640, 512)); 0075 KWin::Cursors::self()->mouse()->setPos(QPoint(640, 512)); 0076 } 0077 0078 void TestWindowSelection::cleanup() 0079 { 0080 Test::destroyWaylandConnection(); 0081 } 0082 0083 void TestWindowSelection::testSelectOnWindowPointer() 0084 { 0085 // this test verifies window selection through pointer works 0086 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0087 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0088 std::unique_ptr<KWayland::Client::Pointer> pointer(Test::waylandSeat()->createPointer()); 0089 std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard()); 0090 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered); 0091 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left); 0092 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered); 0093 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left); 0094 0095 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0096 QVERIFY(window); 0097 QVERIFY(keyboardEnteredSpy.wait()); 0098 KWin::Cursors::self()->mouse()->setPos(window->frameGeometry().center()); 0099 QCOMPARE(input()->pointer()->focus(), window); 0100 QVERIFY(pointerEnteredSpy.wait()); 0101 0102 Window *selectedWindow = nullptr; 0103 auto callback = [&selectedWindow](Window *t) { 0104 selectedWindow = t; 0105 }; 0106 0107 // start the interaction 0108 QCOMPARE(input()->isSelectingWindow(), false); 0109 kwinApp()->startInteractiveWindowSelection(callback); 0110 QCOMPARE(input()->isSelectingWindow(), true); 0111 QVERIFY(!selectedWindow); 0112 QCOMPARE(keyboardLeftSpy.count(), 0); 0113 QVERIFY(pointerLeftSpy.wait()); 0114 if (keyboardLeftSpy.isEmpty()) { 0115 QVERIFY(keyboardLeftSpy.wait()); 0116 } 0117 QCOMPARE(pointerLeftSpy.count(), 1); 0118 QCOMPARE(keyboardLeftSpy.count(), 1); 0119 0120 // simulate left button press 0121 quint32 timestamp = 0; 0122 Test::pointerButtonPressed(BTN_LEFT, timestamp++); 0123 // should not have ended the mode 0124 QCOMPARE(input()->isSelectingWindow(), true); 0125 QVERIFY(!selectedWindow); 0126 QVERIFY(!input()->pointer()->focus()); 0127 0128 // updating the pointer should not change anything 0129 input()->pointer()->update(); 0130 QVERIFY(!input()->pointer()->focus()); 0131 // updating keyboard should also not change 0132 input()->keyboard()->update(); 0133 0134 // perform a right button click 0135 Test::pointerButtonPressed(BTN_RIGHT, timestamp++); 0136 Test::pointerButtonReleased(BTN_RIGHT, timestamp++); 0137 // should not have ended the mode 0138 QCOMPARE(input()->isSelectingWindow(), true); 0139 QVERIFY(!selectedWindow); 0140 // now release 0141 Test::pointerButtonReleased(BTN_LEFT, timestamp++); 0142 QCOMPARE(input()->isSelectingWindow(), false); 0143 QCOMPARE(selectedWindow, window); 0144 QCOMPARE(input()->pointer()->focus(), window); 0145 // should give back keyboard and pointer 0146 QVERIFY(pointerEnteredSpy.wait()); 0147 if (keyboardEnteredSpy.count() != 2) { 0148 QVERIFY(keyboardEnteredSpy.wait()); 0149 } 0150 QCOMPARE(pointerLeftSpy.count(), 1); 0151 QCOMPARE(keyboardLeftSpy.count(), 1); 0152 QCOMPARE(pointerEnteredSpy.count(), 2); 0153 QCOMPARE(keyboardEnteredSpy.count(), 2); 0154 } 0155 0156 void TestWindowSelection::testSelectOnWindowKeyboard_data() 0157 { 0158 QTest::addColumn<qint32>("key"); 0159 0160 QTest::newRow("enter") << KEY_ENTER; 0161 QTest::newRow("keypad enter") << KEY_KPENTER; 0162 QTest::newRow("space") << KEY_SPACE; 0163 } 0164 0165 void TestWindowSelection::testSelectOnWindowKeyboard() 0166 { 0167 // this test verifies window selection through keyboard key 0168 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0169 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0170 std::unique_ptr<KWayland::Client::Pointer> pointer(Test::waylandSeat()->createPointer()); 0171 std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard()); 0172 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered); 0173 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left); 0174 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered); 0175 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left); 0176 0177 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0178 QVERIFY(window); 0179 QVERIFY(keyboardEnteredSpy.wait()); 0180 QVERIFY(!window->frameGeometry().contains(KWin::Cursors::self()->mouse()->pos())); 0181 0182 Window *selectedWindow = nullptr; 0183 auto callback = [&selectedWindow](Window *t) { 0184 selectedWindow = t; 0185 }; 0186 0187 // start the interaction 0188 QCOMPARE(input()->isSelectingWindow(), false); 0189 kwinApp()->startInteractiveWindowSelection(callback); 0190 QCOMPARE(input()->isSelectingWindow(), true); 0191 QVERIFY(!selectedWindow); 0192 QCOMPARE(keyboardLeftSpy.count(), 0); 0193 QVERIFY(keyboardLeftSpy.wait()); 0194 QCOMPARE(pointerLeftSpy.count(), 0); 0195 QCOMPARE(keyboardLeftSpy.count(), 1); 0196 0197 // simulate key press 0198 quint32 timestamp = 0; 0199 // move cursor through keys 0200 auto keyPress = [×tamp](qint32 key) { 0201 Test::keyboardKeyPressed(key, timestamp++); 0202 Test::keyboardKeyReleased(key, timestamp++); 0203 }; 0204 while (KWin::Cursors::self()->mouse()->pos().x() >= window->frameGeometry().x() + window->frameGeometry().width()) { 0205 keyPress(KEY_LEFT); 0206 } 0207 while (KWin::Cursors::self()->mouse()->pos().x() <= window->frameGeometry().x()) { 0208 keyPress(KEY_RIGHT); 0209 } 0210 while (KWin::Cursors::self()->mouse()->pos().y() <= window->frameGeometry().y()) { 0211 keyPress(KEY_DOWN); 0212 } 0213 while (KWin::Cursors::self()->mouse()->pos().y() >= window->frameGeometry().y() + window->frameGeometry().height()) { 0214 keyPress(KEY_UP); 0215 } 0216 QFETCH(qint32, key); 0217 Test::keyboardKeyPressed(key, timestamp++); 0218 QCOMPARE(input()->isSelectingWindow(), false); 0219 QCOMPARE(selectedWindow, window); 0220 QCOMPARE(input()->pointer()->focus(), window); 0221 // should give back keyboard and pointer 0222 QVERIFY(pointerEnteredSpy.wait()); 0223 if (keyboardEnteredSpy.count() != 2) { 0224 QVERIFY(keyboardEnteredSpy.wait()); 0225 } 0226 QCOMPARE(pointerLeftSpy.count(), 0); 0227 QCOMPARE(keyboardLeftSpy.count(), 1); 0228 QCOMPARE(pointerEnteredSpy.count(), 1); 0229 QCOMPARE(keyboardEnteredSpy.count(), 2); 0230 Test::keyboardKeyReleased(key, timestamp++); 0231 } 0232 0233 void TestWindowSelection::testSelectOnWindowTouch() 0234 { 0235 // this test verifies window selection through touch 0236 std::unique_ptr<KWayland::Client::Touch> touch(Test::waylandSeat()->createTouch()); 0237 QSignalSpy touchStartedSpy(touch.get(), &KWayland::Client::Touch::sequenceStarted); 0238 QSignalSpy touchCanceledSpy(touch.get(), &KWayland::Client::Touch::sequenceCanceled); 0239 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0240 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0241 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0242 QVERIFY(window); 0243 0244 Window *selectedWindow = nullptr; 0245 auto callback = [&selectedWindow](Window *t) { 0246 selectedWindow = t; 0247 }; 0248 0249 // start the interaction 0250 QCOMPARE(input()->isSelectingWindow(), false); 0251 kwinApp()->startInteractiveWindowSelection(callback); 0252 QCOMPARE(input()->isSelectingWindow(), true); 0253 QVERIFY(!selectedWindow); 0254 0255 // simulate touch down 0256 quint32 timestamp = 0; 0257 Test::touchDown(0, window->frameGeometry().center(), timestamp++); 0258 QVERIFY(!selectedWindow); 0259 Test::touchUp(0, timestamp++); 0260 QCOMPARE(input()->isSelectingWindow(), false); 0261 QCOMPARE(selectedWindow, window); 0262 0263 // with movement 0264 selectedWindow = nullptr; 0265 kwinApp()->startInteractiveWindowSelection(callback); 0266 Test::touchDown(0, window->frameGeometry().bottomRight() + QPoint(20, 20), timestamp++); 0267 QVERIFY(!selectedWindow); 0268 Test::touchMotion(0, window->frameGeometry().bottomRight() - QPoint(1, 1), timestamp++); 0269 QVERIFY(!selectedWindow); 0270 Test::touchUp(0, timestamp++); 0271 QCOMPARE(selectedWindow, window); 0272 QCOMPARE(input()->isSelectingWindow(), false); 0273 0274 // it cancels active touch sequence on the window 0275 Test::touchDown(0, window->frameGeometry().center(), timestamp++); 0276 QVERIFY(touchStartedSpy.wait()); 0277 selectedWindow = nullptr; 0278 kwinApp()->startInteractiveWindowSelection(callback); 0279 QCOMPARE(input()->isSelectingWindow(), true); 0280 QVERIFY(touchCanceledSpy.wait()); 0281 QVERIFY(!selectedWindow); 0282 // this touch up does not yet select the window, it was started prior to the selection 0283 Test::touchUp(0, timestamp++); 0284 QVERIFY(!selectedWindow); 0285 Test::touchDown(0, window->frameGeometry().center(), timestamp++); 0286 Test::touchUp(0, timestamp++); 0287 QCOMPARE(selectedWindow, window); 0288 QCOMPARE(input()->isSelectingWindow(), false); 0289 0290 QCOMPARE(touchStartedSpy.count(), 1); 0291 QCOMPARE(touchCanceledSpy.count(), 1); 0292 } 0293 0294 void TestWindowSelection::testCancelOnWindowPointer() 0295 { 0296 // this test verifies that window selection cancels through right button click 0297 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0298 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0299 std::unique_ptr<KWayland::Client::Pointer> pointer(Test::waylandSeat()->createPointer()); 0300 std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard()); 0301 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered); 0302 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left); 0303 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered); 0304 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left); 0305 0306 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0307 QVERIFY(window); 0308 QVERIFY(keyboardEnteredSpy.wait()); 0309 KWin::Cursors::self()->mouse()->setPos(window->frameGeometry().center()); 0310 QCOMPARE(input()->pointer()->focus(), window); 0311 QVERIFY(pointerEnteredSpy.wait()); 0312 0313 Window *selectedWindow = nullptr; 0314 auto callback = [&selectedWindow](Window *t) { 0315 selectedWindow = t; 0316 }; 0317 0318 // start the interaction 0319 QCOMPARE(input()->isSelectingWindow(), false); 0320 kwinApp()->startInteractiveWindowSelection(callback); 0321 QCOMPARE(input()->isSelectingWindow(), true); 0322 QVERIFY(!selectedWindow); 0323 QCOMPARE(keyboardLeftSpy.count(), 0); 0324 QVERIFY(pointerLeftSpy.wait()); 0325 if (keyboardLeftSpy.isEmpty()) { 0326 QVERIFY(keyboardLeftSpy.wait()); 0327 } 0328 QCOMPARE(pointerLeftSpy.count(), 1); 0329 QCOMPARE(keyboardLeftSpy.count(), 1); 0330 0331 // simulate left button press 0332 quint32 timestamp = 0; 0333 Test::pointerButtonPressed(BTN_RIGHT, timestamp++); 0334 Test::pointerButtonReleased(BTN_RIGHT, timestamp++); 0335 QCOMPARE(input()->isSelectingWindow(), false); 0336 QVERIFY(!selectedWindow); 0337 QCOMPARE(input()->pointer()->focus(), window); 0338 // should give back keyboard and pointer 0339 QVERIFY(pointerEnteredSpy.wait()); 0340 if (keyboardEnteredSpy.count() != 2) { 0341 QVERIFY(keyboardEnteredSpy.wait()); 0342 } 0343 QCOMPARE(pointerLeftSpy.count(), 1); 0344 QCOMPARE(keyboardLeftSpy.count(), 1); 0345 QCOMPARE(pointerEnteredSpy.count(), 2); 0346 QCOMPARE(keyboardEnteredSpy.count(), 2); 0347 } 0348 0349 void TestWindowSelection::testCancelOnWindowKeyboard() 0350 { 0351 // this test verifies that cancel window selection through escape key works 0352 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0353 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0354 std::unique_ptr<KWayland::Client::Pointer> pointer(Test::waylandSeat()->createPointer()); 0355 std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard()); 0356 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered); 0357 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left); 0358 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered); 0359 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left); 0360 0361 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0362 QVERIFY(window); 0363 QVERIFY(keyboardEnteredSpy.wait()); 0364 KWin::Cursors::self()->mouse()->setPos(window->frameGeometry().center()); 0365 QCOMPARE(input()->pointer()->focus(), window); 0366 QVERIFY(pointerEnteredSpy.wait()); 0367 0368 Window *selectedWindow = nullptr; 0369 auto callback = [&selectedWindow](Window *t) { 0370 selectedWindow = t; 0371 }; 0372 0373 // start the interaction 0374 QCOMPARE(input()->isSelectingWindow(), false); 0375 kwinApp()->startInteractiveWindowSelection(callback); 0376 QCOMPARE(input()->isSelectingWindow(), true); 0377 QVERIFY(!selectedWindow); 0378 QCOMPARE(keyboardLeftSpy.count(), 0); 0379 QVERIFY(pointerLeftSpy.wait()); 0380 if (keyboardLeftSpy.isEmpty()) { 0381 QVERIFY(keyboardLeftSpy.wait()); 0382 } 0383 QCOMPARE(pointerLeftSpy.count(), 1); 0384 QCOMPARE(keyboardLeftSpy.count(), 1); 0385 0386 // simulate left button press 0387 quint32 timestamp = 0; 0388 Test::keyboardKeyPressed(KEY_ESC, timestamp++); 0389 QCOMPARE(input()->isSelectingWindow(), false); 0390 QVERIFY(!selectedWindow); 0391 QCOMPARE(input()->pointer()->focus(), window); 0392 // should give back keyboard and pointer 0393 QVERIFY(pointerEnteredSpy.wait()); 0394 if (keyboardEnteredSpy.count() != 2) { 0395 QVERIFY(keyboardEnteredSpy.wait()); 0396 } 0397 QCOMPARE(pointerLeftSpy.count(), 1); 0398 QCOMPARE(keyboardLeftSpy.count(), 1); 0399 QCOMPARE(pointerEnteredSpy.count(), 2); 0400 QCOMPARE(keyboardEnteredSpy.count(), 2); 0401 Test::keyboardKeyReleased(KEY_ESC, timestamp++); 0402 } 0403 0404 void TestWindowSelection::testSelectPointPointer() 0405 { 0406 // this test verifies point selection through pointer works 0407 std::unique_ptr<KWayland::Client::Surface> surface(Test::createSurface()); 0408 std::unique_ptr<Test::XdgToplevel> shellSurface(Test::createXdgToplevelSurface(surface.get())); 0409 std::unique_ptr<KWayland::Client::Pointer> pointer(Test::waylandSeat()->createPointer()); 0410 std::unique_ptr<KWayland::Client::Keyboard> keyboard(Test::waylandSeat()->createKeyboard()); 0411 QSignalSpy pointerEnteredSpy(pointer.get(), &KWayland::Client::Pointer::entered); 0412 QSignalSpy pointerLeftSpy(pointer.get(), &KWayland::Client::Pointer::left); 0413 QSignalSpy keyboardEnteredSpy(keyboard.get(), &KWayland::Client::Keyboard::entered); 0414 QSignalSpy keyboardLeftSpy(keyboard.get(), &KWayland::Client::Keyboard::left); 0415 0416 auto window = Test::renderAndWaitForShown(surface.get(), QSize(100, 50), Qt::blue); 0417 QVERIFY(window); 0418 QVERIFY(keyboardEnteredSpy.wait()); 0419 KWin::Cursors::self()->mouse()->setPos(window->frameGeometry().center()); 0420 QCOMPARE(input()->pointer()->focus(), window); 0421 QVERIFY(pointerEnteredSpy.wait()); 0422 0423 QPoint point; 0424 auto callback = [&point](const QPoint &p) { 0425 point = p; 0426 }; 0427 0428 // start the interaction 0429 QCOMPARE(input()->isSelectingWindow(), false); 0430 kwinApp()->startInteractivePositionSelection(callback); 0431 QCOMPARE(input()->isSelectingWindow(), true); 0432 QCOMPARE(point, QPoint()); 0433 QCOMPARE(keyboardLeftSpy.count(), 0); 0434 QVERIFY(pointerLeftSpy.wait()); 0435 if (keyboardLeftSpy.isEmpty()) { 0436 QVERIFY(keyboardLeftSpy.wait()); 0437 } 0438 QCOMPARE(pointerLeftSpy.count(), 1); 0439 QCOMPARE(keyboardLeftSpy.count(), 1); 0440 0441 // trying again should not be allowed 0442 QPoint point2; 0443 kwinApp()->startInteractivePositionSelection([&point2](const QPoint &p) { 0444 point2 = p; 0445 }); 0446 QCOMPARE(point2, QPoint(-1, -1)); 0447 0448 // simulate left button press 0449 quint32 timestamp = 0; 0450 Test::pointerButtonPressed(BTN_LEFT, timestamp++); 0451 // should not have ended the mode 0452 QCOMPARE(input()->isSelectingWindow(), true); 0453 QCOMPARE(point, QPoint()); 0454 QVERIFY(!input()->pointer()->focus()); 0455 0456 // updating the pointer should not change anything 0457 input()->pointer()->update(); 0458 QVERIFY(!input()->pointer()->focus()); 0459 // updating keyboard should also not change 0460 input()->keyboard()->update(); 0461 0462 // perform a right button click 0463 Test::pointerButtonPressed(BTN_RIGHT, timestamp++); 0464 Test::pointerButtonReleased(BTN_RIGHT, timestamp++); 0465 // should not have ended the mode 0466 QCOMPARE(input()->isSelectingWindow(), true); 0467 QCOMPARE(point, QPoint()); 0468 // now release 0469 Test::pointerButtonReleased(BTN_LEFT, timestamp++); 0470 QCOMPARE(input()->isSelectingWindow(), false); 0471 QCOMPARE(point, input()->globalPointer().toPoint()); 0472 QCOMPARE(input()->pointer()->focus(), window); 0473 // should give back keyboard and pointer 0474 QVERIFY(pointerEnteredSpy.wait()); 0475 if (keyboardEnteredSpy.count() != 2) { 0476 QVERIFY(keyboardEnteredSpy.wait()); 0477 } 0478 QCOMPARE(pointerLeftSpy.count(), 1); 0479 QCOMPARE(keyboardLeftSpy.count(), 1); 0480 QCOMPARE(pointerEnteredSpy.count(), 2); 0481 QCOMPARE(keyboardEnteredSpy.count(), 2); 0482 } 0483 0484 void TestWindowSelection::testSelectPointTouch() 0485 { 0486 // this test verifies point selection through touch works 0487 QPoint point; 0488 auto callback = [&point](const QPoint &p) { 0489 point = p; 0490 }; 0491 0492 // start the interaction 0493 QCOMPARE(input()->isSelectingWindow(), false); 0494 kwinApp()->startInteractivePositionSelection(callback); 0495 QCOMPARE(input()->isSelectingWindow(), true); 0496 QCOMPARE(point, QPoint()); 0497 0498 // let's create multiple touch points 0499 quint32 timestamp = 0; 0500 Test::touchDown(0, QPointF(0, 1), timestamp++); 0501 QCOMPARE(input()->isSelectingWindow(), true); 0502 Test::touchDown(1, QPointF(10, 20), timestamp++); 0503 QCOMPARE(input()->isSelectingWindow(), true); 0504 Test::touchDown(2, QPointF(30, 40), timestamp++); 0505 QCOMPARE(input()->isSelectingWindow(), true); 0506 0507 // let's move our points 0508 Test::touchMotion(0, QPointF(5, 10), timestamp++); 0509 Test::touchMotion(2, QPointF(20, 25), timestamp++); 0510 Test::touchMotion(1, QPointF(25, 35), timestamp++); 0511 QCOMPARE(input()->isSelectingWindow(), true); 0512 Test::touchUp(0, timestamp++); 0513 QCOMPARE(input()->isSelectingWindow(), true); 0514 Test::touchUp(2, timestamp++); 0515 QCOMPARE(input()->isSelectingWindow(), true); 0516 Test::touchUp(1, timestamp++); 0517 QCOMPARE(input()->isSelectingWindow(), false); 0518 QCOMPARE(point, QPoint(25, 35)); 0519 } 0520 0521 WAYLANDTEST_MAIN(TestWindowSelection) 0522 #include "window_selection_test.moc"