This commit is contained in:
tgc-dk 2024-10-03 20:24:04 +00:00 committed by GitHub
commit 90a71175a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 288 additions and 34 deletions

View file

@ -402,6 +402,7 @@ list(APPEND SOURCE_FILES
displayapp/widgets/PageIndicator.cpp displayapp/widgets/PageIndicator.cpp
displayapp/widgets/DotIndicator.cpp displayapp/widgets/DotIndicator.cpp
displayapp/widgets/StatusIcons.cpp displayapp/widgets/StatusIcons.cpp
displayapp/widgets/PopupMessage.cpp
## Settings ## Settings
displayapp/screens/settings/QuickSettings.cpp displayapp/screens/settings/QuickSettings.cpp

View file

@ -62,7 +62,7 @@
#define configTICK_RATE_HZ 1024 #define configTICK_RATE_HZ 1024
#define configMAX_PRIORITIES (3) #define configMAX_PRIORITIES (3)
#define configMINIMAL_STACK_SIZE (120) #define configMINIMAL_STACK_SIZE (120)
#define configTOTAL_HEAP_SIZE (1024 * 40) #define configTOTAL_HEAP_SIZE (1024 * 35)
#define configMAX_TASK_NAME_LEN (4) #define configMAX_TASK_NAME_LEN (4)
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1 #define configIDLE_SHOULD_YIELD 1

View file

@ -13,7 +13,14 @@ namespace Pinetime {
enum class WeatherFormat : uint8_t { Metric, Imperial }; enum class WeatherFormat : uint8_t { Metric, Imperial };
enum class Notification : uint8_t { On, Off, Sleep }; enum class Notification : uint8_t { On, Off, Sleep };
enum class ChimesOption : uint8_t { None, Hours, HalfHours }; 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 { enum class Colors : uint8_t {
White, White,
Silver, Silver,
@ -260,7 +267,7 @@ namespace Pinetime {
} }
}; };
std::bitset<5> getWakeUpModes() const { std::bitset<6> getWakeUpModes() const {
return settings.wakeUpMode; return settings.wakeUpMode;
} }
@ -321,7 +328,7 @@ namespace Pinetime {
WatchFaceInfineat watchFaceInfineat; WatchFaceInfineat watchFaceInfineat;
std::bitset<5> wakeUpMode {0}; std::bitset<6> wakeUpMode {0};
uint16_t shakeWakeThreshold = 150; uint16_t shakeWakeThreshold = 150;
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium; Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;

View file

@ -30,6 +30,7 @@
#include "displayapp/screens/Weather.h" #include "displayapp/screens/Weather.h"
#include "displayapp/screens/PassKey.h" #include "displayapp/screens/PassKey.h"
#include "displayapp/screens/Error.h" #include "displayapp/screens/Error.h"
#include "displayapp/screens/Symbols.h"
#include "drivers/Cst816s.h" #include "drivers/Cst816s.h"
#include "drivers/St7789.h" #include "drivers/St7789.h"
@ -101,6 +102,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
spiNorFlash {spiNorFlash}, spiNorFlash {spiNorFlash},
lvgl {lcd, filesystem}, lvgl {lcd, filesystem},
timer(this, TimerCallback), timer(this, TimerCallback),
popupMessage {Screens::Symbols::lock, 90, 90},
controllers {batteryController, controllers {batteryController,
bleController, bleController,
dateTimeController, dateTimeController,
@ -456,6 +458,12 @@ void DisplayApp::Refresh() {
case Messages::OnChargingEvent: case Messages::OnChargingEvent:
motorController.RunForDuration(15); motorController.RunForDuration(15);
break; 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<Screens::SettingWeatherFormat>(settingsController); currentScreen = std::make_unique<Screens::SettingWeatherFormat>(settingsController);
break; break;
case Apps::SettingWakeUp: case Apps::SettingWakeUp:
currentScreen = std::make_unique<Screens::SettingWakeUp>(settingsController); currentScreen = std::make_unique<Screens::SettingWakeUp>(this, settingsController);
break; break;
case Apps::SettingDisplay: case Apps::SettingDisplay:
currentScreen = std::make_unique<Screens::SettingDisplay>(settingsController); currentScreen = std::make_unique<Screens::SettingDisplay>(settingsController);

View file

@ -15,6 +15,7 @@
#include "components/timer/Timer.h" #include "components/timer/Timer.h"
#include "components/alarm/AlarmController.h" #include "components/alarm/AlarmController.h"
#include "touchhandler/TouchHandler.h" #include "touchhandler/TouchHandler.h"
#include "displayapp/widgets/PopupMessage.h"
#include "displayapp/Messages.h" #include "displayapp/Messages.h"
#include "BootErrors.h" #include "BootErrors.h"
@ -102,8 +103,10 @@ namespace Pinetime {
Pinetime::Controllers::FirmwareValidator validator; Pinetime::Controllers::FirmwareValidator validator;
Pinetime::Components::LittleVgl lvgl; Pinetime::Components::LittleVgl lvgl;
Pinetime::Controllers::Timer timer; Pinetime::Controllers::Timer timer;
Pinetime::Applications::Widgets::PopupMessage popupMessage;
AppControllers controllers; AppControllers controllers;
TaskHandle_t taskHandle; TaskHandle_t taskHandle;
States state = States::Running; States state = States::Running;

View file

@ -24,6 +24,8 @@ namespace Pinetime {
Chime, Chime,
BleRadioEnableToggle, BleRadioEnableToggle,
OnChargingEvent, OnChargingEvent,
ShowIgnoreTouchPopup,
HideIgnoreTouchPopup
}; };
} }
} }

View file

@ -1,5 +1,5 @@
set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20 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) open_sans_light fontawesome_weathericons)
find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED
HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin") HINTS "${CMAKE_SOURCE_DIR}/node_modules/.bin")

