Fix button navigation

This commit is contained in:
jpirnay
2026-05-14 18:44:49 +02:00
parent c9060df3e4
commit 07bdb10842
8 changed files with 44 additions and 49 deletions
+9
View File
@@ -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]);
}
+12
View File
@@ -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<int>(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<int>(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 };
@@ -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(); });
@@ -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(); });
+11 -6
View File
@@ -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;
@@ -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(); });
+7
View File
@@ -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<BA>(action)) {
case BA::BTN_PAGE_FORWARD:
activityManager.dispatchButtonAction(BA::BTN_PAGE_FORWARD);
+5 -5
View File
@@ -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;