Skip to content

Commit

Permalink
refactor: split gestures into multiple files (#72)
Browse files Browse the repository at this point in the history
* cleanup

* refactor: generalize action

* refactor: split into multiple files

* refactor: split into multiple files
  • Loading branch information
horriblename committed Dec 27, 2023
1 parent e377be9 commit 0165a9e
Show file tree
Hide file tree
Showing 7 changed files with 309 additions and 309 deletions.
154 changes: 154 additions & 0 deletions src/gestures/Actions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#include "Actions.hpp"
#include <glm/glm.hpp>

wf::touch::action_status_t CMultiAction::update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) {
if (event.time - this->start_time > *this->timeout) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_UP) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_DOWN) {
// cancel if previous fingers moved too much
this->finger_count = state.fingers.size();
for (auto& finger : state.fingers) {
// TODO multiply tolerance by sensitivity?
if (glm::length(finger.second.delta()) > GESTURE_INITIAL_TOLERANCE) {
return wf::touch::ACTION_STATUS_CANCELLED;
}
}

return wf::touch::ACTION_STATUS_RUNNING;
}

if ((glm::length(state.get_center().delta()) >= MIN_SWIPE_DISTANCE) && (this->target_direction == 0)) {
this->target_direction = state.get_center().get_direction();
}

if (this->target_direction == 0) {
return wf::touch::ACTION_STATUS_RUNNING;
}

for (auto& finger : state.fingers) {
if (finger.second.get_incorrect_drag_distance(this->target_direction) > this->get_move_tolerance()) {
return wf::touch::ACTION_STATUS_CANCELLED;
}
}

if (state.get_center().get_drag_distance(target_direction) >= base_threshold / *sensitivity) {
return wf::touch::ACTION_STATUS_COMPLETED;
}
return wf::touch::ACTION_STATUS_RUNNING;
}

wf::touch::action_status_t MultiFingerDownAction::update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) {
if (event.time - this->start_time > this->get_duration()) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_UP) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_DOWN && state.fingers.size() >= SEND_CANCEL_EVENT_FINGER_COUNT) {
return wf::touch::ACTION_STATUS_COMPLETED;
}

return wf::touch::ACTION_STATUS_RUNNING;
}

wf::touch::action_status_t MultiFingerTap::update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) {
if (event.time - this->start_time > *this->timeout) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_UP) {
return wf::touch::ACTION_STATUS_COMPLETED;
}

if (event.type == wf::touch::EVENT_TYPE_MOTION) {
for (const auto& finger : state.fingers) {
const auto delta = finger.second.delta();
if (delta.x * delta.x + delta.y + delta.y > this->base_threshold / *this->sensitivity) {
return wf::touch::ACTION_STATUS_CANCELLED;
}
}
}

return wf::touch::ACTION_STATUS_RUNNING;
}

wf::touch::action_status_t LongPress::update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) {
if (event.time - this->start_time > *this->delay) {
return wf::touch::ACTION_STATUS_COMPLETED;
}

switch (event.type) {
case wf::touch::EVENT_TYPE_MOTION:
for (const auto& finger : state.fingers) {
const auto delta = finger.second.delta();
if (delta.x * delta.x + delta.y + delta.y > this->base_threshold / *this->sensitivity) {
return wf::touch::ACTION_STATUS_CANCELLED;
}
}
break;

case wf::touch::EVENT_TYPE_TOUCH_DOWN:
// TODO: also reset wl_timer here
gesture_action_t::reset(event.time);
this->update_external_timer_callback(event.time, *this->delay);
break;

case wf::touch::EVENT_TYPE_TOUCH_UP:
return wf::touch::ACTION_STATUS_CANCELLED;
}

return wf::touch::ACTION_STATUS_RUNNING;
}

wf::touch::action_status_t LiftoffAction::update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) {
if (event.time - this->start_time > this->get_duration()) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_UP) {
return wf::touch::ACTION_STATUS_COMPLETED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_DOWN) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

return wf::touch::ACTION_STATUS_RUNNING;
}

