From b7dad0ab3b550669e5f8411ae2b20a3c66f166bb Mon Sep 17 00:00:00 2001
From: taj-ny <79316397+taj-ny@users.noreply.github.com>
Date: Fri, 18 Oct 2024 16:07:48 +0200
Subject: [PATCH] libgestures: replace gesture->triggerOneActionOnly with
action->blockOtheractions
closes #17
---
docs/configuration.md | 6 ++--
docs/example_gestures.md | 3 +-
src/kwin/config/config.cpp | 3 +-
.../libgestures/actions/action.cpp | 10 ++++++
src/libgestures/libgestures/actions/action.h | 8 +++++
.../libgestures/gestures/gesture.cpp | 31 +++++++++++--------
.../libgestures/gestures/gesture.h | 12 +++----
.../gestures/test_gesturerecognizer.cpp | 23 ++++++--------
.../gestures/test_gesturerecognizer.h | 1 -
9 files changed, 56 insertions(+), 41 deletions(-)
diff --git a/docs/configuration.md b/docs/configuration.md
index 0220294..6fa634e 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -14,8 +14,7 @@ See [example_gestures.md](example_gestures.md) for examples.
- **Fingers** (int) - Number of fingers required to trigger this gesture.
Sets **MinimumFingers** and **MaximumFingers**.
Minimum value: **2** for hold and pinch gestures, **3** for swipe.
Default: **none**
- **MinimumFingers** (int) - Minimum number of fingers required to trigger this gesture.
See **Fingers** for accepted values.
Default: **none**
- **MaximumFingers** (int) - Maximum number of fingers required to trigger this gesture.
See **Fingers** for accepted values.
Default: **none**
- - **TriggerWhenThresholdReached** (bool) - Whether to trigger the gesture immediately after the specified threshold is reached.
Default: **false**
- - **TriggerOneActionOnly** (bool) - Whether to trigger only the first action that satisfies a condition.
Default: **false**
+ - **TriggerWhenThresholdReached** (bool) - Whether to trigger the gesture immediately after the specified threshold is reached.
Default: **false**
- **[Hold]** - Configuration for hold gestures.
- **Threshold** (int) - In milliseconds.
Default: **0**
- **[Pinch]** - Configuration for pinch gestures.
@@ -44,7 +43,8 @@ See [example_gestures.md](example_gestures.md) for examples.
- ``Command`` - Run a command.
- ``GlobalShortcut`` - Invoke a global shortcut.
- ``KeySequence`` - Send keystrokes.
- - **RepeatInterval** (int/float) - Whether and how often this action should repeat.
Can be negative for all gestures except hold.
Default: **0 (no repeating)**
+ - **RepeatInterval** (int/float) - Whether and how often this action should repeat.
Can be negative for all gestures except hold.
Default: **0 (no repeating)**
+ - **BlockOtherActions** (bool) - Whether this action should block other actions if triggered.
Default: **false**
- **[Command]** - Configuration for the GlobalShortcut action.
- **Command** (string) - The command to run.
Default: **none**
- **[GlobalShortcut]** - Configuration for the GlobalShortcut action.
diff --git a/docs/example_gestures.md b/docs/example_gestures.md
index 9c55b97..2777b64 100644
--- a/docs/example_gestures.md
+++ b/docs/example_gestures.md
@@ -102,7 +102,7 @@ Command=pactl set-sink-volume @DEFAULT_SINK@ +5%
[Gestures][Touchpad][4]
Type=Swipe
Fingers=4
-TriggerWhenThresholdReached=false
+TriggerWhenThresholdReached=true
[Gestures][Touchpad][4][Swipe]
Direction=Down
@@ -123,6 +123,7 @@ Type=GlobalShortcut
[Gestures][Touchpad][4][Actions][1][Conditions][0]
WindowState=Maximized
+BlockOtherActions=true # Prevent the minimize window action from triggering during the same gesture
[Gestures][Touchpad][4][Actions][1][GlobalShortcut]
Component=kwin
diff --git a/src/kwin/config/config.cpp b/src/kwin/config/config.cpp
index ac9d979..ca24e95 100644
--- a/src/kwin/config/config.cpp
+++ b/src/kwin/config/config.cpp
@@ -34,7 +34,6 @@ void Config::read(std::shared_ptr filter, std::shared_p
minimumFingers = maximumFingers = fingers;
}
const bool triggerWhenThresholdReached = gestureGroup.readEntry("TriggerWhenThresholdReached", false);
- const bool triggerOneActionOnly = gestureGroup.readEntry("TriggerOneActionOnly", false);
std::shared_ptr gesture;
if (gestureType == "Hold")
@@ -89,7 +88,6 @@ void Config::read(std::shared_ptr filter, std::shared_p
gesture->setFingers(minimumFingers, maximumFingers);
gesture->setTriggerWhenThresholdReached(triggerWhenThresholdReached);
- gesture->setTriggerOneActionOnly(triggerOneActionOnly);
if (!gesture)
continue;
@@ -128,6 +126,7 @@ void Config::read(std::shared_ptr filter, std::shared_p
continue;
action->setRepeatInterval(actionGroup.readEntry("RepeatInterval", 0.0));
+ action->setBlockOtherActions(actionGroup.readEntry("BlockOtherActions", false));
const auto conditions = readConditions(actionGroup.group("Conditions"), windowInfoProvider);
for (const auto &condition : conditions)
diff --git a/src/libgestures/libgestures/actions/action.cpp b/src/libgestures/libgestures/actions/action.cpp
index 0669c89..183ce7b 100644
--- a/src/libgestures/libgestures/actions/action.cpp
+++ b/src/libgestures/libgestures/actions/action.cpp
@@ -35,6 +35,11 @@ bool GestureAction::canExecute() const
return m_repeatInterval != 0 || !m_triggered;
}
+bool GestureAction::blocksOtherActions() const
+{
+ return m_triggered && m_blockOtherActions;
+}
+
void GestureAction::onGestureCancelled()
{
if (m_when == When::Cancelled && canExecute() && satisfiesConditions())
@@ -82,6 +87,11 @@ void GestureAction::onGestureUpdated(const qreal &delta)
}
}
+void GestureAction::setBlockOtherActions(const bool &blockOtherActions)
+{
+ m_blockOtherActions = blockOtherActions;
+}
+
void GestureAction::setRepeatInterval(const qreal &interval)
{
m_repeatInterval = interval;
diff --git a/src/libgestures/libgestures/actions/action.h b/src/libgestures/libgestures/actions/action.h
index 39844b7..8dbb4c4 100644
--- a/src/libgestures/libgestures/actions/action.h
+++ b/src/libgestures/libgestures/actions/action.h
@@ -24,6 +24,12 @@ class GestureAction : public QObject
bool repeat() const { return m_repeatInterval != 0; };
+ /**
+ * @return Whether any other actions belonging to a gesture should not be executed. @c true if the action has been
+ * executed and blockOtherActions has been set to @c true, @c false otherwise.
+ */
+ [[nodiscard]] bool blocksOtherActions() const;
+
void addCondition(const std::shared_ptr &condition);
/**
@@ -32,6 +38,7 @@ class GestureAction : public QObject
*/
bool satisfiesConditions() const;
+ void setBlockOtherActions(const bool &blockOtherActions);
void setRepeatInterval(const qreal &interval);
signals:
/**
@@ -65,6 +72,7 @@ private slots:
void onGestureStarted();
void onGestureUpdated(const qreal &delta);
private:
+ bool m_blockOtherActions = false;
qreal m_repeatInterval = 0;
std::vector> m_conditions;
diff --git a/src/libgestures/libgestures/gestures/gesture.cpp b/src/libgestures/libgestures/gestures/gesture.cpp
index 493084d..3b41ee5 100644
--- a/src/libgestures/libgestures/gestures/gesture.cpp
+++ b/src/libgestures/libgestures/gestures/gesture.cpp
@@ -21,6 +21,7 @@ void Gesture::onCancelled()
m_accumulatedDelta = 0;
m_hasStarted = false;
+ m_blockingAction = std::nullopt;
}
void Gesture::onEnded()
@@ -29,10 +30,16 @@ void Gesture::onEnded()
return;
for (const auto &action : m_actions)
+ {
+ if (!action->repeat() && !m_triggerWhenThresholdReached && action->canExecute() && thresholdReached(m_accumulatedDelta)
+ && action->satisfiesConditions() && (!m_blockingAction || m_blockingAction->get() == action.get()))
+ action->execute();
Q_EMIT action->gestureEnded();
+ }
m_accumulatedDelta = 0;
m_hasStarted = false;
+ m_blockingAction = std::nullopt;
}
void Gesture::onStarted()
@@ -54,20 +61,23 @@ void Gesture::onUpdated(const qreal &delta, bool &endedPrematurely)
for (const auto &action : m_actions)
{
- if (!action->satisfiesConditions())
+ if (!action->satisfiesConditions() || (m_blockingAction.has_value() && m_blockingAction.value().get() != action.get()))
continue;
- if (!action->repeat() && m_triggerWhenThresholdReached && action->canExecute()) {
+ if (!action->repeat() && m_triggerWhenThresholdReached && action->canExecute())
+ {
action->execute();
- if (m_triggerOneActionOnly)
- {
- Q_EMIT ended();
- endedPrematurely = true;
- return;
- }
+ if (!action->blocksOtherActions())
+ continue;
+
+ Q_EMIT ended();
+ endedPrematurely = true;
+ return;
}
Q_EMIT action->gestureUpdated(delta);
+ if (action->blocksOtherActions())
+ m_blockingAction = action;
}
}
@@ -121,9 +131,4 @@ void Gesture::setFingers(const uint8_t &minimum, const uint8_t &maximum)
m_maximumFingers = maximum;
}
-void Gesture::setTriggerOneActionOnly(const bool &triggerOneActionOnly)
-{
- m_triggerOneActionOnly = triggerOneActionOnly;
-}
-
} // namespace libgestures
\ No newline at end of file
diff --git a/src/libgestures/libgestures/gestures/gesture.h b/src/libgestures/libgestures/gestures/gesture.h
index d14962a..5330bda 100644
--- a/src/libgestures/libgestures/gestures/gesture.h
+++ b/src/libgestures/libgestures/gestures/gesture.h
@@ -34,12 +34,6 @@ class Gesture : public QObject
void setTriggerWhenThresholdReached(const bool &triggerWhenThresholdReached);
void setThreshold(const qreal &threshold);
void setFingers(const uint8_t &minimum, const uint8_t &maximum);
-
- /**
- * @param triggerOneActionOnly Whether only one action should be executed during a gesture. This can cause a
- * gesture to end prematurely.
- */
- void setTriggerOneActionOnly(const bool &triggerOneActionOnly);
signals:
/**
* Emitted when the gesture has been cancelled.
@@ -75,7 +69,6 @@ private slots:
private:
uint8_t m_minimumFingers = 0;
uint8_t m_maximumFingers = 0;
- bool m_triggerOneActionOnly = false;
std::vector> m_conditions;
@@ -83,6 +76,11 @@ private slots:
qreal m_accumulatedDelta = 0;
bool m_hasStarted = false;
+
+ /**
+ * The action that currently blocks other actions. Reset after gesture has been cancelled or ended.
+ */
+ std::optional> m_blockingAction;
};
} // namespace libgestures
\ No newline at end of file
diff --git a/tests/libgestures/gestures/test_gesturerecognizer.cpp b/tests/libgestures/gestures/test_gesturerecognizer.cpp
index 42b9c4c..c0f9f6a 100644
--- a/tests/libgestures/gestures/test_gesturerecognizer.cpp
+++ b/tests/libgestures/gestures/test_gesturerecognizer.cpp
@@ -13,14 +13,6 @@ void TestGestureRecognizer::init()
m_hold2To3->setFingers(2, 3);
m_hold3To4 = std::make_shared();
m_hold3To4->setFingers(3, 4);
-
- m_hold2_2actions_trigger1only = std::make_shared();
- m_hold2_2actions_trigger1only->setTriggerWhenThresholdReached(true);
- m_hold2_2actions_trigger1only->setFingers(2, 2);
- m_hold2_2actions_trigger1only->setTriggerOneActionOnly(true);
- m_hold2_2actions_trigger1only->setThreshold(1);
- m_hold2_2actions_trigger1only->addAction(std::make_shared());
- m_hold2_2actions_trigger1only->addAction(std::make_shared());
}
void TestGestureRecognizer::gestureBegin_calledTwice_hasOneActiveGesture()
@@ -91,8 +83,9 @@ void TestGestureRecognizer::holdGestureUpdate_twoActiveGesturesAndOneEndsPrematu
gesture1->setThreshold(1);
gesture1->setFingers(2, 2);
gesture1->setTriggerWhenThresholdReached(true);
- gesture1->setTriggerOneActionOnly(true);
- gesture1->addAction(std::make_shared());
+ const auto action = std::make_shared();
+ action->setBlockOtherActions(true);
+ gesture1->addAction(action);
const auto gesture2 = std::make_shared();
gesture2->setThreshold(1);
gesture2->setFingers(2, 2);
@@ -159,8 +152,9 @@ void TestGestureRecognizer::pinchGestureUpdate_twoActiveGesturesAndOneEndsPremat
gesture1->setThreshold(0.1);
gesture1->setFingers(2, 2);
gesture1->setTriggerWhenThresholdReached(true);
- gesture1->setTriggerOneActionOnly(true);
- gesture1->addAction(std::make_shared());
+ const auto action = std::make_shared();
+ action->setBlockOtherActions(true);
+ gesture1->addAction(action);
const auto gesture2 = std::make_shared();
gesture2->setDirection(PinchDirection::Expanding);
gesture2->setThreshold(0.1);
@@ -262,8 +256,9 @@ void TestGestureRecognizer::swipeGestureUpdate_twoActiveGesturesAndOneEndsPremat
gesture1->setThreshold(1);
gesture1->setFingers(3, 3);
gesture1->setTriggerWhenThresholdReached(true);
- gesture1->setTriggerOneActionOnly(true);
- gesture1->addAction(std::make_shared());
+ const auto action = std::make_shared();
+ action->setBlockOtherActions(true);
+ gesture1->addAction(action);
const auto gesture2 = std::make_shared();
gesture2->setDirection(SwipeDirection::Right);
gesture2->setThreshold(1);
diff --git a/tests/libgestures/gestures/test_gesturerecognizer.h b/tests/libgestures/gestures/test_gesturerecognizer.h
index cdb9a96..094a639 100644
--- a/tests/libgestures/gestures/test_gesturerecognizer.h
+++ b/tests/libgestures/gestures/test_gesturerecognizer.h
@@ -48,7 +48,6 @@ private slots:
std::shared_ptr m_hold2;
std::shared_ptr m_hold2To3;
std::shared_ptr m_hold3To4;
- std::shared_ptr m_hold2_2actions_trigger1only;
};
} // namespace libgestures
\ No newline at end of file