diff --git a/src/hal/Power.cpp b/src/hal/Power.cpp index 043b90b..e9b2859 100644 --- a/src/hal/Power.cpp +++ b/src/hal/Power.cpp @@ -48,11 +48,22 @@ uint8_t Power::percentToPWM(uint8_t pct) const { void Power::activity() { _lastActivity = millis(); + if (_state == SCREEN_OFF) { + _justWokeFromOff = true; + } if (_state != ACTIVE) { setState(ACTIVE); } } +void Power::forceScreenOff() { + if (_justWokeFromOff) { + _justWokeFromOff = false; + return; + } + setState(SCREEN_OFF); +} + void Power::weakActivity() { _lastActivity = millis(); // Trackball wakes from DIM but not from SCREEN_OFF @@ -96,6 +107,8 @@ void Power::loop() { case SCREEN_OFF: break; } + + _justWokeFromOff = false; } void Power::setState(State newState) { diff --git a/src/hal/Power.h b/src/hal/Power.h index 565dbbf..2eb4740 100644 --- a/src/hal/Power.h +++ b/src/hal/Power.h @@ -15,6 +15,9 @@ public: void activity(); // Weak activity = trackball — wakes from DIM only, not SCREEN_OFF void weakActivity(); + // Manual screen-off; no-op if activity() just woke from SCREEN_OFF this tick + // so a single keypress can't both wake and re-sleep. + void forceScreenOff(); // Battery float batteryVoltage() const; @@ -57,4 +60,5 @@ private: static constexpr uint8_t DIM_PWM = 40; // ~15% PWM when dimmed bool _kbAutoOn = false; bool _kbAutoOff = false; + bool _justWokeFromOff = false; }; diff --git a/src/input/InputManager.cpp b/src/input/InputManager.cpp index 5c659b3..c0b7bca 100644 --- a/src/input/InputManager.cpp +++ b/src/input/InputManager.cpp @@ -31,8 +31,11 @@ void InputManager::update() { _activity = true; // Movement is weak — only wakes from dim } - // Generate nav events from trackball movement (click handled below via GPIO) - if (!_hasKey) { + // Generate nav events from trackball movement (click handled below via GPIO). + // Skip entirely when screen is off so a backpacked device doesn't accumulate + // phantom up/down/left/right keypresses or wake from movement. + bool screenOn = !_powerMgr || _powerMgr->isScreenOn(); + if (!_hasKey && screenOn) { unsigned long now = millis(); // Accumulate deltas, clamp to ±20 @@ -85,11 +88,16 @@ void InputManager::update() { _clickPending = true; _longPressFired = false; _clickStartMs = millis(); + // Capture screen state BEFORE activity wakes it, so long-press + // doesn't blank a freshly-woken screen (wake-then-blank ping-pong) + _clickFromScreenOn = _powerMgr ? _powerMgr->isScreenOn() : true; _activity = true; _strongActivity = true; // Click wakes from screen off } else if (!_longPressFired && millis() - _clickStartMs >= LONG_PRESS_MS) { - // Long press threshold reached - _longPress = true; + // Long press threshold reached — only emit if click started screen-on + if (_clickFromScreenOn) { + _longPress = true; + } _longPressFired = true; _hasKey = false; // Suppress any concurrent events _activity = true; @@ -117,8 +125,10 @@ void InputManager::update() { } } - // Touch activity check — throttled to ~50Hz - if (_touch) { + // Touch activity check — throttled to ~50Hz. + // Suppressed while screen is off (pocket-carry safety: prevents + // accidental wakes from pressure on the touch panel). + if (_touch && (!_powerMgr || _powerMgr->isScreenOn())) { unsigned long now = millis(); if (now - _lastTouchPoll >= TOUCH_POLL_MS) { _lastTouchPoll = now; diff --git a/src/input/InputManager.h b/src/input/InputManager.h index 341bc8e..923c6b3 100644 --- a/src/input/InputManager.h +++ b/src/input/InputManager.h @@ -3,10 +3,12 @@ #include "hal/Keyboard.h" #include "hal/Trackball.h" #include "hal/TouchInput.h" +#include "hal/Power.h" class InputManager { public: void begin(Keyboard* kb, Trackball* tb, TouchInput* touch); + void setPowerMgr(Power* pm) { _powerMgr = pm; } void update(); // Keyboard events @@ -26,6 +28,7 @@ private: Keyboard* _kb = nullptr; Trackball* _tb = nullptr; TouchInput* _touch = nullptr; + Power* _powerMgr = nullptr; bool _hasKey = false; KeyEvent _keyEvent; @@ -34,6 +37,7 @@ private: bool _longPress = false; bool _clickPending = false; bool _longPressFired = false; + bool _clickFromScreenOn = true; // Captured at click DOWN to gate long-press unsigned long _clickStartMs = 0; unsigned long _lastClickDownMs = 0; static constexpr unsigned long LONG_PRESS_MS = 1200; diff --git a/src/main.cpp b/src/main.cpp index ad1f808..cbf5884 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -456,6 +456,7 @@ void setup() { // Step 10: Input manager inputManager.begin(&keyboard, &trackball, &touch); + inputManager.setPowerMgr(&powerMgr); // Step 10.5: LVGL input drivers LvInput::init(&keyboard, &trackball, &touch); @@ -956,9 +957,11 @@ void loop() { powerMgr.weakActivity(); // Trackball: wake from dim only } - // 2. Long-press dispatch + // 2. Long-press dispatch — screen blanking is the default if no screen consumes it if (inputManager.hadLongPress()) { - ui.handleLongPress(); + if (!ui.handleLongPress()) { + powerMgr.forceScreenOff(); + } } // 3. Key event dispatch