From e839b4ae09c92ffcc6a194a3f067f05d91e8b3de Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 3 May 2023 22:16:52 +0200 Subject: [PATCH 1/4] SystemTask: implement screen locked until button is pressed When the device is woken through pressing the button everything is the same. But when woken through other means like single-tap or raise-to-wake, then the screen is locked (and showing a lock screen on touch input) until the button is pressed. Only exception is when the alarm wakes the screen, then touch input is still valid for the user to be able to press the red "stop alarm" button. Co-authored-by: NeroBurner --- src/CMakeLists.txt | 1 + src/displayapp/DisplayApp.cpp | 6 +++ src/displayapp/DisplayApp.h | 2 + src/displayapp/Messages.h | 2 + src/displayapp/widgets/PopupMessage.cpp | 56 +++++++++++++++++++++++++ src/displayapp/widgets/PopupMessage.h | 20 +++++++++ src/systemtask/SystemTask.cpp | 24 ++++++++++- src/systemtask/SystemTask.h | 2 + 8 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 src/displayapp/widgets/PopupMessage.cpp create mode 100644 src/displayapp/widgets/PopupMessage.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8651059018..55313f0bc6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -403,6 +403,7 @@ list(APPEND SOURCE_FILES displayapp/widgets/PageIndicator.cpp displayapp/widgets/DotIndicator.cpp displayapp/widgets/StatusIcons.cpp + displayapp/widgets/PopupMessage.cpp ## Settings displayapp/screens/settings/QuickSettings.cpp diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index add006500f..fbb429cdd9 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -476,6 +476,12 @@ void DisplayApp::Refresh() { LoadNewScreen(Apps::Clock, DisplayApp::FullRefreshDirections::None); motorController.RunForDuration(35); break; + case Messages::ShowIgnoreTouchPopup: + popupMessage.SetHidden(false); + break; + case Messages::HideIgnoreTouchPopup: + popupMessage.SetHidden(true); + break; } } diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 2f276eaf9e..1dfc496e61 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -15,6 +15,7 @@ #include "components/timer/Timer.h" #include "components/alarm/AlarmController.h" #include "touchhandler/TouchHandler.h" +#include "displayapp/widgets/PopupMessage.h" #include "displayapp/Messages.h" #include "BootErrors.h" @@ -102,6 +103,7 @@ namespace Pinetime { Pinetime::Controllers::FirmwareValidator validator; Pinetime::Components::LittleVgl lvgl; Pinetime::Controllers::Timer timer; + Pinetime::Applications::Widgets::PopupMessage popupMessage; AppControllers controllers; TaskHandle_t taskHandle; diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index 1fcd72d278..76750a96e8 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -24,6 +24,8 @@ namespace Pinetime { AlarmTriggered, Chime, BleRadioEnableToggle, + ShowIgnoreTouchPopup, + HideIgnoreTouchPopup }; } } diff --git a/src/displayapp/widgets/PopupMessage.cpp b/src/displayapp/widgets/PopupMessage.cpp new file mode 100644 index 0000000000..ffcecdca4e --- /dev/null +++ b/src/displayapp/widgets/PopupMessage.cpp @@ -0,0 +1,56 @@ +#include "displayapp/widgets/PopupMessage.h" +#include "displayapp/InfiniTimeTheme.h" +#include + +using namespace Pinetime::Applications::Widgets; + +PopupMessage::PopupMessage() { +} + +void PopupMessage::Create() { + popup = lv_obj_create(lv_scr_act(), nullptr); + lv_obj_set_size(popup, 90, 90); + lv_obj_align(popup, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_color(popup, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, Colors::bg); + lv_obj_set_style_local_bg_opa(popup, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_60); + lv_obj_t* lockBody = lv_obj_create(popup, nullptr); + lv_obj_set_size(lockBody, 55, 50); + lv_obj_align(lockBody, popup, LV_ALIGN_CENTER, 0, 10); + + lv_obj_set_style_local_bg_color(lockBody, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_bg_opa(lockBody, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_border_color(lockBody, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_border_width(lockBody, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 22); + lv_obj_set_style_local_border_side(lockBody, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_BORDER_SIDE_FULL); + lv_obj_set_style_local_border_opa(lockBody, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100); + + lv_obj_t* lockTop = lv_obj_create(popup, nullptr); + lv_obj_set_size(lockTop, 30, 35); + lv_obj_align(lockTop, popup, LV_ALIGN_CENTER, 0, -20); + lv_obj_set_style_local_bg_color(lockTop, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_bg_opa(lockTop, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0); + lv_obj_set_style_local_border_color(lockTop, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); + lv_obj_set_style_local_border_width(lockTop, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, 6); + lv_obj_set_style_local_border_side(lockTop, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_BORDER_SIDE_FULL); + lv_obj_set_style_local_border_opa(lockTop, LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100); + + lv_obj_set_hidden(popup, isHidden); +} + +void PopupMessage::SetHidden(bool hidden) { + if (isHidden == hidden) { + return; + } + isHidden = hidden; + // create/delete on demand + if (popup == nullptr && !isHidden) { + Create(); + } else if (popup != nullptr) { + lv_obj_del(popup); + popup = nullptr; + } +} + +bool PopupMessage::IsHidden() { + return isHidden; +} diff --git a/src/displayapp/widgets/PopupMessage.h b/src/displayapp/widgets/PopupMessage.h new file mode 100644 index 0000000000..39e16b2c8f --- /dev/null +++ b/src/displayapp/widgets/PopupMessage.h @@ -0,0 +1,20 @@ +#pragma once +#include + +namespace Pinetime { + namespace Applications { + namespace Widgets { + class PopupMessage { + public: + PopupMessage(); + void Create(); + void SetHidden(bool hidden); + bool IsHidden(); + + private: + lv_obj_t* popup = nullptr; + bool isHidden = true; + }; + } + } +} diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 8e0435e372..d978763b07 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -215,6 +215,7 @@ void SystemTask::Work() { } break; case Messages::SetOffAlarm: + unlockedByButton = true; // unlock so it is possible to press red stop button GoToRunning(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered); break; @@ -224,6 +225,7 @@ void SystemTask::Work() { bleDiscoveryTimer = 5; break; case Messages::BleFirmwareUpdateStarted: + unlockedByButton = true; // prevent no screen-locked popup on firmware update GoToRunning(); wakeLocksHeld++; displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted); @@ -251,7 +253,14 @@ void SystemTask::Work() { break; } if (state == SystemTaskState::Running) { - displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); + if (unlockedByButton) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); + } else { + auto gesture = touchHandler.GestureGet(); + if (gesture != Pinetime::Applications::TouchEvents::None) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowIgnoreTouchPopup); + } + } } else { // If asleep, check for touch panel wake triggers auto gesture = touchHandler.GestureGet(); @@ -273,6 +282,7 @@ void SystemTask::Work() { action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping if (IsSleeping()) { + unlockedByButton = true; fastWakeUpDone = true; GoToRunning(); break; @@ -314,6 +324,8 @@ void SystemTask::Work() { } else { state = SystemTaskState::AODSleeping; } + // lock when going to sleep + unlockedByButton = false; break; case Messages::OnNewDay: // We might be sleeping (with TWI device disabled. @@ -424,6 +436,8 @@ void SystemTask::GoToSleep() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep); } heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep); + unlockedByButton = false; + displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup); state = SystemTaskState::GoingToSleep; }; @@ -473,7 +487,13 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) { case Actions::Click: // If the first action after fast wakeup is a click, it should be ignored. if (!fastWakeUpDone) { - displayApp.PushMessage(Applications::Display::Messages::ButtonPushed); + if (!unlockedByButton) { + // the first button event unlocks the touch input + unlockedByButton = true; + displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup); + } else { + displayApp.PushMessage(Applications::Display::Messages::ButtonPushed); + } } break; case Actions::DoubleClick: diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 0060e36096..be0d6e4dea 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -134,6 +134,8 @@ namespace Pinetime { bool stepCounterMustBeReset = false; static constexpr TickType_t batteryMeasurementPeriod = pdMS_TO_TICKS(10 * 60 * 1000); + bool unlockedByButton = true; + SystemMonitor monitor; }; } From ace122e63ec8eea24626ca9ef46abd5980509cb6 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sat, 24 May 2025 21:40:04 +0200 Subject: [PATCH 2/4] PopupMessage: little cleanup, more const --- src/displayapp/widgets/PopupMessage.cpp | 7 ++----- src/displayapp/widgets/PopupMessage.h | 26 +++++++++++-------------- 2 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/displayapp/widgets/PopupMessage.cpp b/src/displayapp/widgets/PopupMessage.cpp index ffcecdca4e..56545f5143 100644 --- a/src/displayapp/widgets/PopupMessage.cpp +++ b/src/displayapp/widgets/PopupMessage.cpp @@ -4,9 +4,6 @@ using namespace Pinetime::Applications::Widgets; -PopupMessage::PopupMessage() { -} - void PopupMessage::Create() { popup = lv_obj_create(lv_scr_act(), nullptr); lv_obj_set_size(popup, 90, 90); @@ -37,7 +34,7 @@ void PopupMessage::Create() { lv_obj_set_hidden(popup, isHidden); } -void PopupMessage::SetHidden(bool hidden) { +void PopupMessage::SetHidden(const bool hidden) { if (isHidden == hidden) { return; } @@ -51,6 +48,6 @@ void PopupMessage::SetHidden(bool hidden) { } } -bool PopupMessage::IsHidden() { +bool PopupMessage::IsHidden() const { return isHidden; } diff --git a/src/displayapp/widgets/PopupMessage.h b/src/displayapp/widgets/PopupMessage.h index 39e16b2c8f..6a43d5525b 100644 --- a/src/displayapp/widgets/PopupMessage.h +++ b/src/displayapp/widgets/PopupMessage.h @@ -1,20 +1,16 @@ #pragma once #include -namespace Pinetime { - namespace Applications { - namespace Widgets { - class PopupMessage { - public: - PopupMessage(); - void Create(); - void SetHidden(bool hidden); - bool IsHidden(); +namespace Pinetime::Applications::Widgets { + class PopupMessage { + public: + PopupMessage() = default; + void Create(); + void SetHidden(bool hidden); + bool IsHidden() const; - private: - lv_obj_t* popup = nullptr; - bool isHidden = true; - }; - } - } + private: + lv_obj_t* popup = nullptr; + bool isHidden = true; + }; } From 085ea372c2b3125cf7e1348f8fd1ff148a9c2259 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Thu, 29 May 2025 22:32:31 +0200 Subject: [PATCH 3/4] SystemTask: clang-format --- src/systemtask/SystemTask.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index d978763b07..ea1dc544ce 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -215,7 +215,7 @@ void SystemTask::Work() { } break; case Messages::SetOffAlarm: - unlockedByButton = true; // unlock so it is possible to press red stop button + unlockedByButton = true; // unlock so it is possible to press red stop button GoToRunning(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered); break; @@ -225,7 +225,7 @@ void SystemTask::Work() { bleDiscoveryTimer = 5; break; case Messages::BleFirmwareUpdateStarted: - unlockedByButton = true; // prevent no screen-locked popup on firmware update + unlockedByButton = true; // prevent no screen-locked popup on firmware update GoToRunning(); wakeLocksHeld++; displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted); From ea52fb7e5f4b361c777f7f5f24b2035ef61e7006 Mon Sep 17 00:00:00 2001 From: sim Date: Sun, 20 Jul 2025 12:57:45 +0200 Subject: [PATCH 4/4] Always hide lock popup when changing appview It fixes a potential double-free when removing lock popup --- src/displayapp/DisplayApp.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index fbb429cdd9..7b3b77230f 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -505,6 +505,11 @@ void DisplayApp::LoadNewScreen(Apps app, DisplayApp::FullRefreshDirections direc // This is mainly to fix an issue with receiving two notifications at the same time // and shouldn't happen otherwise. if (app != currentApp) { + // We need to remove the popup + // If we keep the popup linked to the previous view, and this view is deleted, a bug will occur if we try to re-remove the popup. + // Not removing the popup will also prevent the popup to be raised on top of + // the new app + popupMessage.SetHidden(true); returnAppStack.Push(currentApp); appStackDirections.Push(direction); }