wf::touch::action_status_t TouchUpOrDownAction::update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) {
if (event.time - this->start_time > this->get_duration()) {
return wf::touch::ACTION_STATUS_CANCELLED;
}

if (event.type == wf::touch::EVENT_TYPE_TOUCH_UP || event.type == wf::touch::EVENT_TYPE_TOUCH_DOWN) {
return wf::touch::ACTION_STATUS_COMPLETED;
}

return wf::touch::ACTION_STATUS_RUNNING;
}

wf::touch::action_status_t OnCompleteAction::update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) {
auto status = this->action->update_state(state, event);

if (status == wf::touch::ACTION_STATUS_COMPLETED) {
this->callback();
}

return status;
}
116 changes: 116 additions & 0 deletions src/gestures/Actions.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#include "Shared.hpp"
#include <functional>
#include <memory>
#include <optional>
#include <wayfire/touch/touch.hpp>

using UpdateExternalTimerCallback = std::function<void(uint32_t current_timer, uint32_t delay)>;

// swipe and with multiple fingers and directions
class CMultiAction : public wf::touch::gesture_action_t {
private:
double base_threshold;
const float* sensitivity;
const int64_t* timeout;

public:
// threshold = base_threshold / sensitivity
// if the threshold needs to be adjusted dynamically, the sensitivity
// pointer is used
CMultiAction(double base_threshold, const float* sensitivity, const int64_t* timeout)
: base_threshold(base_threshold), sensitivity(sensitivity), timeout(timeout){};

GestureDirection target_direction = 0;
int finger_count = 0;

// The action is completed if any number of fingers is moved enough.
//
// This action should be followed by another that completes upon lifting a
// finger to achieve a gesture that completes after a multi-finger swipe is
// done and lifted.
wf::touch::action_status_t update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) override;

void reset(uint32_t time) override {
gesture_action_t::reset(time);
target_direction = 0;
};
};

class MultiFingerTap : public wf::touch::gesture_action_t {
private:
double base_threshold;
const float* sensitivity;
const int64_t* timeout;

public:
MultiFingerTap(double base_threshold, const float* sensitivity, const int64_t* timeout)
: base_threshold(base_threshold), sensitivity(sensitivity), timeout(timeout){};

wf::touch::action_status_t update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) override;
};

class LongPress : public wf::touch::gesture_action_t {
private:
double base_threshold;
const float* sensitivity;
const int64_t* delay;
UpdateExternalTimerCallback update_external_timer_callback;

public:
// TODO: I hope one day I can figure out how not to pass a function for the update timer callback
LongPress(double base_threshold, const float* sensitivity, const int64_t* delay,
UpdateExternalTimerCallback update_external_timer)
: base_threshold(base_threshold), sensitivity(sensitivity), delay(delay),
update_external_timer_callback(update_external_timer){};

wf::touch::action_status_t update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) override;
};

// Completes upon receiving enough touch down events within a short duration
class MultiFingerDownAction : public wf::touch::gesture_action_t {
// upon completion, calls the given callback.
//
// Intended to be used to send cancel events to surfaces when enough fingers
// touch down in quick succession.
public:
MultiFingerDownAction() {}

wf::touch::action_status_t update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) override;
};

// Completes upon receiving a touch up event and cancels upon receiving a touch
// down event.
class LiftoffAction : public wf::touch::gesture_action_t {
wf::touch::action_status_t update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) override;
};

// Completes upon receiving a touch up or touch down event
class TouchUpOrDownAction : public wf::touch::gesture_action_t {
wf::touch::action_status_t update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) override;
};

// This action is used to call a function right after another action is completed
class OnCompleteAction : public wf::touch::gesture_action_t {
private:
std::unique_ptr<wf::touch::gesture_action_t> action;
const std::function<void()> callback;

public:
OnCompleteAction(std::unique_ptr<wf::touch::gesture_action_t> action, std::function<void()> callback)
: callback(callback) {
this->action = std::move(action);
}

wf::touch::action_status_t update_state(const wf::touch::gesture_state_t& state,
const wf::touch::gesture_event_t& event) override;

void reset(uint32_t time) override {
this->action->reset(time);
}
};
Loading

0 comments on commit 0165a9e

Please sign in to comment.