View file

@ -64,6 +64,16 @@
"bpp": 1, "bpp": 1,
"size": 48 "size": 48
}, },
"lv_font_sys_80": {
"sources": [
{
"file": "material-design-icons/MaterialIcons-Regular.ttf",
"range": "0xe897"
}
],
"bpp": 1,
"size": 80
},
"fontawesome_weathericons": { "fontawesome_weathericons": {
"sources": [ "sources": [
{ {

View file

@ -0,0 +1,29 @@
#pragma once
#include <cstdint>
#include <lvgl/lvgl.h>
#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;
};
}
}
}

View file

@ -64,6 +64,9 @@ namespace Pinetime {
static constexpr const char* flashlight = "\xEF\x80\x8B"; static constexpr const char* flashlight = "\xEF\x80\x8B";
static constexpr const char* paintbrushLg = "\xEE\x90\x8A"; static constexpr const char* paintbrushLg = "\xEE\x90\x8A";
// wake-up screenlock icon, from material icons
static constexpr const char* lock = "\xEE\xA2\x97";
} }
} }
} }

View file

@ -8,7 +8,17 @@
using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications::Screens;
constexpr std::array<SettingWakeUp::Option, 5> SettingWakeUp::options; constexpr std::array<SettingWakeUp::Option, SettingWakeUp::numOptions> SettingWakeUp::options;
auto SettingWakeUp::CreateScreenList() {
std::array<std::function<std::unique_ptr<Screen>()>, nScreens> screens;
for (size_t i = 0; i < screens.size(); i++) {
screens[i] = [this, i]() -> std::unique_ptr<Screen> {
return CreateScreen(i);
};
}
return screens;
}
namespace { namespace {
void event_handler(lv_obj_t* obj, lv_event_t event) { 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<Screen> SettingWakeUp::CreateScreen(size_t screenNum) {
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr); 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); 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_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); 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); cbOption[i] = lv_checkbox_create(container1, nullptr);
lv_checkbox_set_text(cbOption[i], options[i].name); lv_checkbox_set_text(cbOption[i], options[i].name);
if (settingsController.isWakeUpModeOn(static_cast<Controllers::Settings::WakeUpMode>(i))) { if (settingsController.isWakeUpModeOn(options[i].wakeUpMode)) {
lv_checkbox_set_checked(cbOption[i], true); lv_checkbox_set_checked(cbOption[i], true);
} }
cbOption[i]->user_data = this; cbOption[i]->user_data = this;
lv_obj_set_event_cb(cbOption[i], event_handler); lv_obj_set_event_cb(cbOption[i], event_handler);
} }
return std::make_unique<Screens::Page>(screenNum, nScreens, container1);
} }
SettingWakeUp::~SettingWakeUp() { bool SettingWakeUp::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
lv_obj_clean(lv_scr_act()); return screens.OnTouchEvent(event);
settingsController.SaveSettings();
} }
void SettingWakeUp::UpdateSelected(lv_obj_t* object) { 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. // for example, when setting SingleTap, DoubleTap is unset and vice versa.
auto modes = settingsController.getWakeUpModes(); auto modes = settingsController.getWakeUpModes();
for (size_t i = 0; i < options.size(); ++i) { 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]);
}
} }
} }

