Skip to content

Commit

Permalink
libgestures: replace gesture->triggerOneActionOnly with action->block…
Browse files Browse the repository at this point in the history
…Otheractions

closes #17
  • Loading branch information
taj-ny committed Oct 18, 2024
1 parent 2d16551 commit b7dad0a
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 41 deletions.
6 changes: 3 additions & 3 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ See [example_gestures.md](example_gestures.md) for examples.
- **Fingers** (int) - Number of fingers required to trigger this gesture.<br>Sets **MinimumFingers** and **MaximumFingers**.<br>Minimum value: **2** for hold and pinch gestures, **3** for swipe.<br>Default: **none**
- **MinimumFingers** (int) - Minimum number of fingers required to trigger this gesture.<br>See **Fingers** for accepted values.<br>Default: **none**
- **MaximumFingers** (int) - Maximum number of fingers required to trigger this gesture.<br>See **Fingers** for accepted values.<br>Default: **none**
- **TriggerWhenThresholdReached** (bool) - Whether to trigger the gesture immediately after the specified threshold is reached.<br>Default: **false**
- **TriggerOneActionOnly** (bool) - Whether to trigger only the first action that satisfies a condition.<br>Default: **false**<br>&nbsp;
- **TriggerWhenThresholdReached** (bool) - Whether to trigger the gesture immediately after the specified threshold is reached.<br>Default: **false**&nbsp;
- **[Hold]** - Configuration for hold gestures.
- **Threshold** (int) - In milliseconds.<br>Default: **0**
- **[Pinch]** - Configuration for pinch gestures.
Expand Down Expand Up @@ -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.<br>Can be negative for all gestures except hold.<br>Default: **0 (no repeating)**<br>&nbsp;
- **RepeatInterval** (int/float) - Whether and how often this action should repeat.<br>Can be negative for all gestures except hold.<br>Default: **0 (no repeating)**
- **BlockOtherActions** (bool) - Whether this action should block other actions if triggered.<br>Default: **false**<br>&nbsp;
- **[Command]** - Configuration for the GlobalShortcut action.
- **Command** (string) - The command to run.<br>Default: **none**
- **[GlobalShortcut]** - Configuration for the GlobalShortcut action.
Expand Down
3 changes: 2 additions & 1 deletion docs/example_gestures.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/kwin/config/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ void Config::read(std::shared_ptr<GestureInputEventFilter> filter, std::shared_p
minimumFingers = maximumFingers = fingers;
}
const bool triggerWhenThresholdReached = gestureGroup.readEntry("TriggerWhenThresholdReached", false);
const bool triggerOneActionOnly = gestureGroup.readEntry("TriggerOneActionOnly", false);

std::shared_ptr<libgestures::Gesture> gesture;
if (gestureType == "Hold")
Expand Down Expand Up @@ -89,7 +88,6 @@ void Config::read(std::shared_ptr<GestureInputEventFilter> filter, std::shared_p

gesture->setFingers(minimumFingers, maximumFingers);
gesture->setTriggerWhenThresholdReached(triggerWhenThresholdReached);
gesture->setTriggerOneActionOnly(triggerOneActionOnly);

if (!gesture)
continue;
Expand Down Expand Up @@ -128,6 +126,7 @@ void Config::read(std::shared_ptr<GestureInputEventFilter> 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)
Expand Down
10 changes: 10 additions & 0 deletions src/libgestures/libgestures/actions/action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions src/libgestures/libgestures/actions/action.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<const Condition> &condition);

/**
Expand All @@ -32,6 +38,7 @@ class GestureAction : public QObject
*/
bool satisfiesConditions() const;

void setBlockOtherActions(const bool &blockOtherActions);
void setRepeatInterval(const qreal &interval);
signals:
/**
Expand Down Expand Up @@ -65,6 +72,7 @@ private slots:
void onGestureStarted();
void onGestureUpdated(const qreal &delta);
private:
bool m_blockOtherActions = false;
qreal m_repeatInterval = 0;
std::vector<std::shared_ptr<const Condition>> m_conditions;

Expand Down
31 changes: 18 additions & 13 deletions src/libgestures/libgestures/gestures/gesture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ void Gesture::onCancelled()

m_accumulatedDelta = 0;
m_hasStarted = false;
m_blockingAction = std::nullopt;
}

void Gesture::onEnded()
Expand All @@ -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()
Expand All @@ -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;
}
}

Expand Down Expand Up @@ -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
12 changes: 5 additions & 7 deletions src/libgestures/libgestures/gestures/gesture.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -75,14 +69,18 @@ private slots:
private:
uint8_t m_minimumFingers = 0;
uint8_t m_maximumFingers = 0;
bool m_triggerOneActionOnly = false;

std::vector<std::shared_ptr<const Condition>> m_conditions;

std::vector<std::shared_ptr<GestureAction>> m_actions;

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<std::shared_ptr<GestureAction>> m_blockingAction;
};

} // namespace libgestures
23 changes: 9 additions & 14 deletions tests/libgestures/gestures/test_gesturerecognizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ void TestGestureRecognizer::init()
m_hold2To3->setFingers(2, 3);
m_hold3To4 = std::make_shared<HoldGesture>();
m_hold3To4->setFingers(3, 4);

m_hold2_2actions_trigger1only = std::make_shared<HoldGesture>();
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<GestureAction>());
m_hold2_2actions_trigger1only->addAction(std::make_shared<GestureAction>());
}

void TestGestureRecognizer::gestureBegin_calledTwice_hasOneActiveGesture()
Expand Down Expand Up @@ -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<GestureAction>());
const auto action = std::make_shared<GestureAction>();
action->setBlockOtherActions(true);
gesture1->addAction(action);
const auto gesture2 = std::make_shared<HoldGesture>();
gesture2->setThreshold(1);
gesture2->setFingers(2, 2);
Expand Down Expand Up @@ -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<GestureAction>());
const auto action = std::make_shared<GestureAction>();
action->setBlockOtherActions(true);
gesture1->addAction(action);
const auto gesture2 = std::make_shared<PinchGesture>();
gesture2->setDirection(PinchDirection::Expanding);
gesture2->setThreshold(0.1);
Expand Down Expand Up @@ -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<GestureAction>());
const auto action = std::make_shared<GestureAction>();
action->setBlockOtherActions(true);
gesture1->addAction(action);
const auto gesture2 = std::make_shared<SwipeGesture>();
gesture2->setDirection(SwipeDirection::Right);
gesture2->setThreshold(1);
Expand Down
1 change: 0 additions & 1 deletion tests/libgestures/gestures/test_gesturerecognizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ private slots:
std::shared_ptr<HoldGesture> m_hold2;
std::shared_ptr<HoldGesture> m_hold2To3;
std::shared_ptr<HoldGesture> m_hold3To4;
std::shared_ptr<HoldGesture> m_hold2_2actions_trigger1only;
};

} // namespace libgestures

0 comments on commit b7dad0a

Please sign in to comment.