diff --git a/src/ButtonEventManager.cpp b/src/ButtonEventManager.cpp index 93d63baf..90f8204d 100644 --- a/src/ButtonEventManager.cpp +++ b/src/ButtonEventManager.cpp @@ -72,6 +72,7 @@ void ButtonEventManager::drain() { b.releaseTime = 0; } eventHead = eventTail = 0; + longPressDispatchedMask = 0; } void ButtonEventManager::processButton(const int idx, const Button btn) { @@ -140,6 +141,14 @@ void ButtonEventManager::processButton(const int idx, const Button btn) { } void ButtonEventManager::update() { + // Clear the long-press-dispatched flag for buttons that are pressed again. + // This allows the flag to survive through the release tick (so detectPageTurn + // can suppress the page-turn on release) and resets cleanly on the next press. + for (int i = 0; i < NUM_BUTTONS; i++) { + if ((longPressDispatchedMask & (1u << i)) && input.wasPressed(ALL_BUTTONS[i])) { + longPressDispatchedMask &= ~(1u << i); + } + } for (int i = 0; i < NUM_BUTTONS; i++) { processButton(i, ALL_BUTTONS[i]); } diff --git a/src/ButtonEventManager.h b/src/ButtonEventManager.h index 3d12e27c..7b9cc77d 100644 --- a/src/ButtonEventManager.h +++ b/src/ButtonEventManager.h @@ -71,6 +71,17 @@ class ButtonEventManager { // ButtonEventManager queries CrossPointSettings internally. bool hasDoubleAction(Button button) const; + // Called by the global dispatcher (main.cpp) when a Long event is consumed for a + // non-default action on a navigation button. Suppresses the release-based page turn + // that would otherwise fire when the button is released after the long action. + void markLongPressDispatched(Button button) { longPressDispatchedMask |= (1u << static_cast(button)); } + + // Returns true if markLongPressDispatched was called for this button since the last + // update(). detectPageTurn() uses this to skip wasReleased-based page turns. + bool wasLongPressDispatched(Button button) const { + return (longPressDispatchedMask & (1u << static_cast(button))) != 0; + } + private: static constexpr int NUM_BUTTONS = 9; static constexpr Button ALL_BUTTONS[NUM_BUTTONS] = { @@ -79,6 +90,7 @@ class ButtonEventManager { }; uint32_t forcedDoubleMask = 0; + uint32_t longPressDispatchedMask = 0; enum class State { Idle, Pressed, ReleasedOnce, DoublePressed }; diff --git a/src/activities/reader/EpubReaderChapterSelectionActivity.cpp b/src/activities/reader/EpubReaderChapterSelectionActivity.cpp index 2e5b8f3a..c07726d6 100644 --- a/src/activities/reader/EpubReaderChapterSelectionActivity.cpp +++ b/src/activities/reader/EpubReaderChapterSelectionActivity.cpp @@ -64,18 +64,6 @@ void EpubReaderChapterSelectionActivity::loop() { finish(); return; } - if ((ev.button == MappedInputManager::Button::PageBack || ev.button == MappedInputManager::Button::Left) && - ev.type == ButtonEventManager::PressType::Short) { - selectorIndex = ButtonNavigator::previousIndex(selectorIndex, totalItems); - requestUpdate(); - return; - } - if ((ev.button == MappedInputManager::Button::PageForward || ev.button == MappedInputManager::Button::Right) && - ev.type == ButtonEventManager::PressType::Short) { - selectorIndex = ButtonNavigator::nextIndex(selectorIndex, totalItems); - requestUpdate(); - return; - } } buttonNavigator.onNextList(selectorIndex, totalItems, [this] { requestUpdate(); }); diff --git a/src/activities/reader/MdReaderTocSelectionActivity.cpp b/src/activities/reader/MdReaderTocSelectionActivity.cpp index 575a789d..a62ea32c 100644 --- a/src/activities/reader/MdReaderTocSelectionActivity.cpp +++ b/src/activities/reader/MdReaderTocSelectionActivity.cpp @@ -55,20 +55,6 @@ void MdReaderTocSelectionActivity::loop() { finish(); return; } - - if ((ev.button == MappedInputManager::Button::PageBack || ev.button == MappedInputManager::Button::Left) && - ev.type == ButtonEventManager::PressType::Short) { - selectorIndex = ButtonNavigator::previousIndex(selectorIndex, totalItems); - requestUpdate(); - return; - } - - if ((ev.button == MappedInputManager::Button::PageForward || ev.button == MappedInputManager::Button::Right) && - ev.type == ButtonEventManager::PressType::Short) { - selectorIndex = ButtonNavigator::nextIndex(selectorIndex, totalItems); - requestUpdate(); - return; - } } buttonNavigator.onNextList(selectorIndex, totalItems, [this] { requestUpdate(); }); diff --git a/src/activities/reader/ReaderUtils.h b/src/activities/reader/ReaderUtils.h index f62b720f..b9c4da94 100644 --- a/src/activities/reader/ReaderUtils.h +++ b/src/activities/reader/ReaderUtils.h @@ -115,16 +115,21 @@ inline PageTurnResult detectPageTurn(const MappedInputManager& input) { } const bool prevButtonReleased = (SETTINGS.btnShortPageBack == BA::BTN_DEFAULT && !globalButtonEvents().hasDoubleAction(MappedInputManager::Button::PageBack) && + !globalButtonEvents().wasLongPressDispatched(MappedInputManager::Button::PageBack) && input.wasReleased(MappedInputManager::Button::PageBack)) || (SETTINGS.btnShortLeft == BA::BTN_DEFAULT && !globalButtonEvents().hasDoubleAction(MappedInputManager::Button::Left) && + !globalButtonEvents().wasLongPressDispatched(MappedInputManager::Button::Left) && input.wasReleased(MappedInputManager::Button::Left)); - const bool nextButtonReleased = (SETTINGS.btnShortPageForward == BA::BTN_DEFAULT && - !globalButtonEvents().hasDoubleAction(MappedInputManager::Button::PageForward) && - input.wasReleased(MappedInputManager::Button::PageForward)) || - (SETTINGS.btnShortRight == BA::BTN_DEFAULT && - !globalButtonEvents().hasDoubleAction(MappedInputManager::Button::Right) && - input.wasReleased(MappedInputManager::Button::Right)); + const bool nextButtonReleased = + (SETTINGS.btnShortPageForward == BA::BTN_DEFAULT && + !globalButtonEvents().hasDoubleAction(MappedInputManager::Button::PageForward) && + !globalButtonEvents().wasLongPressDispatched(MappedInputManager::Button::PageForward) && + input.wasReleased(MappedInputManager::Button::PageForward)) || + (SETTINGS.btnShortRight == BA::BTN_DEFAULT && + !globalButtonEvents().hasDoubleAction(MappedInputManager::Button::Right) && + !globalButtonEvents().wasLongPressDispatched(MappedInputManager::Button::Right) && + input.wasReleased(MappedInputManager::Button::Right)); const bool prev = tiltPrev || prevButtonReleased; const bool next = tiltNext || nextButtonReleased; diff --git a/src/activities/reader/XtcReaderChapterSelectionActivity.cpp b/src/activities/reader/XtcReaderChapterSelectionActivity.cpp index b932771a..7a4befe1 100644 --- a/src/activities/reader/XtcReaderChapterSelectionActivity.cpp +++ b/src/activities/reader/XtcReaderChapterSelectionActivity.cpp @@ -71,18 +71,6 @@ void XtcReaderChapterSelectionActivity::loop() { finish(); return; } - if ((ev.button == MappedInputManager::Button::PageBack || ev.button == MappedInputManager::Button::Left) && - ev.type == ButtonEventManager::PressType::Short) { - selectorIndex = ButtonNavigator::previousIndex(selectorIndex, totalItems); - requestUpdate(); - return; - } - if ((ev.button == MappedInputManager::Button::PageForward || ev.button == MappedInputManager::Button::Right) && - ev.type == ButtonEventManager::PressType::Short) { - selectorIndex = ButtonNavigator::nextIndex(selectorIndex, totalItems); - requestUpdate(); - return; - } } buttonNavigator.onNextList(selectorIndex, totalItems, [this] { requestUpdate(); }); diff --git a/src/main.cpp b/src/main.cpp index 2aa112e9..f46564eb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -532,6 +532,13 @@ void loop() { continue; } + // When a non-default Long action fires for a page-turn button, mark it so that + // detectPageTurn() suppresses the wasReleased-based page turn on button release. + if (ev.type == ButtonEventManager::PressType::Long && + (ev.button == B::Left || ev.button == B::Right || ev.button == B::PageBack || ev.button == B::PageForward)) { + buttonEventManager.markLongPressDispatched(ev.button); + } + switch (static_cast(action)) { case BA::BTN_PAGE_FORWARD: activityManager.dispatchButtonAction(BA::BTN_PAGE_FORWARD); diff --git a/src/util/ButtonNavigator.cpp b/src/util/ButtonNavigator.cpp index 1a901551..28e6eeab 100644 --- a/src/util/ButtonNavigator.cpp +++ b/src/util/ButtonNavigator.cpp @@ -272,15 +272,15 @@ void ButtonNavigator::onListNav(const Buttons& buttons, const bool forward, int& const bool wasReleased = std::any_of(buttons.begin(), buttons.end(), [](const MappedInputManager::Button b) { return mappedInput->wasReleased(b); }); - if (wasReleased) { + if (!wasReleased) return; + + // Long press already fired: reset the guard and skip navigation — the jump-to-end + // already happened on the down-hold, so release produces no additional move. + if (longPressFired) { longPressFired = false; return; } - const bool wasPressed = std::any_of(buttons.begin(), buttons.end(), - [](const MappedInputManager::Button b) { return mappedInput->wasPressed(b); }); - if (!wasPressed) return; - const uint32_t now = millis(); const bool isDouble = (now - lastPressMs) < listDoubleClickMs; lastPressMs = now;