From 615cd352fbc59b2851d5ff7748013749fa5227a1 Mon Sep 17 00:00:00 2001 From: Xaver Hugl Date: Fri, 27 May 2022 17:26:24 +0200 Subject: [PATCH] add autotest for touchscreen gestures --- autotests/integration/touch_input_test.cpp | 68 ++++++++++++++++++++++ src/globalshortcuts.cpp | 14 +++++ src/globalshortcuts.h | 1 + src/input.cpp | 5 ++ src/input.h | 1 + 5 files changed, 89 insertions(+) diff --git a/autotests/integration/touch_input_test.cpp b/autotests/integration/touch_input_test.cpp index 45ddf833ee..1b3eb93405 100644 --- a/autotests/integration/touch_input_test.cpp +++ b/autotests/integration/touch_input_test.cpp @@ -41,6 +41,7 @@ private Q_SLOTS: void testTouchMouseAction(); void testTouchPointCount(); void testUpdateFocusOnDecorationDestroy(); + void testGestureDetection(); private: Window *showWindow(bool decorated = false); @@ -369,6 +370,73 @@ void TouchInputTest::testUpdateFocusOnDecorationDestroy() QVERIFY(Test::waitForWindowDestroyed(window)); } +void TouchInputTest::testGestureDetection() +{ + bool callbackTriggered = false; + const auto callback = [&callbackTriggered](float progress) { + Q_UNUSED(progress); + callbackTriggered = true; + qWarning() << "progress callback!" << progress; + }; + QAction action; + input()->forceRegisterTouchscreenSwipeShortcut(SwipeDirection::Right, 3, &action, callback); + + // verify that gestures are detected + + quint32 timestamp = 1; + Test::touchDown(0, QPointF(500, 125), timestamp++); + Test::touchDown(1, QPointF(500, 125), timestamp++); + Test::touchDown(2, QPointF(500, 125), timestamp++); + + Test::touchMotion(0, QPointF(100, 125), timestamp++); + QVERIFY(callbackTriggered); + + // verify that gestures are canceled properly + QSignalSpy gestureCancelled(&action, &QAction::triggered); + QVERIFY(gestureCancelled.isValid()); + Test::touchUp(0, timestamp++); + QVERIFY(gestureCancelled.wait()); + + Test::touchUp(1, timestamp++); + Test::touchUp(2, timestamp++); + + callbackTriggered = false; + + // verify that touch points too far apart don't trigger a gesture + Test::touchDown(0, QPointF(125, 125), timestamp++); + Test::touchDown(1, QPointF(10000, 125), timestamp++); + Test::touchDown(2, QPointF(125, 125), timestamp++); + QVERIFY(!callbackTriggered); + + Test::touchUp(0, timestamp++); + Test::touchUp(1, timestamp++); + Test::touchUp(2, timestamp++); + + // verify that touch points triggered too slow don't trigger a gesture + Test::touchDown(0, QPointF(125, 125), timestamp++); + timestamp += 1000; + Test::touchDown(1, QPointF(125, 125), timestamp++); + Test::touchDown(2, QPointF(125, 125), timestamp++); + QVERIFY(!callbackTriggered); + + Test::touchUp(0, timestamp++); + Test::touchUp(1, timestamp++); + Test::touchUp(2, timestamp++); + + // verify that after a gesture has been canceled but never initiated, gestures still work + Test::touchDown(0, QPointF(500, 125), timestamp++); + Test::touchDown(1, QPointF(500, 125), timestamp++); + Test::touchDown(2, QPointF(500, 125), timestamp++); + + Test::touchMotion(0, QPointF(100, 125), timestamp++); + Test::touchMotion(1, QPointF(100, 125), timestamp++); + Test::touchMotion(2, QPointF(100, 125), timestamp++); + QVERIFY(callbackTriggered); + + Test::touchUp(0, timestamp++); + Test::touchUp(1, timestamp++); + Test::touchUp(2, timestamp++); +} } WAYLANDTEST_MAIN(KWin::TouchInputTest) diff --git a/src/globalshortcuts.cpp b/src/globalshortcuts.cpp index 166e26db69..229be6987c 100644 --- a/src/globalshortcuts.cpp +++ b/src/globalshortcuts.cpp @@ -196,6 +196,20 @@ void GlobalShortcutsManager::registerTouchscreenSwipe(QAction *action, std::func addIfNotExists(GlobalShortcut(RealtimeFeedbackSwipeShortcut{DeviceType::Touchscreen, direction, progressCallback, fingerCount}, action), DeviceType::Touchscreen); } +void GlobalShortcutsManager::forceRegisterTouchscreenSwipe(QAction *action, std::function progressCallback, SwipeDirection direction, uint fingerCount) +{ + GlobalShortcut shortcut{RealtimeFeedbackSwipeShortcut{DeviceType::Touchscreen, direction, progressCallback, fingerCount}, action}; + const auto it = std::find_if(m_shortcuts.begin(), m_shortcuts.end(), [&shortcut](const auto &s) { + return shortcut.shortcut() == s.shortcut(); + }); + if (it != m_shortcuts.end()) { + m_shortcuts.erase(it); + } + m_touchscreenGestureRecognizer->registerSwipeGesture(shortcut.swipeGesture()); + connect(shortcut.action(), &QAction::destroyed, this, &GlobalShortcutsManager::objectDeleted); + m_shortcuts.push_back(std::move(shortcut)); +} + bool GlobalShortcutsManager::processKey(Qt::KeyboardModifiers mods, int keyQt) { if (m_kglobalAccelInterface) { diff --git a/src/globalshortcuts.h b/src/globalshortcuts.h index 0984e5a4c2..3f6b3ba08c 100644 --- a/src/globalshortcuts.h +++ b/src/globalshortcuts.h @@ -73,6 +73,7 @@ public: void registerRealtimeTouchpadPinch(QAction *onUp, std::function progressCallback, PinchDirection direction, uint fingerCount = 4); void registerTouchscreenSwipe(QAction *action, std::function progressCallback, SwipeDirection direction, uint fingerCount); + void forceRegisterTouchscreenSwipe(QAction *action, std::function progressCallback, SwipeDirection direction, uint fingerCount); /** * @brief Processes a key event to decide whether a shortcut needs to be triggered. diff --git a/src/input.cpp b/src/input.cpp index e6ae775612..3d0b817f2f 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -3262,6 +3262,11 @@ void InputRedirection::registerTouchscreenSwipeShortcut(SwipeDirection direction m_shortcuts->registerTouchscreenSwipe(action, progressCallback, direction, fingerCount); } +void InputRedirection::forceRegisterTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback) +{ + m_shortcuts->forceRegisterTouchscreenSwipe(action, progressCallback, direction, fingerCount); +} + void InputRedirection::warpPointer(const QPointF &pos) { m_pointer->warp(pos); diff --git a/src/input.h b/src/input.h index 892768de9d..980160d212 100644 --- a/src/input.h +++ b/src/input.h @@ -140,6 +140,7 @@ public: void registerTouchpadPinchShortcut(PinchDirection direction, uint fingerCount, QAction *action); void registerRealtimeTouchpadPinchShortcut(PinchDirection direction, uint fingerCount, QAction *onUp, std::function progressCallback); void registerTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback); + void forceRegisterTouchscreenSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function progressCallback); void registerGlobalAccel(KGlobalAccelInterface *interface); bool supportsPointerWarping() const;