View file

@ -4,7 +4,10 @@
#include <cstdint> #include <cstdint>
#include <lvgl/lvgl.h> #include <lvgl/lvgl.h>
#include "components/settings/Settings.h" #include "components/settings/Settings.h"
#include "displayapp/screens/Page.h"
#include "displayapp/screens/Screen.h" #include "displayapp/screens/Screen.h"
#include "displayapp/screens/ScreenList.h"
#include "displayapp/widgets/PageIndicator.h"
namespace Pinetime { namespace Pinetime {
@ -13,27 +16,40 @@ namespace Pinetime {
class SettingWakeUp : public Screen { class SettingWakeUp : public Screen {
public: public:
SettingWakeUp(Pinetime::Controllers::Settings& settingsController); SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController);
~SettingWakeUp() override; ~SettingWakeUp() override;
void UpdateSelected(lv_obj_t* object); void UpdateSelected(lv_obj_t* object);
bool OnTouchEvent(TouchEvents event) override;
private: private:
auto CreateScreenList();
std::unique_ptr<Screen> CreateScreen(size_t screenNum);
struct Option { struct Option {
Controllers::Settings::WakeUpMode wakeUpMode; Controllers::Settings::WakeUpMode wakeUpMode;
const char* name; const char* name;
}; };
static constexpr size_t numOptions = 6;
static constexpr size_t optionsPerScreen = 4;
static constexpr size_t nScreens = 2;
Controllers::Settings& settingsController; Controllers::Settings& settingsController;
static constexpr std::array<Option, 5> options = {{
ScreenList<nScreens> screens;
static constexpr std::array<Option, numOptions> options = {{
{Controllers::Settings::WakeUpMode::SingleTap, "Single Tap"}, {Controllers::Settings::WakeUpMode::SingleTap, "Single Tap"},
{Controllers::Settings::WakeUpMode::DoubleTap, "Double Tap"}, {Controllers::Settings::WakeUpMode::DoubleTap, "Double Tap"},
{Controllers::Settings::WakeUpMode::RaiseWrist, "Raise Wrist"}, {Controllers::Settings::WakeUpMode::RaiseWrist, "Raise Wrist"},
{Controllers::Settings::WakeUpMode::Shake, "Shake Wake"}, {Controllers::Settings::WakeUpMode::Shake, "Shake Wake"},
{Controllers::Settings::WakeUpMode::LowerWrist, "Lower Wrist"}, {Controllers::Settings::WakeUpMode::LowerWrist, "Lower Wrist"},
{Controllers::Settings::WakeUpMode::ButtonUnlocks, "Button Unlock"},
}}; }};
lv_obj_t* cbOption[options.size()]; std::array<lv_obj_t*, numOptions> cbOption;
}; };
} }
} }

View file

@ -0,0 +1,37 @@
#include "displayapp/widgets/PopupMessage.h"
#include <libraries/log/nrf_log.h>
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;
}

View file

@ -0,0 +1,24 @@
#pragma once
#include <lvgl/lvgl.h>
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;
};
}
}
}

