diff --git a/autotests/test_gestures.cpp b/autotests/test_gestures.cpp index ebcd4d68f4..1900727f31 100644 --- a/autotests/test_gestures.cpp +++ b/autotests/test_gestures.cpp @@ -279,6 +279,7 @@ void GestureTest::testSwipeUpdateTrigger() SwipeGesture gesture; QFETCH(GestureDirection, direction); gesture.setDirection(direction); + gesture.setTriggerDelta(QSizeF(1, 1)); QSignalSpy triggeredSpy(&gesture, &SwipeGesture::triggered); QVERIFY(triggeredSpy.isValid()); diff --git a/src/effects/desktopgrid/desktopgrideffect.cpp b/src/effects/desktopgrid/desktopgrideffect.cpp index 095beac581..577f5816ea 100644 --- a/src/effects/desktopgrid/desktopgrideffect.cpp +++ b/src/effects/desktopgrid/desktopgrideffect.cpp @@ -62,6 +62,7 @@ DesktopGridEffect::DesktopGridEffect() }); effects->registerGesture(GestureDeviceType::Touchpad, GestureDirection::Up, 4, m_realtimeToggleAction, [this](qreal progress) { + progress = std::clamp(progress, 0.0, 1.0); if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == this) { switch (m_status) { case Status::Inactive: diff --git a/src/effects/overview/overvieweffect.cpp b/src/effects/overview/overvieweffect.cpp index 98f9e5a3ff..5a5cd6c2fe 100644 --- a/src/effects/overview/overvieweffect.cpp +++ b/src/effects/overview/overvieweffect.cpp @@ -52,6 +52,7 @@ OverviewEffect::OverviewEffect() }); auto progressCallback = [this](qreal progress) { + progress = std::clamp(progress, 0.0, 1.1); if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == this) { switch (m_status) { case Status::Inactive: diff --git a/src/effects/windowview/windowvieweffect.cpp b/src/effects/windowview/windowvieweffect.cpp index 749b609e3d..b07eaead12 100644 --- a/src/effects/windowview/windowvieweffect.cpp +++ b/src/effects/windowview/windowvieweffect.cpp @@ -111,6 +111,7 @@ WindowViewEffect::WindowViewEffect() }); const auto gestureCallback = [this](qreal progress) { + progress = std::clamp(progress, 0.0, 1.1); if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == this) { switch (m_status) { case Status::Inactive: diff --git a/src/gestures.cpp b/src/gestures.cpp index 3dc4956b22..ce7351e9af 100644 --- a/src/gestures.cpp +++ b/src/gestures.cpp @@ -47,17 +47,34 @@ qreal SwipeGesture::getTriggerProgress(const QSizeF &delta) const return 1.0; } - if (m_direction.testFlag(GestureDirection::DirectionlessSwipe)) { - return std::min(std::hypot(delta.width(), delta.height()) / m_triggerDelta.width(), 1.0); + qreal progress = 0.0; + + if (m_direction & GestureDirection::Up) { + qreal candidate = -delta.height() / m_triggerDelta.height(); + if (candidate > progress) { + progress = candidate; + } + } + if (m_direction & GestureDirection::Down) { + qreal candidate = delta.height() / m_triggerDelta.height(); + if (candidate > progress) { + progress = candidate; + } + } + if (m_direction & GestureDirection::Left) { + qreal candidate = -delta.width() / m_triggerDelta.width(); + if (candidate > progress) { + progress = candidate; + } + } + if (m_direction & GestureDirection::Right) { + qreal candidate = delta.width() / m_triggerDelta.width(); + if (candidate > progress) { + progress = candidate; + } } - if (m_direction & GestureDirection::VerticalAxis) { - return std::min(std::abs(delta.height()) / std::abs(m_triggerDelta.height()), 1.0); - } else if (m_direction & GestureDirection::HorizontalAxis) { - return std::min(std::abs(delta.width()) / std::abs(m_triggerDelta.width()), 1.0); - } - - return 1.0; + return std::clamp(progress, 0.0, 1.0); } bool SwipeGesture::triggerDeltaReached(const QSizeF &delta) const @@ -167,13 +184,12 @@ int GestureRecognizer::startSwipeGesture(uint fingerCount, const QPointF &startP } // Only add gestures who's direction aligns with current swipe axis - if (gesture->direction().testFlag(GestureDirection::DirectionlessSwipe)) { - } else if (gesture->direction() & GestureDirection::VerticalAxis) { - if (m_currentSwipeAxis == Axis::Horizontal) { + if (m_currentSwipeAxis == Axis::Vertical) { + if (!(gesture->direction() & (GestureDirection::Up | GestureDirection::Down))) { continue; } - } else if (gesture->direction() & GestureDirection::HorizontalAxis) { - if (m_currentSwipeAxis == Axis::Vertical) { + } else if (m_currentSwipeAxis == Axis::Horizontal) { + if (!(gesture->direction() & (GestureDirection::Left | GestureDirection::Right))) { continue; } } @@ -250,36 +266,9 @@ void GestureRecognizer::updateSwipeGesture(const QSizeF &delta) Q_EMIT g->triggerProgress(g->getTriggerProgress(m_currentDelta)); Q_EMIT g->semanticProgress(g->getSemanticProgress(m_currentDelta), g->direction()); Q_EMIT g->pixelDelta(m_currentDelta, g->direction()); - Q_EMIT g->semanticDelta(g->getSemanticDelta(m_currentDelta), g->direction()); - if (!g->direction().testFlag(GestureDirection::DirectionlessSwipe)) { - Q_EMIT g->semanticProgressAxis(g->getSemanticAxisProgress(m_currentDelta), g->direction()); - } - Q_EMIT g->swipePixelVector(QVector2D(m_currentDelta.width(), m_currentDelta.height())); } } -bool GestureRecognizer::mutuallyExclusive(GestureDirections currentDir, GestureDirections gestureDir) -{ - if (currentDir == gestureDir) { - return false; - } - if (gestureDir.testFlag(GestureDirection::DirectionlessSwipe)) { - return false; - } - - if (currentDir & GestureDirection::VerticalAxis) { - if (gestureDir.testFlag(GestureDirection::VerticalAxis)) { - return false; - } - } else if (currentDir & GestureDirection::HorizontalAxis) { - if (gestureDir.testFlag(GestureDirection::HorizontalAxis)) { - return false; - } - } - - return true; -} - void GestureRecognizer::cancelActiveGestures() { for (auto g : qAsConst(m_activeSwipeGestures)) { @@ -374,7 +363,6 @@ void GestureRecognizer::updatePinchGesture(qreal scale, qreal angleDelta, const for (PinchGesture *g : std::as_const(m_activePinchGestures)) { Q_EMIT g->triggerProgress(g->getTriggerProgress(scale)); Q_EMIT g->semanticProgress(g->getSemanticProgress(scale), g->direction()); - Q_EMIT g->semanticProgressAxis(g->getSemanticAxisProgress(scale), g->direction()); } } @@ -473,6 +461,7 @@ QSizeF SwipeGesture::triggerDelta() const void SwipeGesture::setTriggerDelta(const QSizeF &delta) { + Q_ASSERT(delta.width() >= 0 && delta.height() >= 0); m_triggerDelta = delta; m_triggerDeltaRelevant = true; } @@ -503,25 +492,36 @@ int GestureRecognizer::startSwipeGesture(uint fingerCount) return startSwipeGesture(fingerCount, QPointF(), StartPositionBehavior::Irrelevant); } -QSizeF SwipeGesture::getSemanticDelta(const QSizeF &delta) const -{ - QSizeF d = QSizeF(); - d.setWidth(delta.width() / m_unitDelta); - d.setHeight(delta.height() / m_unitDelta); - return d; -} - qreal SwipeGesture::getSemanticProgress(const QSizeF &delta) const { - if (m_direction.testFlag(GestureDirection::DirectionlessSwipe)) { - return std::hypot(delta.width(), delta.height()) / m_unitDelta; - } else if (m_direction & GestureDirection::VerticalAxis) { - return std::abs(delta.height()) / m_unitDelta; - } else if (m_direction & GestureDirection::HorizontalAxis) { - return std::abs(delta.width()) / m_unitDelta; + qreal progress = 0; + + if (direction() & GestureDirection::Up) { + qreal val = -delta.height() / m_unitDelta; + if (val > progress) { + progress = val; + } + } + if (direction() & GestureDirection::Down) { + qreal val = delta.height() / m_unitDelta; + if (val > progress) { + progress = val; + } + } + if (direction() & GestureDirection::Left) { + qreal val = -delta.width() / m_unitDelta; + if (val > progress) { + progress = val; + } + } + if (direction() & GestureDirection::Right) { + qreal val = delta.width() / m_unitDelta; + if (val > progress) { + progress = val; + } } - return 1.0; + return progress; } qreal PinchGesture::getSemanticProgress(const qreal scale) const @@ -529,22 +529,6 @@ qreal PinchGesture::getSemanticProgress(const qreal scale) const return std::max(std::abs(1 - scale) / m_unitScaleDelta, 0.0); } -qreal SwipeGesture::getSemanticAxisProgress(const QSizeF &delta) const -{ - if (m_direction & GestureDirection::VerticalAxis) { - return delta.height() / m_unitDelta; - } else if (m_direction & GestureDirection::HorizontalAxis) { - return delta.width() / m_unitDelta; - } - - return 1.0; -} - -qreal PinchGesture::getSemanticAxisProgress(const qreal scale) const -{ - return (scale - 1) / m_unitScaleDelta; -} - int GestureRecognizer::startSwipeGesture(const QPointF &startPos) { return startSwipeGesture(1, startPos, StartPositionBehavior::Relevant); diff --git a/src/gestures.h b/src/gestures.h index 2070585e5e..987066ee7c 100644 --- a/src/gestures.h +++ b/src/gestures.h @@ -27,7 +27,7 @@ static const QSet DEFAULT_VALID_FINGER_COUNTS = {1, 2, 3, 4, 5, 6, 7, 8, 9 /** * This is the amount of change for 1 unit of change, like switch by 1 desktop. */ -static const qreal DEFAULT_UNIT_DELTA = 400; // Pixels +static const qreal DEFAULT_UNIT_DELTA = 200; // Pixels static const qreal DEFAULT_UNIT_SCALE_DELTA = .2; // 20% class Gesture : public QObject @@ -74,7 +74,7 @@ Q_SIGNALS: */ void cancelled(); /** - * Progress towards the minimum threshold to trigger + * Progress towards the minimum threshold to trigger. [0, 1] */ void triggerProgress(qreal); /** @@ -84,13 +84,6 @@ Q_SIGNALS: * It can be more than 1, indicating an action should happen more than once. */ void semanticProgress(qreal, GestureDirections); - /** - * Like semantic progress except [-1, 1] and - * it captures both of something - * example: Up and Down (VerticalAxis), Contracting and Expanding (BiDirectionalPinch) - * Positive values are Up, Right and Expanding - */ - void semanticProgressAxis(qreal, GestureDirections); private: QSet m_validFingerCounts = DEFAULT_VALID_FINGER_COUNTS; @@ -118,10 +111,19 @@ public: bool maximumYIsRelevant() const; void setStartGeometry(const QRect &geometry); + /** + * In pixels + */ QSizeF triggerDelta() const; void setTriggerDelta(const QSizeF &delta); bool isTriggerDeltaRelevant() const; + /** + * Returns the progress [0, 1] of the gesture + * being triggered. Picks the largest possible value + * considering each direction available to the + * gesture. + */ qreal getTriggerProgress(const QSizeF &delta) const; bool triggerDeltaReached(const QSizeF &delta) const; @@ -134,17 +136,6 @@ public: * that the action should be done more times. */ qreal getSemanticProgress(const QSizeF &delta) const; - /** - * Like the last one, except [-1, 1] - * Positive values are Up and Right - */ - qreal getSemanticAxisProgress(const QSizeF &delta) const; - /** - * A two dimensional semantic delta. - * [-1, 1] on each axis. - * Positive is Up and Right - */ - QSizeF getSemanticDelta(const QSizeF &delta) const; Q_SIGNALS: /** @@ -152,17 +143,6 @@ Q_SIGNALS: * started to where it is now. */ void pixelDelta(const QSizeF &delta, GestureDirections); - /** - * A 2d coordinate giving the semantic axis delta - * [-1, 1] on both horizontal and vertical axes. - */ - void semanticDelta(const QSizeF &delta, GestureDirections); - /** - * GIves a 2d vector of pointing from - * where the gesture started to where - * it is now. - */ - void swipePixelVector(const QVector2D &vector); private: bool m_minimumXRelevant = false; @@ -194,6 +174,9 @@ public: void setTriggerScaleDelta(const qreal &scaleDelta); bool isTriggerScaleDeltaRelevant() const; + /** + * [0, 1] + */ qreal getTriggerProgress(const qreal &scaleDelta) const; bool triggerScaleDeltaReached(const qreal &scaleDelta) const; @@ -206,18 +189,6 @@ public: * that the action should be done more times. */ qreal getSemanticProgress(const qreal scale) const; - /** - * Like the last one, except [-1, 1] - * Positive is expanding. - * Positive values are Expanding - */ - qreal getSemanticAxisProgress(const qreal scale) const; - -Q_SIGNALS: - /** - * The progress is reported in [0.0,1.0] - */ - void triggerProgress(qreal); private: bool m_triggerScaleDeltaRelevant = false; @@ -251,7 +222,6 @@ public: private: void cancelActiveGestures(); - bool mutuallyExclusive(GestureDirections d, GestureDirections gestureDir); enum class StartPositionBehavior { Relevant, Irrelevant, diff --git a/src/globalshortcuts.cpp b/src/globalshortcuts.cpp index 273d0c77c9..dc9b4bf321 100644 --- a/src/globalshortcuts.cpp +++ b/src/globalshortcuts.cpp @@ -131,14 +131,14 @@ void GlobalShortcutsManager::registerGesture(GestureDeviceType device, GestureDi std::unique_ptr gesture = std::make_unique(); gesture->addFingerCount(fingerCount); gesture->setTriggerDelta(QSizeF(200, 200)); - connect(gesture.get(), &SwipeGesture::triggerProgress, progressCallback); + connect(gesture.get(), &SwipeGesture::semanticProgress, progressCallback); connect(gesture.get(), &Gesture::triggered, onUp, &QAction::trigger, Qt::QueuedConnection); connect(gesture.get(), &Gesture::cancelled, onUp, &QAction::trigger, Qt::QueuedConnection); shortcut.swipeGesture = std::move(gesture); } else if (isPinchDirection(direction)) { std::unique_ptr gesture = std::make_unique(); gesture->addFingerCount(fingerCount); - connect(gesture.get(), &PinchGesture::triggerProgress, progressCallback); + connect(gesture.get(), &PinchGesture::semanticProgress, progressCallback); connect(gesture.get(), &Gesture::triggered, onUp, &QAction::trigger, Qt::QueuedConnection); connect(gesture.get(), &Gesture::cancelled, onUp, &QAction::trigger, Qt::QueuedConnection); shortcut.pinchGesture = std::move(gesture); @@ -154,7 +154,7 @@ void GlobalShortcutsManager::forceRegisterTouchscreenSwipe(QAction *onUp, std::f gesture->addFingerCount(fingerCount); gesture->setDirection(direction); gesture->setTriggerDelta(QSizeF(200, 200)); - connect(gesture.get(), &SwipeGesture::triggerProgress, progressCallback); + connect(gesture.get(), &SwipeGesture::semanticProgress, progressCallback); connect(gesture.get(), &Gesture::triggered, onUp, &QAction::trigger, Qt::QueuedConnection); connect(gesture.get(), &Gesture::cancelled, onUp, &QAction::trigger, Qt::QueuedConnection); GestureShortcut gestureShortcut{GestureDeviceType::Touchscreen, direction}; diff --git a/src/libkwineffects/kwinglobals.h b/src/libkwineffects/kwinglobals.h index 89133d4cb5..a84cef0626 100644 --- a/src/libkwineffects/kwinglobals.h +++ b/src/libkwineffects/kwinglobals.h @@ -232,22 +232,18 @@ enum class GestureDirection { Right = 1 << 4, Expanding = 1 << 5, Contracting = 1 << 6, - VerticalAxis = Up | Down, // Up is positive values - HorizontalAxis = Left | Right, // Right is positive - DirectionlessSwipe = Left | Right | Up | Down, // Positive is Up/Right - BiDirectionalPinch = Expanding | Contracting, // Positive is Expanding }; Q_DECLARE_FLAGS(GestureDirections, GestureDirection) Q_DECLARE_OPERATORS_FOR_FLAGS(GestureDirections) Q_DECLARE_METATYPE(GestureDirection) -static bool isSwipeDirection(GestureDirections d) +inline bool isSwipeDirection(GestureDirections d) { return d & (GestureDirection::Up | GestureDirection::Down | GestureDirection::Left | GestureDirection::Right); } -static bool isPinchDirection(GestureDirections d) +inline bool isPinchDirection(GestureDirections d) { return d & (GestureDirection::Contracting | GestureDirection::Expanding); }