From f768e0749d9df7dd2f4efaec09df8a82c7fc894f Mon Sep 17 00:00:00 2001 From: Tomas Groth Date: Wed, 3 May 2023 22:16:52 +0200 Subject: [PATCH 1/4] Refactor the original ignore-touch implementation to work on latest code Improve the lock and the code Squeeze in button unlock option in Wake Up settings Split the WakeUp settings into 2 pages Replace the text in the popup with a lock icon. SystemTask: rebase onto 1.15.0 Co-authored-by: NeroBurner --- src/CMakeLists.txt | 1 + src/components/settings/Settings.h | 13 ++++- src/displayapp/DisplayApp.cpp | 10 +++- src/displayapp/DisplayApp.h | 3 + src/displayapp/Messages.h | 2 + src/displayapp/fonts/CMakeLists.txt | 2 +- src/displayapp/fonts/fonts.json | 10 ++++ src/displayapp/screens/Page.h | 29 ++++++++++ src/displayapp/screens/Symbols.h | 3 + .../screens/settings/SettingWakeUp.cpp | 46 ++++++++++++--- .../screens/settings/SettingWakeUp.h | 22 ++++++- src/displayapp/widgets/PopupMessage.cpp | 37 ++++++++++++ src/displayapp/widgets/PopupMessage.h | 24 ++++++++ src/libs/lv_conf.h | 3 +- src/systemtask/SystemTask.cpp | 58 +++++++++++++++---- src/systemtask/SystemTask.h | 5 ++ src/touchhandler/TouchHandler.cpp | 20 ++++++- src/touchhandler/TouchHandler.h | 31 +++++++++- 18 files changed, 286 insertions(+), 33 deletions(-) create mode 100644 src/displayapp/screens/Page.h 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 e2b69b8b02..75531bb8f5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -402,6 +402,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/components/settings/Settings.h b/src/components/settings/Settings.h index 602de3a585..356977d70a 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -13,7 +13,14 @@ namespace Pinetime { enum class WeatherFormat : uint8_t { Metric, Imperial }; enum class Notification : uint8_t { On, Off, Sleep }; enum class ChimesOption : uint8_t { None, Hours, HalfHours }; - enum class WakeUpMode : uint8_t { SingleTap = 0, DoubleTap = 1, RaiseWrist = 2, Shake = 3, LowerWrist = 4 }; + enum class WakeUpMode : uint8_t { + SingleTap = 0, + DoubleTap = 1, + RaiseWrist = 2, + Shake = 3, + LowerWrist = 4, + ButtonUnlocks = 5, + }; enum class Colors : uint8_t { White, Silver, @@ -260,7 +267,7 @@ namespace Pinetime { } }; - std::bitset<5> getWakeUpModes() const { + std::bitset<6> getWakeUpModes() const { return settings.wakeUpMode; } @@ -321,7 +328,7 @@ namespace Pinetime { WatchFaceInfineat watchFaceInfineat; - std::bitset<5> wakeUpMode {0}; + std::bitset<6> wakeUpMode {0}; uint16_t shakeWakeThreshold = 150; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 6671ac9e51..ed667bd920 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -30,6 +30,7 @@ #include "displayapp/screens/Weather.h" #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" +#include "displayapp/screens/Symbols.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" @@ -101,6 +102,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, spiNorFlash {spiNorFlash}, lvgl {lcd, filesystem}, timer(this, TimerCallback), + popupMessage {Screens::Symbols::lock, 90, 90}, controllers {batteryController, bleController, dateTimeController, @@ -478,6 +480,12 @@ void DisplayApp::Refresh() { case Messages::OnChargingEvent: motorController.RunForDuration(15); break; + case Messages::ShowIgnoreTouchPopup: + popupMessage.SetHidden(false); + break; + case Messages::HideIgnoreTouchPopup: + popupMessage.SetHidden(true); + break; } } @@ -603,7 +611,7 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio currentScreen = std::make_unique(settingsController); break; case Apps::SettingWakeUp: - currentScreen = std::make_unique(settingsController); + currentScreen = std::make_unique(this, settingsController); break; case Apps::SettingDisplay: currentScreen = std::make_unique(settingsController); diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 2f276eaf9e..2ee551197d 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,8 +103,10 @@ namespace Pinetime { Pinetime::Controllers::FirmwareValidator validator; Pinetime::Components::LittleVgl lvgl; Pinetime::Controllers::Timer timer; + Pinetime::Applications::Widgets::PopupMessage popupMessage; AppControllers controllers; + TaskHandle_t taskHandle; States state = States::Running; diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index d2abc8e58d..f3294775cb 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -25,6 +25,8 @@ namespace Pinetime { Chime, BleRadioEnableToggle, OnChargingEvent, + ShowIgnoreTouchPopup, + HideIgnoreTouchPopup }; } } diff --git a/src/displayapp/fonts/CMakeLists.txt b/src/displayapp/fonts/CMakeLists.txt index 562f0801ad..979e6c5901 100644 --- a/src/displayapp/fonts/CMakeLists.txt +++ b/src/displayapp/fonts/CMakeLists.txt @@ -1,5 +1,5 @@ set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20 - jetbrains_mono_extrabold_compressed lv_font_sys_48 + jetbrains_mono_extrabold_compressed lv_font_sys_48 lv_font_sys_80 open_sans_light fontawesome_weathericons) find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin") diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 41c383c0d4..59afed0f5b 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -64,6 +64,16 @@ "bpp": 1, "size": 48 }, + "lv_font_sys_80": { + "sources": [ + { + "file": "material-design-icons/MaterialIcons-Regular.ttf", + "range": "0xe897" + } + ], + "bpp": 1, + "size": 80 + }, "fontawesome_weathericons": { "sources": [ { diff --git a/src/displayapp/screens/Page.h b/src/displayapp/screens/Page.h new file mode 100644 index 0000000000..b670630fa6 --- /dev/null +++ b/src/displayapp/screens/Page.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include "displayapp/screens/Screen.h" +#include "displayapp/widgets/PageIndicator.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class Page : public Screen { + public: + Page(uint8_t screenID, uint8_t numScreens, lv_obj_t* contentObj) : contentObj {contentObj}, pageIndicator(screenID, numScreens) { + pageIndicator.Create(); + } + + ~Page() override { + lv_obj_clean(lv_scr_act()); + } + + private: + lv_obj_t* contentObj = nullptr; + Widgets::PageIndicator pageIndicator; + }; + } + } +} diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index bd958b285f..323fc73a87 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -64,6 +64,9 @@ namespace Pinetime { static constexpr const char* flashlight = "\xEF\x80\x8B"; static constexpr const char* paintbrushLg = "\xEE\x90\x8A"; + + // wake-up screenlock icon, from material icons + static constexpr const char* lock = "\xEE\xA2\x97"; } } } diff --git a/src/displayapp/screens/settings/SettingWakeUp.cpp b/src/displayapp/screens/settings/SettingWakeUp.cpp index 4649dc82e2..d610ff8258 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.cpp +++ b/src/displayapp/screens/settings/SettingWakeUp.cpp @@ -8,7 +8,17 @@ using namespace Pinetime::Applications::Screens; -constexpr std::array SettingWakeUp::options; +constexpr std::array SettingWakeUp::options; + +auto SettingWakeUp::CreateScreenList() { + std::array()>, nScreens> screens; + for (size_t i = 0; i < screens.size(); i++) { + screens[i] = [this, i]() -> std::unique_ptr { + return CreateScreen(i); + }; + } + return screens; +} namespace { void event_handler(lv_obj_t* obj, lv_event_t event) { @@ -19,7 +29,16 @@ namespace { } } -SettingWakeUp::SettingWakeUp(Pinetime::Controllers::Settings& settingsController) : settingsController {settingsController} { +SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) + : settingsController {settingsController}, screens {app, 0, CreateScreenList(), Screens::ScreenListModes::UpDown} { +} + +SettingWakeUp::~SettingWakeUp() { + lv_obj_clean(lv_scr_act()); + settingsController.SaveSettings(); +} + +std::unique_ptr SettingWakeUp::CreateScreen(size_t screenNum) { lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP); @@ -43,20 +62,29 @@ SettingWakeUp::SettingWakeUp(Pinetime::Controllers::Settings& settingsController lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - for (unsigned int i = 0; i < options.size(); i++) { + // cleanup any old pointers + cbOption.fill(nullptr); + + // only loop as far as the list size aĺlows + unsigned int loopMax = screenNum * optionsPerScreen + optionsPerScreen; + if (loopMax > options.size()) { + loopMax = options.size(); + } + + for (unsigned int i = screenNum * optionsPerScreen; i < loopMax; i++) { cbOption[i] = lv_checkbox_create(container1, nullptr); lv_checkbox_set_text(cbOption[i], options[i].name); - if (settingsController.isWakeUpModeOn(static_cast(i))) { + if (settingsController.isWakeUpModeOn(options[i].wakeUpMode)) { lv_checkbox_set_checked(cbOption[i], true); } cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); } + return std::make_unique(screenNum, nScreens, container1); } -SettingWakeUp::~SettingWakeUp() { - lv_obj_clean(lv_scr_act()); - settingsController.SaveSettings(); +bool SettingWakeUp::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + return screens.OnTouchEvent(event); } void SettingWakeUp::UpdateSelected(lv_obj_t* object) { @@ -74,6 +102,8 @@ void SettingWakeUp::UpdateSelected(lv_obj_t* object) { // for example, when setting SingleTap, DoubleTap is unset and vice versa. auto modes = settingsController.getWakeUpModes(); for (size_t i = 0; i < options.size(); ++i) { - lv_checkbox_set_checked(cbOption[i], modes[i]); + if (cbOption[i]) { + lv_checkbox_set_checked(cbOption[i], modes[i]); + } } } diff --git a/src/displayapp/screens/settings/SettingWakeUp.h b/src/displayapp/screens/settings/SettingWakeUp.h index 61edabce34..b7bc4723d0 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.h +++ b/src/displayapp/screens/settings/SettingWakeUp.h @@ -4,7 +4,10 @@ #include #include #include "components/settings/Settings.h" +#include "displayapp/screens/Page.h" #include "displayapp/screens/Screen.h" +#include "displayapp/screens/ScreenList.h" +#include "displayapp/widgets/PageIndicator.h" namespace Pinetime { @@ -13,27 +16,40 @@ namespace Pinetime { class SettingWakeUp : public Screen { public: - SettingWakeUp(Pinetime::Controllers::Settings& settingsController); + SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController); ~SettingWakeUp() override; void UpdateSelected(lv_obj_t* object); + bool OnTouchEvent(TouchEvents event) override; + private: + auto CreateScreenList(); + std::unique_ptr CreateScreen(size_t screenNum); + struct Option { Controllers::Settings::WakeUpMode wakeUpMode; const char* name; }; + static constexpr size_t numOptions = 6; + static constexpr size_t optionsPerScreen = 4; + static constexpr size_t nScreens = 2; + Controllers::Settings& settingsController; - static constexpr std::array options = {{ + + ScreenList screens; + + static constexpr std::array options = {{ {Controllers::Settings::WakeUpMode::SingleTap, "Single Tap"}, {Controllers::Settings::WakeUpMode::DoubleTap, "Double Tap"}, {Controllers::Settings::WakeUpMode::RaiseWrist, "Raise Wrist"}, {Controllers::Settings::WakeUpMode::Shake, "Shake Wake"}, {Controllers::Settings::WakeUpMode::LowerWrist, "Lower Wrist"}, + {Controllers::Settings::WakeUpMode::ButtonUnlocks, "Button Unlock"}, }}; - lv_obj_t* cbOption[options.size()]; + std::array cbOption; }; } } diff --git a/src/displayapp/widgets/PopupMessage.cpp b/src/displayapp/widgets/PopupMessage.cpp new file mode 100644 index 0000000000..7bfcc97e23 --- /dev/null +++ b/src/displayapp/widgets/PopupMessage.cpp @@ -0,0 +1,37 @@ +#include "displayapp/widgets/PopupMessage.h" +#include + +using namespace Pinetime::Applications::Widgets; + +PopupMessage::PopupMessage(const char* msg, int16_t h, int16_t w) : message {msg}, height {h}, width {w} { +} + +void PopupMessage::Create() { + btnPopup = lv_btn_create(lv_scr_act(), nullptr); + btnPopup->user_data = this; + lv_obj_set_size(btnPopup, height, width); + lv_obj_align(btnPopup, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(btnPopup, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_60); + lv_obj_set_style_local_text_font(btnPopup, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_80); + lv_obj_t* lblMessage = lv_label_create(btnPopup, nullptr); + lv_label_set_text_static(lblMessage, message); + lv_obj_set_hidden(btnPopup, isHidden); +} + +void PopupMessage::SetHidden(bool hidden) { + if (isHidden == hidden) { + return; + } + isHidden = hidden; + // create/delete on demand + if (btnPopup == nullptr && !isHidden) { + Create(); + } else if (btnPopup != nullptr) { + lv_obj_del(btnPopup); + btnPopup = 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..ca993912fe --- /dev/null +++ b/src/displayapp/widgets/PopupMessage.h @@ -0,0 +1,24 @@ +#pragma once +#include + +namespace Pinetime { + namespace Applications { + namespace Widgets { + class PopupMessage { + public: + // The caller owns the message string, it is not copied. + PopupMessage(const char* msg, int16_t h, int16_t w); + void Create(); + void SetHidden(bool hidden); + bool IsHidden(); + + private: + const char* message; + lv_obj_t* btnPopup = nullptr; + bool isHidden = true; + int16_t height; + int16_t width; + }; + } + } +} diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h index c23647f2c0..9bf21fb841 100644 --- a/src/libs/lv_conf.h +++ b/src/libs/lv_conf.h @@ -419,7 +419,8 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in LV_FONT_DECLARE(jetbrains_mono_76) \ LV_FONT_DECLARE(open_sans_light) \ LV_FONT_DECLARE(fontawesome_weathericons) \ - LV_FONT_DECLARE(lv_font_sys_48) + LV_FONT_DECLARE(lv_font_sys_48) \ + LV_FONT_DECLARE(lv_font_sys_80) /* Enable it if you have fonts with a lot of characters. * The limit depends on the font size, font face and bpp diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index eb013d6d1a..16adf6f004 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -211,11 +211,13 @@ void SystemTask::Work() { if (IsSleeping()) { GoToRunning(); } + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification); } break; case Messages::SetOffAlarm: GoToRunning(); + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered); break; case Messages::BleConnected: @@ -226,6 +228,7 @@ void SystemTask::Work() { case Messages::BleFirmwareUpdateStarted: GoToRunning(); wakeLocksHeld++; + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted); break; case Messages::BleFirmwareUpdateFinished: @@ -238,6 +241,7 @@ void SystemTask::Work() { NRF_LOG_INFO("[systemtask] FS Started"); GoToRunning(); wakeLocksHeld++; + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); // TODO add intent of fs access icon or something break; case Messages::StopFileTransfer: @@ -247,11 +251,20 @@ void SystemTask::Work() { break; case Messages::OnTouchEvent: // Finish immediately if no new events - if (!touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) { + Pinetime::Controllers::TouchHandler::TouchProcessReply reply; + reply = + touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo(), + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::ButtonUnlocks)); + if (reply == Pinetime::Controllers::TouchHandler::TouchProcessReply::NoAction) { break; } if (state == SystemTaskState::Running) { - displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); + if (reply == Pinetime::Controllers::TouchHandler::TouchProcessReply::TouchEvent) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); + } else if (reply == Pinetime::Controllers::TouchHandler::TouchProcessReply::IgnoreTouchPopup) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowIgnoreTouchPopup); + touchHandler.SetIgnoreTouchPopupHidden(false); + } } else { // If asleep, check for touch panel wake triggers auto gesture = touchHandler.GestureGet(); @@ -261,24 +274,34 @@ void SystemTask::Work() { settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) || (gesture == Pinetime::Applications::TouchEvents::Tap && settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) { + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction, + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::ButtonUnlocks)); GoToRunning(); } } break; case Messages::HandleButtonEvent: { - Controllers::ButtonActions action = Controllers::ButtonActions::None; - if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { - action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release); + // if the IgnoreTouchPopup is active the first button event unlocks the device + if (!touchHandler.IsIgnoreTouchPopupHidden()) { + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Button, false); + touchHandler.SetIgnoreTouchPopupHidden(true); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup); } else { - action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); - // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping - if (IsSleeping()) { - fastWakeUpDone = true; - GoToRunning(); - break; + Controllers::ButtonActions action = Controllers::ButtonActions::None; + if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { + action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release); + } else { + action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Button, false); + // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping + if (IsSleeping()) { + fastWakeUpDone = true; + GoToRunning(); + break; + } } + HandleButtonAction(action); } - HandleButtonAction(action); } break; case Messages::HandleButtonTimerEvent: { auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer); @@ -314,6 +337,8 @@ void SystemTask::Work() { } else { state = SystemTaskState::AODSleeping; } + // reset touch restrictions when going to sleep + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); break; case Messages::OnNewDay: // We might be sleeping (with TWI device disabled. @@ -325,6 +350,7 @@ void SystemTask::Work() { if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours && !alarmController.IsAlerting()) { GoToRunning(); + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime); } break; @@ -333,12 +359,14 @@ void SystemTask::Work() { if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours && !alarmController.IsAlerting()) { GoToRunning(); + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime); } break; case Messages::OnChargingEvent: batteryController.ReadPowerState(); GoToRunning(); + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent); break; case Messages::MeasureBatteryTimerExpired: @@ -349,6 +377,7 @@ void SystemTask::Work() { break; case Messages::OnPairing: GoToRunning(); + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false); displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey); break; case Messages::BleRadioEnableToggle: @@ -425,6 +454,8 @@ void SystemTask::GoToSleep() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep); } heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep); + touchHandler.SetIgnoreTouchPopupHidden(true); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup); state = SystemTaskState::GoingToSleep; }; @@ -452,6 +483,9 @@ void SystemTask::UpdateMotion() { motionController.ShouldRaiseWake()) || (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) && motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) { + if (state == SystemTaskState::Sleeping) { + touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction, true); + } GoToRunning(); } } diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 0060e36096..3646d8cc94 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -53,6 +53,11 @@ namespace Pinetime { class SystemTask { public: enum class SystemTaskState { Sleeping, Running, GoingToSleep, AODSleeping }; + // Enum describes how the watch was woken: + // * WakeUpAction: The actions selected in the wakeup settings, single/double tap, raise, shake + // * Button: The hardware button + // * Other: Other things that can wake the watch up, eg. apps and notifications. + enum class WokenBy { WakeUpAction, Button, Other }; SystemTask(Drivers::SpiMaster& spi, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Drivers::TwiMaster& twiMaster, diff --git a/src/touchhandler/TouchHandler.cpp b/src/touchhandler/TouchHandler.cpp index b29f951fcb..55d2eff03d 100644 --- a/src/touchhandler/TouchHandler.cpp +++ b/src/touchhandler/TouchHandler.cpp @@ -33,9 +33,9 @@ Pinetime::Applications::TouchEvents TouchHandler::GestureGet() { return returnGesture; } -bool TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info) { +TouchHandler::TouchProcessReply TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn) { if (!info.isValid) { - return false; + return TouchHandler::TouchProcessReply::NoAction; } // Only a single gesture per touch @@ -62,5 +62,19 @@ bool TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info) { currentTouchPoint = {info.x, info.y, info.touching}; - return true; + // if the watch was just woken by touch and button must be used to unlock, ignore the first touch event which + // is the touch event that woke the watch. Otherwise the lock-popup will be displayed + if (buttonUnlocksOn && ignoreNextTouchEvent) { + ignoreNextTouchEvent = false; + return TouchHandler::TouchProcessReply::NoAction; + + } else if (!buttonUnlocksOn || wokenBy != WokenBy::WakeUpAction) { + + // if we get to here TouchEvents is allowed and the "ButtonUnlocks" requirement can be overridden + wokenBy = WokenBy::Other; + + return TouchHandler::TouchProcessReply::TouchEvent; + } else { + return TouchHandler::TouchProcessReply::IgnoreTouchPopup; + } } diff --git a/src/touchhandler/TouchHandler.h b/src/touchhandler/TouchHandler.h index a44822552d..2eb997c614 100644 --- a/src/touchhandler/TouchHandler.h +++ b/src/touchhandler/TouchHandler.h @@ -6,13 +6,25 @@ namespace Pinetime { namespace Controllers { class TouchHandler { public: + // Enum describes how the watch was woken: + // * WakeUpAction: The actions selected in the wakeup settings, single/double tap, raise, shake + // * Button: The hardware button + // * Other: Other things that can wake the watch up, eg. apps and notifications. + enum class WokenBy { WakeUpAction, Button, Other }; + + // Enum describes how the reply from ProcessTouchInfo should be interpreted: + // * NoAction: Do nothing, ignore input. + // * TouchEvent: The input should be treated as a normal touch event. + // * IgnoreTouchPopup: Show the popup when ignoring touch input. + enum class TouchProcessReply { NoAction, TouchEvent, IgnoreTouchPopup }; + struct TouchPoint { int x; int y; bool touching; }; - bool ProcessTouchInfo(Drivers::Cst816S::TouchInfos info); + TouchProcessReply ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn); bool IsTouching() const { return currentTouchPoint.touching; @@ -26,12 +38,29 @@ namespace Pinetime { return currentTouchPoint.y; } + void SetIgnoreTouchPopupHidden(bool hidden) { + ignoreTouchPopupHidden = hidden; + } + + bool IsIgnoreTouchPopupHidden() { + return ignoreTouchPopupHidden; + } + + void SetWokenBy(WokenBy woken, bool ifButtonUnlocksIgnoreTouch) { + wokenBy = woken; + ignoreNextTouchEvent = ifButtonUnlocksIgnoreTouch; + } + Pinetime::Applications::TouchEvents GestureGet(); private: Pinetime::Applications::TouchEvents gesture; TouchPoint currentTouchPoint = {}; bool gestureReleased = true; + + WokenBy wokenBy; + bool ignoreNextTouchEvent = false; + bool ignoreTouchPopupHidden = true; }; } } From ebf45f8757d5631ca17ab07fcc58c8a1d387e266 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Mon, 30 Sep 2024 21:22:20 +0200 Subject: [PATCH 2/4] TouchHandler: default buttonUnlocksOn to false --- src/touchhandler/TouchHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/touchhandler/TouchHandler.h b/src/touchhandler/TouchHandler.h index 2eb997c614..3c5f3c566a 100644 --- a/src/touchhandler/TouchHandler.h +++ b/src/touchhandler/TouchHandler.h @@ -24,7 +24,7 @@ namespace Pinetime { bool touching; }; - TouchProcessReply ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn); + TouchProcessReply ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn = false); bool IsTouching() const { return currentTouchPoint.touching; From b9786ddb3639148721336fbff18aaca1634a9cdd Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sun, 6 Oct 2024 20:13:52 +0200 Subject: [PATCH 3/4] PopupMessage: draw lock with lvgl, hard code size --- src/displayapp/DisplayApp.cpp | 1 - src/displayapp/widgets/PopupMessage.cpp | 47 +++++++++++++++++-------- src/displayapp/widgets/PopupMessage.h | 8 ++--- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index ed667bd920..1b2ba19e26 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -102,7 +102,6 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, spiNorFlash {spiNorFlash}, lvgl {lcd, filesystem}, timer(this, TimerCallback), - popupMessage {Screens::Symbols::lock, 90, 90}, controllers {batteryController, bleController, dateTimeController, diff --git a/src/displayapp/widgets/PopupMessage.cpp b/src/displayapp/widgets/PopupMessage.cpp index 7bfcc97e23..ffcecdca4e 100644 --- a/src/displayapp/widgets/PopupMessage.cpp +++ b/src/displayapp/widgets/PopupMessage.cpp @@ -1,21 +1,40 @@ #include "displayapp/widgets/PopupMessage.h" +#include "displayapp/InfiniTimeTheme.h" #include using namespace Pinetime::Applications::Widgets; -PopupMessage::PopupMessage(const char* msg, int16_t h, int16_t w) : message {msg}, height {h}, width {w} { +PopupMessage::PopupMessage() { } void PopupMessage::Create() { - btnPopup = lv_btn_create(lv_scr_act(), nullptr); - btnPopup->user_data = this; - lv_obj_set_size(btnPopup, height, width); - lv_obj_align(btnPopup, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - lv_obj_set_style_local_bg_opa(btnPopup, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_60); - lv_obj_set_style_local_text_font(btnPopup, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_80); - lv_obj_t* lblMessage = lv_label_create(btnPopup, nullptr); - lv_label_set_text_static(lblMessage, message); - lv_obj_set_hidden(btnPopup, isHidden); + 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) { @@ -24,11 +43,11 @@ void PopupMessage::SetHidden(bool hidden) { } isHidden = hidden; // create/delete on demand - if (btnPopup == nullptr && !isHidden) { + if (popup == nullptr && !isHidden) { Create(); - } else if (btnPopup != nullptr) { - lv_obj_del(btnPopup); - btnPopup = nullptr; + } else if (popup != nullptr) { + lv_obj_del(popup); + popup = nullptr; } } diff --git a/src/displayapp/widgets/PopupMessage.h b/src/displayapp/widgets/PopupMessage.h index ca993912fe..39e16b2c8f 100644 --- a/src/displayapp/widgets/PopupMessage.h +++ b/src/displayapp/widgets/PopupMessage.h @@ -6,18 +6,14 @@ namespace Pinetime { namespace Widgets { class PopupMessage { public: - // The caller owns the message string, it is not copied. - PopupMessage(const char* msg, int16_t h, int16_t w); + PopupMessage(); void Create(); void SetHidden(bool hidden); bool IsHidden(); private: - const char* message; - lv_obj_t* btnPopup = nullptr; + lv_obj_t* popup = nullptr; bool isHidden = true; - int16_t height; - int16_t width; }; } } From a00a8d327e92b7785be84a859634226a31f2ddfc Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sun, 6 Oct 2024 20:17:58 +0200 Subject: [PATCH 4/4] Remove new font, draw with lvgl --- src/displayapp/DisplayApp.cpp | 1 - src/displayapp/fonts/CMakeLists.txt | 2 +- src/displayapp/fonts/fonts.json | 10 ---------- src/displayapp/screens/Symbols.h | 3 --- src/libs/lv_conf.h | 3 +-- 5 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 1b2ba19e26..2feb4ca5b0 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -30,7 +30,6 @@ #include "displayapp/screens/Weather.h" #include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" -#include "displayapp/screens/Symbols.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" diff --git a/src/displayapp/fonts/CMakeLists.txt b/src/displayapp/fonts/CMakeLists.txt index 979e6c5901..562f0801ad 100644 --- a/src/displayapp/fonts/CMakeLists.txt +++ b/src/displayapp/fonts/CMakeLists.txt @@ -1,5 +1,5 @@ set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20 - jetbrains_mono_extrabold_compressed lv_font_sys_48 lv_font_sys_80 + jetbrains_mono_extrabold_compressed lv_font_sys_48 open_sans_light fontawesome_weathericons) find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin") diff --git a/src/displayapp/fonts/fonts.json b/src/displayapp/fonts/fonts.json index 59afed0f5b..41c383c0d4 100644 --- a/src/displayapp/fonts/fonts.json +++ b/src/displayapp/fonts/fonts.json @@ -64,16 +64,6 @@ "bpp": 1, "size": 48 }, - "lv_font_sys_80": { - "sources": [ - { - "file": "material-design-icons/MaterialIcons-Regular.ttf", - "range": "0xe897" - } - ], - "bpp": 1, - "size": 80 - }, "fontawesome_weathericons": { "sources": [ { diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h index 323fc73a87..bd958b285f 100644 --- a/src/displayapp/screens/Symbols.h +++ b/src/displayapp/screens/Symbols.h @@ -64,9 +64,6 @@ namespace Pinetime { static constexpr const char* flashlight = "\xEF\x80\x8B"; static constexpr const char* paintbrushLg = "\xEE\x90\x8A"; - - // wake-up screenlock icon, from material icons - static constexpr const char* lock = "\xEE\xA2\x97"; } } } diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h index 9bf21fb841..c23647f2c0 100644 --- a/src/libs/lv_conf.h +++ b/src/libs/lv_conf.h @@ -419,8 +419,7 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in LV_FONT_DECLARE(jetbrains_mono_76) \ LV_FONT_DECLARE(open_sans_light) \ LV_FONT_DECLARE(fontawesome_weathericons) \ - LV_FONT_DECLARE(lv_font_sys_48) \ - LV_FONT_DECLARE(lv_font_sys_80) + LV_FONT_DECLARE(lv_font_sys_48) /* Enable it if you have fonts with a lot of characters. * The limit depends on the font size, font face and bpp