View file

@ -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(jetbrains_mono_76) \
LV_FONT_DECLARE(open_sans_light) \ LV_FONT_DECLARE(open_sans_light) \
LV_FONT_DECLARE(fontawesome_weathericons) \ 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. /* Enable it if you have fonts with a lot of characters.
* The limit depends on the font size, font face and bpp * The limit depends on the font size, font face and bpp

View file

@ -199,7 +199,11 @@ void SystemTask::Work() {
GoToRunning(); GoToRunning();
break; break;
case Messages::TouchWakeUp: { 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(); auto gesture = touchHandler.GestureGet();
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
gesture != Pinetime::Applications::TouchEvents::None && gesture != Pinetime::Applications::TouchEvents::None &&
@ -207,6 +211,7 @@ void SystemTask::Work() {
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) || settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
(gesture == Pinetime::Applications::TouchEvents::Tap && (gesture == Pinetime::Applications::TouchEvents::Tap &&
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) { settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction, true);
GoToRunning(); GoToRunning();
} }
} }
@ -225,11 +230,13 @@ void SystemTask::Work() {
if (IsSleeping()) { if (IsSleeping()) {
GoToRunning(); GoToRunning();
} }
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification); displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
} }
break; break;
case Messages::SetOffAlarm: case Messages::SetOffAlarm:
GoToRunning(); GoToRunning();
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered); displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
break; break;
case Messages::BleConnected: case Messages::BleConnected:
@ -240,6 +247,7 @@ void SystemTask::Work() {
case Messages::BleFirmwareUpdateStarted: case Messages::BleFirmwareUpdateStarted:
GoToRunning(); GoToRunning();
wakeLocksHeld++; wakeLocksHeld++;
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted); displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
break; break;
case Messages::BleFirmwareUpdateFinished: case Messages::BleFirmwareUpdateFinished:
@ -252,6 +260,7 @@ void SystemTask::Work() {
NRF_LOG_INFO("[systemtask] FS Started"); NRF_LOG_INFO("[systemtask] FS Started");
GoToRunning(); GoToRunning();
wakeLocksHeld++; wakeLocksHeld++;
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
// TODO add intent of fs access icon or something // TODO add intent of fs access icon or something
break; break;
case Messages::StopFileTransfer: case Messages::StopFileTransfer:
@ -260,24 +269,39 @@ void SystemTask::Work() {
// TODO add intent of fs access icon or something // TODO add intent of fs access icon or something
break; break;
case Messages::OnTouchEvent: 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); 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; break;
case Messages::HandleButtonEvent: { case Messages::HandleButtonEvent: {
Controllers::ButtonActions action = Controllers::ButtonActions::None; // if the IgnoreTouchPopup is active the first button event unlocks the device
if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { if (!touchHandler.IsIgnoreTouchPopupHidden()) {
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release); touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Button, false);
touchHandler.SetIgnoreTouchPopupHidden(true);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup);
} else { } else {
action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); Controllers::ButtonActions action = Controllers::ButtonActions::None;
// This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) {
if (IsSleeping()) { action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release);
fastWakeUpDone = true; } else {
GoToRunning(); action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press);
break; 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; } break;
case Messages::HandleButtonTimerEvent: { case Messages::HandleButtonTimerEvent: {
auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer); auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer);
@ -308,6 +332,8 @@ void SystemTask::Work() {
} }
state = SystemTaskState::Sleeping; state = SystemTaskState::Sleeping;
// reset touch restrictions when going to sleep
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
break; break;
case Messages::OnNewDay: case Messages::OnNewDay:
// We might be sleeping (with TWI device disabled. // We might be sleeping (with TWI device disabled.
@ -319,6 +345,7 @@ void SystemTask::Work() {
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours && !alarmController.IsAlerting()) { settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::Hours && !alarmController.IsAlerting()) {
GoToRunning(); GoToRunning();
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime); displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
} }
break; break;
@ -327,12 +354,14 @@ void SystemTask::Work() {
if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep && if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours && !alarmController.IsAlerting()) { settingsController.GetChimeOption() == Controllers::Settings::ChimesOption::HalfHours && !alarmController.IsAlerting()) {
GoToRunning(); GoToRunning();
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime); displayApp.PushMessage(Pinetime::Applications::Display::Messages::Chime);
} }
break; break;
case Messages::OnChargingEvent: case Messages::OnChargingEvent:
batteryController.ReadPowerState(); batteryController.ReadPowerState();
GoToRunning(); GoToRunning();
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent); displayApp.PushMessage(Applications::Display::Messages::OnChargingEvent);
break; break;
case Messages::MeasureBatteryTimerExpired: case Messages::MeasureBatteryTimerExpired:
@ -343,6 +372,7 @@ void SystemTask::Work() {
break; break;
case Messages::OnPairing: case Messages::OnPairing:
GoToRunning(); GoToRunning();
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other, false);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey); displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey);
break; break;
case Messages::BleRadioEnableToggle: case Messages::BleRadioEnableToggle:
@ -413,6 +443,8 @@ void SystemTask::GoToSleep() {
NRF_LOG_INFO("[systemtask] Going to sleep"); NRF_LOG_INFO("[systemtask] Going to sleep");
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep); displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep); heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
touchHandler.SetIgnoreTouchPopupHidden(true);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup);
state = SystemTaskState::GoingToSleep; state = SystemTaskState::GoingToSleep;
}; };
@ -438,6 +470,9 @@ void SystemTask::UpdateMotion() {
motionController.ShouldRaiseWake()) || motionController.ShouldRaiseWake()) ||
(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) && (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) &&
motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) { motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) {
if (state == SystemTaskState::Sleeping) {
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction, true);
}
GoToRunning(); GoToRunning();
} }
} }

View file

@ -53,6 +53,11 @@ namespace Pinetime {
class SystemTask { class SystemTask {
public: public:
enum class SystemTaskState { Sleeping, Running, GoingToSleep }; 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, SystemTask(Drivers::SpiMaster& spi,
Pinetime::Drivers::SpiNorFlash& spiNorFlash, Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Drivers::TwiMaster& twiMaster, Drivers::TwiMaster& twiMaster,

View file

@ -33,9 +33,9 @@ Pinetime::Applications::TouchEvents TouchHandler::GestureGet() {
return returnGesture; return returnGesture;
} }
bool TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info) { TouchHandler::TouchProcessReply TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn) {
if (!info.isValid) { if (!info.isValid) {
return false; return TouchHandler::TouchProcessReply::NoAction;
} }
// Only a single gesture per touch // Only a single gesture per touch
@ -62,5 +62,19 @@ bool TouchHandler::ProcessTouchInfo(Drivers::Cst816S::TouchInfos info) {
currentTouchPoint = {info.x, info.y, info.touching}; 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;
}
} }

View file

@ -6,13 +6,25 @@ namespace Pinetime {
namespace Controllers { namespace Controllers {
class TouchHandler { class TouchHandler {
public: 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 { struct TouchPoint {
int x; int x;
int y; int y;
bool touching; bool touching;
}; };
bool ProcessTouchInfo(Drivers::Cst816S::TouchInfos info); TouchProcessReply ProcessTouchInfo(Drivers::Cst816S::TouchInfos info, bool buttonUnlocksOn = false);
bool IsTouching() const { bool IsTouching() const {
return currentTouchPoint.touching; return currentTouchPoint.touching;
@ -26,12 +38,29 @@ namespace Pinetime {
return currentTouchPoint.y; 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(); Pinetime::Applications::TouchEvents GestureGet();
private: private:
Pinetime::Applications::TouchEvents gesture; Pinetime::Applications::TouchEvents gesture;
TouchPoint currentTouchPoint = {}; TouchPoint currentTouchPoint = {};
bool gestureReleased = true; bool gestureReleased = true;
WokenBy wokenBy;
bool ignoreNextTouchEvent = false;
bool ignoreTouchPopupHidden = true;
}; };
} }
} }