From 63d04fbfa2b23477ef99db965ab1d0cfda1dc1f3 Mon Sep 17 00:00:00 2001 From: Trail Mate Dev Date: Fri, 18 Sep 2026 14:52:57 +0800 Subject: [PATCH] feat(screen): add resume API and swipe-up gesture for Wio L2 --- .../include/platform/ui/screen_runtime.h | 10 ++ .../ui/components/screen_saver_overlay.cpp | 17 ++- packs/zh-Hans/locales/zh-Hans/strings.tsv | 3 +- .../esp/arduino_common/src/LV_Helper_v9.cpp | 135 ++++++++++++++++-- .../esp/arduino_common/src/screen_sleep.cpp | 16 ++- platform/esp/idf_common/src/screen_sleep.cpp | 12 +- .../common/src/platform/ui/screen_runtime.cpp | 12 +- 7 files changed, 190 insertions(+), 15 deletions(-) diff --git a/modules/core_sys/include/platform/ui/screen_runtime.h b/modules/core_sys/include/platform/ui/screen_runtime.h index 0f9294e7..41477d87 100644 --- a/modules/core_sys/include/platform/ui/screen_runtime.h +++ b/modules/core_sys/include/platform/ui/screen_runtime.h @@ -6,6 +6,12 @@ namespace platform::ui::screen { +enum class ResumeMethod : std::uint8_t +{ + SpaceKey, + SwipeUp, +}; + struct Hooks { bool (*format_time)(char* out, std::size_t out_len) = nullptr; @@ -33,5 +39,9 @@ void wake_for_modal(); void record_activity(); void disable_sleep(); void enable_sleep(); +// Explicit user intent to dismiss the screen saver and return to +// the UI/page that was active before sleep. +void request_resume(); +ResumeMethod resume_method(); } // namespace platform::ui::screen diff --git a/modules/ui_shared/src/ui/components/screen_saver_overlay.cpp b/modules/ui_shared/src/ui/components/screen_saver_overlay.cpp index bb311b94..a33d09f3 100644 --- a/modules/ui_shared/src/ui/components/screen_saver_overlay.cpp +++ b/modules/ui_shared/src/ui/components/screen_saver_overlay.cpp @@ -3,6 +3,7 @@ #include #include "lvgl.h" +#include "platform/ui/screen_runtime.h" #include "sys/clock.h" #include "ui/localization.h" @@ -43,7 +44,21 @@ void set_label_texts(int unread) } if (s_hint_label != nullptr) { - ::ui::i18n::set_label_text(s_hint_label, "Press SPACE to resume"); + switch (::platform::ui::screen::resume_method()) + { + case ::platform::ui::screen::ResumeMethod::SwipeUp: + ::ui::i18n::set_label_text( + s_hint_label, + "Swipe up to resume"); + break; + + case ::platform::ui::screen::ResumeMethod::SpaceKey: + default: + ::ui::i18n::set_label_text( + s_hint_label, + "Press SPACE to resume"); + break; + } } } diff --git a/packs/zh-Hans/locales/zh-Hans/strings.tsv b/packs/zh-Hans/locales/zh-Hans/strings.tsv index d540bfcd..e17a98ef 100644 --- a/packs/zh-Hans/locales/zh-Hans/strings.tsv +++ b/packs/zh-Hans/locales/zh-Hans/strings.tsv @@ -386,7 +386,8 @@ Pairing init failed 配对初始化失败 Pairing not available 当前无法配对 Pairing not ready 配对尚未就绪 Press Back to exit USB mode 按返回键退出 USB 模式 -Press SPACE to resume 按 SPACE 唤醒屏幕 +Press SPACE to resume 按 SPACE 继续 +Swipe up to resume 上滑以继续 RallyTo 集结到 Route configured 已配置路线 Route: %s 路线:%s diff --git a/platform/esp/arduino_common/src/LV_Helper_v9.cpp b/platform/esp/arduino_common/src/LV_Helper_v9.cpp index b0c18139..d4c00aab 100644 --- a/platform/esp/arduino_common/src/LV_Helper_v9.cpp +++ b/platform/esp/arduino_common/src/LV_Helper_v9.cpp @@ -948,48 +948,162 @@ static void disp_flush(lv_display_t* disp_drv, const lv_area_t* area, uint8_t* c } #ifdef USING_INPUT_DEV_TOUCHPAD + +#if defined(ARDUINO_WIO_TRACKER_L2) +constexpr int16_t kScreenResumeSwipeMinY = 60; +constexpr int16_t kScreenResumeSwipeMaxX = 80; +#endif + static void touchpad_read(lv_indev_t* drv, lv_indev_data_t* data) { - static int16_t x, y; + static int16_t x = 0; + static int16_t y = 0; static bool was_touched = false; + +#if defined(ARDUINO_WIO_TRACKER_L2) + static bool resume_swipe_tracking = false; + static int16_t resume_start_x = 0; + static int16_t resume_start_y = 0; + static int16_t resume_last_x = 0; + static int16_t resume_last_y = 0; +#endif + #if defined(ARDUINO_T_DECK_PRO) static bool debug_touch_active = false; #endif - auto* plane = (LilyGo_Display*)lv_indev_get_user_data(drv); - uint8_t touched = plane->getPoint(&x, &y, 1); + + auto* plane = + static_cast(lv_indev_get_user_data(drv)); + + const uint8_t touched = + plane->getPoint(&x, &y, 1); + if (touched) { #if defined(ARDUINO_T_DECK_PRO) if (!debug_touch_active) { - Serial.printf("[DEBUG-touch-a7682e] down lvgl=%d,%d\n", x, y); + Serial.printf( + "[DEBUG-touch-a7682e] down lvgl=%d,%d\n", + x, + y); + debug_touch_active = true; } #endif + + const bool touch_started = !was_touched; was_touched = true; + input::MorseEngine::notifyTouch(); - if (::platform::ui::screen::is_sleeping() || - ::platform::ui::screen::is_saver_active()) + + const bool screen_power_active = + ::platform::ui::screen::is_sleeping() || + ::platform::ui::screen::is_saver_active(); + + if (screen_power_active) { +#if defined(ARDUINO_WIO_TRACKER_L2) + if (touch_started) + { + resume_swipe_tracking = true; + + resume_start_x = x; + resume_start_y = y; + + resume_last_x = x; + resume_last_y = y; + } + else if (resume_swipe_tracking) + { + resume_last_x = x; + resume_last_y = y; + } +#endif + + // Any touch wakes Sleeping -> WakePreview and refreshes the + // preview timeout. The touch is consumed by the screen-power + // layer and must not reach the underlying UI. ::platform::ui::screen::handle_input(); + data->state = LV_INDEV_STATE_REL; return; } + +#if defined(ARDUINO_WIO_TRACKER_L2) + // If the screen left the saver state while the finger is still down, + // discard any unfinished resume gesture so it cannot leak into the + // normal UI path. + resume_swipe_tracking = false; +#endif + ::platform::ui::screen::record_activity(); + data->point.x = x; data->point.y = y; data->state = LV_INDEV_STATE_PR; return; } + if (was_touched) { was_touched = false; + +#if defined(ARDUINO_WIO_TRACKER_L2) + bool resumed = false; + + if (resume_swipe_tracking) + { + const int16_t delta_y = + static_cast( + resume_start_y - resume_last_y); + + const int16_t delta_x = + static_cast( + std::abs( + static_cast( + resume_last_x - resume_start_x))); + + const bool swipe_up = + delta_y >= kScreenResumeSwipeMinY && + delta_x <= kScreenResumeSwipeMaxX; + + if (swipe_up) + { + Serial.printf( + "[ScreenPower][Touch] resume swipe " + "start=(%d,%d) end=(%d,%d) dx=%d dy=%d\n", + resume_start_x, + resume_start_y, + resume_last_x, + resume_last_y, + delta_x, + delta_y); + + ::platform::ui::screen::request_resume(); + resumed = true; + } + + resume_swipe_tracking = false; + } + + if (!resumed) + { + ::platform::ui::screen::handle_input_release(); + } +#else ::platform::ui::screen::handle_input_release(); +#endif } + #if defined(ARDUINO_T_DECK_PRO) if (debug_touch_active) { - Serial.printf("[DEBUG-touch-a7682e] up lvgl=%d,%d\n", x, y); + Serial.printf( + "[DEBUG-touch-a7682e] up lvgl=%d,%d\n", + x, + y); + debug_touch_active = false; } #endif @@ -1109,8 +1223,9 @@ static void keypad_read(lv_indev_t* drv, lv_indev_data_t* data) } } - // Screen power transitions consume the input event before normal keyboard - // dispatch. Space resumes the page and focus preserved at sleep time. + // Screen-power input is consumed before normal keyboard dispatch. + // Space is the keyboard resume gesture and restores the page/focus + // that was active before sleep. if (::platform::ui::screen::is_sleeping() || ::platform::ui::screen::is_saver_active()) { @@ -1118,7 +1233,7 @@ static void keypad_read(lv_indev_t* drv, lv_indev_data_t* data) { if (!from_nav && key == ' ') { - ::platform::ui::screen::handle_confirm_input(); + ::platform::ui::screen::request_resume(); } else { diff --git a/platform/esp/arduino_common/src/screen_sleep.cpp b/platform/esp/arduino_common/src/screen_sleep.cpp index 0bb35e2f..054478f7 100644 --- a/platform/esp/arduino_common/src/screen_sleep.cpp +++ b/platform/esp/arduino_common/src/screen_sleep.cpp @@ -336,7 +336,7 @@ void handle_input() void handle_confirm_input() { - (void)post_event(Event::ConfirmInput); + request_resume(); } void handle_input_release() @@ -364,4 +364,18 @@ void enable_sleep() (void)post_event(Event::EnableSleep); } +void request_resume() +{ + (void)post_event(Event::ConfirmInput); +} + +ResumeMethod resume_method() +{ +#if defined(ARDUINO_WIO_TRACKER_L2) + return ResumeMethod::SwipeUp; +#else + return ResumeMethod::SpaceKey; +#endif +} + } // namespace platform::ui::screen diff --git a/platform/esp/idf_common/src/screen_sleep.cpp b/platform/esp/idf_common/src/screen_sleep.cpp index 63adf0d5..f6b7f60b 100644 --- a/platform/esp/idf_common/src/screen_sleep.cpp +++ b/platform/esp/idf_common/src/screen_sleep.cpp @@ -349,7 +349,7 @@ void handle_input() void handle_confirm_input() { - (void)post_event(Event::ConfirmInput); + request_resume(); } void handle_input_release() @@ -377,4 +377,14 @@ void enable_sleep() (void)post_event(Event::EnableSleep); } +void request_resume() +{ + (void)post_event(Event::ConfirmInput); +} + +ResumeMethod resume_method() +{ + return ResumeMethod::SpaceKey; +} + } // namespace platform::ui::screen diff --git a/platform/linux/common/src/platform/ui/screen_runtime.cpp b/platform/linux/common/src/platform/ui/screen_runtime.cpp index d4751d2a..f34b7474 100644 --- a/platform/linux/common/src/platform/ui/screen_runtime.cpp +++ b/platform/linux/common/src/platform/ui/screen_runtime.cpp @@ -90,7 +90,7 @@ void handle_input() void handle_confirm_input() { - s_machine.dispatch(platform::ui::screen_power::Event::ConfirmInput, now_ms()); + request_resume(); } void handle_input_release() @@ -118,4 +118,14 @@ void enable_sleep() s_machine.dispatch(platform::ui::screen_power::Event::EnableSleep, now_ms()); } +void request_resume() +{ + s_machine.dispatch(platform::ui::screen_power::Event::ConfirmInput, now_ms()); +} + +ResumeMethod resume_method() +{ + return ResumeMethod::SpaceKey; +} + } // namespace platform::ui::screen