Refactor the original ignore-touch implementation to owrk on latest code

This commit is contained in:
Tomas Groth 2023-05-03 22:16:52 +02:00
parent 020a7fd11d
commit 6f6d870167
11 changed files with 144 additions and 44 deletions

View file

@ -409,6 +409,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

View file

@ -17,6 +17,7 @@ namespace Pinetime {
DoubleTap = 1,
RaiseWrist = 2,
Shake = 3,
ButtonUnlocks = 4,
};
enum class Colors : uint8_t {
White,
@ -226,7 +227,7 @@ namespace Pinetime {
}
};
std::bitset<4> getWakeUpModes() const {
std::bitset<5> getWakeUpModes() const {
return settings.wakeUpMode;
}
@ -267,7 +268,7 @@ namespace Pinetime {
private:
Pinetime::Controllers::FS& fs;
static constexpr uint32_t settingsVersion = 0x0004;
static constexpr uint32_t settingsVersion = 0x0005;
struct SettingsData {
uint32_t version = settingsVersion;
@ -284,7 +285,7 @@ namespace Pinetime {
WatchFaceInfineat watchFaceInfineat;
std::bitset<4> wakeUpMode {0};
std::bitset<5> wakeUpMode {0};
uint16_t shakeWakeThreshold = 150;
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
};

View file

@ -95,7 +95,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
touchHandler {touchHandler},
filesystem {filesystem},
lvgl {lcd, filesystem},
timer(this, TimerCallback) {
timer(this, TimerCallback),
popupMessage {"Touch input\nis ignored,\npush button\nto unlock."} {
}
void DisplayApp::Start(System::BootErrors error) {
@ -363,6 +364,12 @@ void DisplayApp::Refresh() {
RestoreBrightness();
motorController.RunForDuration(15);
break;
case Messages::ShowIgnoreTouchPopup:
popupMessage.SetHidden(false);
break;
case Messages::HideIgnoreTouchPopup:
popupMessage.SetHidden(true);
break;
}
}

View file

@ -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"
@ -96,6 +97,8 @@ namespace Pinetime {
Pinetime::Components::LittleVgl lvgl;
Pinetime::Controllers::Timer timer;
Pinetime::Applications::Widgets::PopupMessage popupMessage;
TaskHandle_t taskHandle;
States state = States::Running;

View file

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

View file

@ -8,7 +8,7 @@
using namespace Pinetime::Applications::Screens;
constexpr std::array<SettingWakeUp::Option, 4> SettingWakeUp::options;
constexpr std::array<SettingWakeUp::Option, 5> SettingWakeUp::options;
namespace {
void event_handler(lv_obj_t* obj, lv_event_t event) {
@ -27,9 +27,9 @@ SettingWakeUp::SettingWakeUp(Pinetime::Controllers::Settings& settingsController
lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_pos(container1, 10, 60);
lv_obj_set_pos(container1, 10, 30);
lv_obj_set_width(container1, LV_HOR_RES - 20);
lv_obj_set_height(container1, LV_VER_RES - 50);
lv_obj_set_height(container1, LV_VER_RES - 40);
lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT);
lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);

View file

@ -25,11 +25,12 @@ namespace Pinetime {
};
Controllers::Settings& settingsController;
static constexpr std::array<Option, 4> options = {{
static constexpr std::array<Option, 5> 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::ButtonUnlocks, "Button Unlock"},
}};
lv_obj_t* cbOption[options.size()];

View file

@ -214,7 +214,9 @@ void SystemTask::Work() {
state = SystemTaskState::Running;
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 &&
@ -222,12 +224,16 @@ void SystemTask::Work() {
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
(gesture == Pinetime::Applications::TouchEvents::Tap &&
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
touchHandler.SetIfButtonUnlocksIgnoreTouch(true);
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction);
GoToRunning();
}
}
break;
}
case Messages::GoToSleep:
touchHandler.SetIgnoreTouchPopupHidden(true);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup);
if (doNotGoToSleep) {
break;
}
@ -291,24 +297,42 @@ 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));
NRF_LOG_INFO("[systemtask] OnTouchEvent, reply %d", reply);
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);
} 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;
}
// if the IgnoreTouchPopup is active the first button event unlocks the device
if (!touchHandler.IsIgnoreTouchPopupHidden()) {
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Button);
touchHandler.SetIfButtonUnlocksIgnoreTouch(false);
touchHandler.SetIgnoreTouchPopupHidden(true);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::HideIgnoreTouchPopup);
}
else {
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);
touchHandler.SetIfButtonUnlocksIgnoreTouch(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);
@ -328,6 +352,8 @@ void SystemTask::Work() {
}
state = SystemTaskState::Sleeping;
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::Other);
touchHandler.SetIfButtonUnlocksIgnoreTouch(false);
break;
case Messages::OnNewDay:
// We might be sleeping (with TWI device disabled.
@ -433,6 +459,8 @@ void SystemTask::UpdateMotion() {
motionController.ShouldRaiseWake(state == SystemTaskState::Sleeping)) ||
(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) &&
motionController.ShouldShakeWake(settingsController.GetShakeThreshold()))) {
touchHandler.SetWokenBy(Pinetime::Controllers::TouchHandler::WokenBy::WakeUpAction);
touchHandler.SetIfButtonUnlocksIgnoreTouch(true);
GoToRunning();
}
}

View file

@ -53,6 +53,11 @@ namespace Pinetime {
class SystemTask {
public:
enum class SystemTaskState { Sleeping, Running, GoingToSleep, WakingUp };
// 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,

View file

@ -33,34 +33,51 @@ 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
if (info.gesture != Pinetime::Drivers::Cst816S::Gestures::None) {
if (gestureReleased) {
if (info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideDown ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideLeft ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideUp ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideRight ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::LongPress) {
if (info.touching) {
// 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;
// Only a single gesture per touch
if (info.gesture != Pinetime::Drivers::Cst816S::Gestures::None) {
if (gestureReleased) {
if (info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideDown ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideLeft ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideUp ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideRight ||
info.gesture == Pinetime::Drivers::Cst816S::Gestures::LongPress) {
if (info.touching) {
gesture = ConvertGesture(info.gesture);
gestureReleased = false;
}
} else {
gesture = ConvertGesture(info.gesture);
gestureReleased = false;
}
} else {
gesture = ConvertGesture(info.gesture);
}
}
if (!info.touching) {
gestureReleased = true;
}
currentTouchPoint = {info.x, info.y, info.touching};
return TouchHandler::TouchProcessReply::TouchEvent;
}
if (!info.touching) {
gestureReleased = true;
else
{
return TouchHandler::TouchProcessReply::IgnoreTouchPopup;
}
currentTouchPoint = {info.x, info.y, info.touching};
return true;
}

View file

@ -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 for when ignoring touvh 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,35 @@ namespace Pinetime {
return currentTouchPoint.y;
}
void SetIfButtonUnlocksIgnoreTouch(bool ignore)
{
ignoreNextTouchEvent = ignore;
}
void SetIgnoreTouchPopupHidden(bool hidden)
{
ignoreTouchPopupHidden = hidden;
}
bool IsIgnoreTouchPopupHidden()
{
return ignoreTouchPopupHidden;
}
void SetWokenBy(WokenBy woken)
{
wokenBy = woken;
}
Pinetime::Applications::TouchEvents GestureGet();
private:
Pinetime::Applications::TouchEvents gesture;
TouchPoint currentTouchPoint = {};
bool gestureReleased = true;
WokenBy wokenBy;
bool ignoreNextTouchEvent = false;
bool ignoreTouchPopupHidden = true;
};
}
}