-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: split gestures into multiple files (#72)
* cleanup * refactor: generalize action * refactor: split into multiple files * refactor: split into multiple files
- Loading branch information
1 parent
e377be9
commit 0165a9e
Showing
7 changed files
with
309 additions
and
309 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
}; |
Oops, something went wrong.