diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0a97a015..0f1f6266 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/FreeRTOSConfig.h b/src/FreeRTOSConfig.h index 67c33a34..930ec764 100644 --- a/src/FreeRTOSConfig.h +++ b/src/FreeRTOSConfig.h @@ -62,7 +62,7 @@ #define configTICK_RATE_HZ 1024 #define configMAX_PRIORITIES (3) #define configMINIMAL_STACK_SIZE (120) -#define configTOTAL_HEAP_SIZE (1024 * 40) +#define configTOTAL_HEAP_SIZE (1024 * 35) #define configMAX_TASK_NAME_LEN (4) #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 1 diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 602de3a5..356977d7 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 ff43bb81..932129cb 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, @@ -456,6 +458,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; } } @@ -579,7 +587,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 d443b8b2..1b4bee63 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 dcfff4c2..b9e052ad 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -24,6 +24,8 @@ namespace Pinetime { Chime, BleRadioEnableToggle, OnChargingEvent, + ShowIgnoreTouchPopup, + HideIgnoreTouchPopup }; } } diff --git a/src/displayapp/fonts/CMakeLists.txt b/src/displayapp/fonts/CMakeLists.txt index 22627efc..3f032808 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 41c383c0..59afed0f 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 00000000..b670630f --- /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 bd958b28..323fc73a 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 4649dc82..d610ff82 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 61edabce..b7bc4723 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 00000000..7bfcc97e --- /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 00000000..ca993912 --- /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 c23647f2..9bf21fb8 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 fc4e8f7e..cec1fc14 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -199,7 +199,11 @@ void SystemTask::Work() { GoToRunning(); break; case Messages::TouchWakeUp: { - 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::TouchEvent) { auto gesture = touchHandler.GestureGet(); if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && gesture != Pinetime::Applications::TouchEvents::None && @@ -207,6 +211,7 @@ 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, true); GoToRunning(); } } @@ -225,11 +230,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: @@ -240,6 +247,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: @@ -252,6 +260,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: @@ -260,24 +269,39 @@ void SystemTask::Work() { // TODO add intent of fs access icon or something break; case Messages::OnTouchEvent: - 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::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); } 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); @@ -308,6 +332,8 @@ void SystemTask::Work() { } state = SystemTaskState::Sleeping; + // 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. @@ -319,6 +345,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; @@ -327,12 +354,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: @@ -343,6 +372,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: @@ -413,6 +443,8 @@ void SystemTask::GoToSleep() { NRF_LOG_INFO("[systemtask] Going to sleep"); 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; }; @@ -438,6 +470,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 8a4e5954..04984a96 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 }; + // 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 b29f951f..55d2eff0 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 a4482255..3c5f3c56 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 = false); 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; }; } }