File indexing completed on 2024-05-05 17:36:03

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 = [&timestamp](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"