File indexing completed on 2024-11-10 04:56:09

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