summaryrefslogtreecommitdiff
path: root/src/input
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-04-29 13:53:11 +1000
committerjacqueline <me@jacqueline.id.au>2024-04-29 13:53:11 +1000
commit1736f7874b8f651ae42a21f48b6a15d90f30974a (patch)
treea039df2382ace755172e00fc0f779a464c92e093 /src/input
parentb255ea799eead9668e7fd69a286349ac4a74a73c (diff)
downloadtangara-fw-1736f7874b8f651ae42a21f48b6a15d90f30974a.tar.gz
Use double-clicks instead of long-presses for wheel shortcuts
Diffstat (limited to 'src/input')
-rw-r--r--src/input/include/input_hook.hpp4
-rw-r--r--src/input/include/input_trigger.hpp7
-rw-r--r--src/input/input_hook.cpp5
-rw-r--r--src/input/input_nav_buttons.cpp4
-rw-r--r--src/input/input_touch_dpad.cpp4
-rw-r--r--src/input/input_touch_wheel.cpp13
-rw-r--r--src/input/input_trigger.cpp44
7 files changed, 55 insertions, 26 deletions
diff --git a/src/input/include/input_hook.hpp b/src/input/include/input_hook.hpp
index a257c04a..a8705210 100644
--- a/src/input/include/input_hook.hpp
+++ b/src/input/include/input_hook.hpp
@@ -45,9 +45,10 @@ class Hook {
class TriggerHooks {
public:
TriggerHooks(std::string name, std::optional<HookCallback> cb)
- : TriggerHooks(name, cb, cb, cb) {}
+ : TriggerHooks(name, cb, cb, cb, cb) {}
TriggerHooks(std::string name,
std::optional<HookCallback> click,
+ std::optional<HookCallback> double_click,
std::optional<HookCallback> long_press,
std::optional<HookCallback> repeat);
@@ -66,6 +67,7 @@ class TriggerHooks {
Trigger trigger_;
Hook click_;
+ Hook double_click_;
Hook long_press_;
Hook repeat_;
};
diff --git a/src/input/include/input_trigger.hpp b/src/input/include/input_trigger.hpp
index 599b796b..bcafa8ad 100644
--- a/src/input/include/input_trigger.hpp
+++ b/src/input/include/input_trigger.hpp
@@ -13,6 +13,7 @@
namespace input {
+const uint16_t kDoubleClickDelayMs = 500;
const uint16_t kLongPressDelayMs = LV_INDEV_DEF_LONG_PRESS_TIME;
const uint16_t kRepeatDelayMs = LV_INDEV_DEF_LONG_PRESS_REP_TIME;
@@ -21,6 +22,7 @@ class Trigger {
enum class State {
kNone,
kClick,
+ kDoubleClick,
kLongPress,
kRepeatPress,
};
@@ -31,7 +33,10 @@ class Trigger {
private:
std::optional<uint64_t> touch_time_ms_;
- uint16_t times_fired_;
+ bool was_pressed_;
+
+ bool was_double_click_;
+ uint16_t times_long_pressed_;
};
} // namespace input
diff --git a/src/input/input_hook.cpp b/src/input/input_hook.cpp
index 48d6c2a4..bf9f3596 100644
--- a/src/input/input_hook.cpp
+++ b/src/input/input_hook.cpp
@@ -39,10 +39,12 @@ auto Hook::callback() -> std::optional<HookCallback> {
TriggerHooks::TriggerHooks(std::string name,
std::optional<HookCallback> click,
+ std::optional<HookCallback> double_click,
std::optional<HookCallback> long_press,
std::optional<HookCallback> repeat)
: name_(name),
click_("click", click),
+ double_click_("double_click", double_click),
long_press_("long_press", long_press),
repeat_("repeat", repeat) {}
@@ -51,6 +53,9 @@ auto TriggerHooks::update(bool pressed, lv_indev_data_t* d) -> void {
case Trigger::State::kClick:
click_.invoke(d);
break;
+ case Trigger::State::kDoubleClick:
+ double_click_.invoke(d);
+ break;
case Trigger::State::kLongPress:
long_press_.invoke(d);
break;
diff --git a/src/input/input_nav_buttons.cpp b/src/input/input_nav_buttons.cpp
index 522f8d6e..61d80075 100644
--- a/src/input/input_nav_buttons.cpp
+++ b/src/input/input_nav_buttons.cpp
@@ -15,8 +15,8 @@ namespace input {
NavButtons::NavButtons(drivers::IGpios& gpios)
: gpios_(gpios),
- up_("upper", actions::scrollUp(), actions::select(), {}),
- down_("lower", actions::scrollDown(), actions::select(), {}) {}
+ up_("upper", {}, actions::scrollUp(), actions::select(), {}),
+ down_("lower", {}, actions::scrollDown(), actions::select(), {}) {}
auto NavButtons::read(lv_indev_data_t* data) -> void {
up_.update(!gpios_.Get(drivers::IGpios::Pin::kKeyUp), data);
diff --git a/src/input/input_touch_dpad.cpp b/src/input/input_touch_dpad.cpp
index d8eff09b..df17d766 100644
--- a/src/input/input_touch_dpad.cpp
+++ b/src/input/input_touch_dpad.cpp
@@ -21,9 +21,9 @@ namespace input {
TouchDPad::TouchDPad(drivers::TouchWheel& wheel)
: wheel_(wheel),
- centre_("centre", actions::select(), {}, {}),
+ centre_("centre", actions::select(), {}, {}, {}),
up_("up", actions::scrollUp()),
- right_("right", {}, {}, {}),
+ right_("right", {}),
down_("down", actions::scrollDown()),
left_("left", actions::goBack()) {}
diff --git a/src/input/input_touch_wheel.cpp b/src/input/input_touch_wheel.cpp
index 67cab3bf..41fd73bc 100644
--- a/src/input/input_touch_wheel.cpp
+++ b/src/input/input_touch_wheel.cpp
@@ -39,11 +39,11 @@ TouchWheel::TouchWheel(drivers::NvsStorage& nvs, drivers::TouchWheel& wheel)
threshold_ = calculateThreshold(int_val);
return true;
}),
- centre_("centre", actions::select(), {}, {}),
- up_("up", {}, actions::scrollToTop(), actions::scrollUp()),
- right_("right", {}, {}, {}),
- down_("down", {}, actions::scrollToBottom(), actions::scrollDown()),
- left_("left", {}, actions::goBack(), {}),
+ centre_("centre", actions::select(), {}, {}, {}),
+ up_("up", {}, actions::scrollToTop(), {}, {}),
+ right_("right", {}),
+ down_("down", {}, actions::scrollToBottom(), {}, {}),
+ left_("left", {}, actions::goBack(), {}, {}),
is_scrolling_(false),
threshold_(calculateThreshold(nvs.ScrollSensitivity())),
is_first_read_(true),
@@ -68,7 +68,8 @@ auto TouchWheel::read(lv_indev_data_t* data) -> void {
data->enc_diff = 0;
}
- centre_.update(!is_scrolling_ && wheel_data.is_button_touched, data);
+ centre_.update(wheel_data.is_button_touched && !wheel_data.is_wheel_touched,
+ data);
// If the user is touching the wheel but not scrolling, then they may be
// clicking on one of the wheel's cardinal directions.
diff --git a/src/input/input_trigger.cpp b/src/input/input_trigger.cpp
index 9485ecb4..00d4a32d 100644
--- a/src/input/input_trigger.cpp
+++ b/src/input/input_trigger.cpp
@@ -8,34 +8,50 @@
#include <sys/_stdint.h>
#include <cstdint>
-#include "esp_log.h"
#include "esp_timer.h"
namespace input {
-Trigger::Trigger() : touch_time_ms_(), times_fired_(0) {}
+Trigger::Trigger()
+ : touch_time_ms_(),
+ was_pressed_(false),
+ was_double_click_(false),
+ times_long_pressed_(0) {}
auto Trigger::update(bool is_pressed) -> State {
// Bail out early if we're in a steady-state of not pressed.
- if (!is_pressed && !touch_time_ms_) {
+ if (!is_pressed && !was_pressed_) {
+ was_double_click_ = false;
+ times_long_pressed_ = 0;
return State::kNone;
}
uint64_t now_ms = esp_timer_get_time() / 1000;
- // Initial press of this key: record the current time, and report that we
- // haven't triggered yet.
- if (is_pressed && !touch_time_ms_) {
+ // This key wasn't being pressed, but now it is.
+ if (is_pressed && !was_pressed_) {
+ // Is this a double click?
+ if (now_ms - *touch_time_ms_ < kDoubleClickDelayMs) {
+ // Don't update touch_time_ms_, since we don't want triple clicks to
+ // register as double clicks.
+ was_double_click_ = true;
+ was_pressed_ = true;
+ return State::kDoubleClick;
+ }
+ // Not a double click; update our accounting info and wait for the next
+ // call.
touch_time_ms_ = now_ms;
- times_fired_ = 0;
+ was_double_click_ = false;
+ times_long_pressed_ = 0;
+ was_pressed_ = true;
return State::kNone;
}
// The key was released. If there were no long-press events fired during the
// press, then this was a standard click.
- if (!is_pressed && touch_time_ms_) {
- touch_time_ms_.reset();
- if (times_fired_ == 0) {
+ if (!is_pressed && was_pressed_) {
+ was_pressed_ = false;
+ if (!was_double_click_ && times_long_pressed_ == 0) {
return State::kClick;
} else {
return State::kNone;
@@ -43,10 +59,10 @@ auto Trigger::update(bool is_pressed) -> State {
}
// Now the more complicated case: the user is continuing to press the button.
- if (times_fired_ == 0) {
+ if (times_long_pressed_ == 0) {
// We haven't fired yet, so we wait for the long-press event.
if (now_ms - *touch_time_ms_ >= kLongPressDelayMs) {
- times_fired_++;
+ times_long_pressed_++;
return State::kLongPress;
}
} else {
@@ -60,8 +76,8 @@ auto Trigger::update(bool is_pressed) -> State {
// kRepeatDelayMs since the long-press event.
uint16_t expected_times_fired =
1 + (time_since_long_press / kRepeatDelayMs);
- if (times_fired_ < expected_times_fired) {
- times_fired_++;
+ if (times_long_pressed_ < expected_times_fired) {
+ times_long_pressed_++;
return State::kRepeatPress;
}
}