From 1736f7874b8f651ae42a21f48b6a15d90f30974a Mon Sep 17 00:00:00 2001 From: jacqueline Date: Mon, 29 Apr 2024 13:53:11 +1000 Subject: [PATCH] Use double-clicks instead of long-presses for wheel shortcuts --- src/input/include/input_hook.hpp | 4 ++- src/input/include/input_trigger.hpp | 7 ++++- src/input/input_hook.cpp | 5 ++++ src/input/input_nav_buttons.cpp | 4 +-- src/input/input_touch_dpad.cpp | 4 +-- src/input/input_touch_wheel.cpp | 13 +++++---- src/input/input_trigger.cpp | 44 ++++++++++++++++++++--------- 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 cb) - : TriggerHooks(name, cb, cb, cb) {} + : TriggerHooks(name, cb, cb, cb, cb) {} TriggerHooks(std::string name, std::optional click, + std::optional double_click, std::optional long_press, std::optional 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 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 { TriggerHooks::TriggerHooks(std::string name, std::optional click, + std::optional double_click, std::optional long_press, std::optional 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 #include -#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; } }