Fix button navigation
This commit is contained in:
@@ -72,6 +72,7 @@ void ButtonEventManager::drain() {
|
|||||||
b.releaseTime = 0;
|
b.releaseTime = 0;
|
||||||
}
|
}
|
||||||
eventHead = eventTail = 0;
|
eventHead = eventTail = 0;
|
||||||
|
longPressDispatchedMask = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ButtonEventManager::processButton(const int idx, const Button btn) {
|
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() {
|
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++) {
|
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
processButton(i, ALL_BUTTONS[i]);
|
processButton(i, ALL_BUTTONS[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,17 @@ class ButtonEventManager {
|
|||||||
// ButtonEventManager queries CrossPointSettings internally.
|
// ButtonEventManager queries CrossPointSettings internally.
|
||||||
bool hasDoubleAction(Button button) const;
|
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:
|
private:
|
||||||
static constexpr int NUM_BUTTONS = 9;
|
static constexpr int NUM_BUTTONS = 9;
|
||||||
static constexpr Button ALL_BUTTONS[NUM_BUTTONS] = {
|
static constexpr Button ALL_BUTTONS[NUM_BUTTONS] = {
|
||||||
@@ -79,6 +90,7 @@ class ButtonEventManager {
|
|||||||
};
|
};
|
||||||
|
|
||||||
uint32_t forcedDoubleMask = 0;
|
uint32_t forcedDoubleMask = 0;
|
||||||
|
uint32_t longPressDispatchedMask = 0;
|
||||||
|
|
||||||
enum class State { Idle, Pressed, ReleasedOnce, DoublePressed };
|
enum class State { Idle, Pressed, ReleasedOnce, DoublePressed };
|
||||||
|
|
||||||
|
|||||||
@@ -64,18 +64,6 @@ void EpubReaderChapterSelectionActivity::loop() {
|
|||||||
finish();
|
finish();
|
||||||
return;
|
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(); });
|
buttonNavigator.onNextList(selectorIndex, totalItems, [this] { requestUpdate(); });
|
||||||
|
|||||||
@@ -55,20 +55,6 @@ void MdReaderTocSelectionActivity::loop() {
|
|||||||
finish();
|
finish();
|
||||||
return;
|
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(); });
|
buttonNavigator.onNextList(selectorIndex, totalItems, [this] { requestUpdate(); });
|
||||||
|
|||||||
@@ -115,16 +115,21 @@ inline PageTurnResult detectPageTurn(const MappedInputManager& input) {
|
|||||||
}
|
}
|
||||||
const bool prevButtonReleased = (SETTINGS.btnShortPageBack == BA::BTN_DEFAULT &&
|
const bool prevButtonReleased = (SETTINGS.btnShortPageBack == BA::BTN_DEFAULT &&
|
||||||
!globalButtonEvents().hasDoubleAction(MappedInputManager::Button::PageBack) &&
|
!globalButtonEvents().hasDoubleAction(MappedInputManager::Button::PageBack) &&
|
||||||
|
!globalButtonEvents().wasLongPressDispatched(MappedInputManager::Button::PageBack) &&
|
||||||
input.wasReleased(MappedInputManager::Button::PageBack)) ||
|
input.wasReleased(MappedInputManager::Button::PageBack)) ||
|
||||||
(SETTINGS.btnShortLeft == BA::BTN_DEFAULT &&
|
(SETTINGS.btnShortLeft == BA::BTN_DEFAULT &&
|
||||||
!globalButtonEvents().hasDoubleAction(MappedInputManager::Button::Left) &&
|
!globalButtonEvents().hasDoubleAction(MappedInputManager::Button::Left) &&
|
||||||
|
!globalButtonEvents().wasLongPressDispatched(MappedInputManager::Button::Left) &&
|
||||||
input.wasReleased(MappedInputManager::Button::Left));
|
input.wasReleased(MappedInputManager::Button::Left));
|
||||||
const bool nextButtonReleased = (SETTINGS.btnShortPageForward == BA::BTN_DEFAULT &&
|
const bool nextButtonReleased =
|
||||||
!globalButtonEvents().hasDoubleAction(MappedInputManager::Button::PageForward) &&
|
(SETTINGS.btnShortPageForward == BA::BTN_DEFAULT &&
|
||||||
input.wasReleased(MappedInputManager::Button::PageForward)) ||
|
!globalButtonEvents().hasDoubleAction(MappedInputManager::Button::PageForward) &&
|
||||||
(SETTINGS.btnShortRight == BA::BTN_DEFAULT &&
|
!globalButtonEvents().wasLongPressDispatched(MappedInputManager::Button::PageForward) &&
|
||||||
!globalButtonEvents().hasDoubleAction(MappedInputManager::Button::Right) &&
|
input.wasReleased(MappedInputManager::Button::PageForward)) ||
|
||||||
input.wasReleased(MappedInputManager::Button::Right));
|
(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 prev = tiltPrev || prevButtonReleased;
|
||||||
const bool next = tiltNext || nextButtonReleased;
|
const bool next = tiltNext || nextButtonReleased;
|
||||||
|
|||||||
@@ -71,18 +71,6 @@ void XtcReaderChapterSelectionActivity::loop() {
|
|||||||
finish();
|
finish();
|
||||||
return;
|
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(); });
|
buttonNavigator.onNextList(selectorIndex, totalItems, [this] { requestUpdate(); });
|
||||||
|
|||||||
@@ -532,6 +532,13 @@ void loop() {
|
|||||||
continue;
|
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)) {
|
switch (static_cast<BA>(action)) {
|
||||||
case BA::BTN_PAGE_FORWARD:
|
case BA::BTN_PAGE_FORWARD:
|
||||||
activityManager.dispatchButtonAction(BA::BTN_PAGE_FORWARD);
|
activityManager.dispatchButtonAction(BA::BTN_PAGE_FORWARD);
|
||||||
|
|||||||
@@ -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 bool wasReleased = std::any_of(buttons.begin(), buttons.end(),
|
||||||
[](const MappedInputManager::Button b) { return mappedInput->wasReleased(b); });
|
[](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;
|
longPressFired = false;
|
||||||
return;
|
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 uint32_t now = millis();
|
||||||
const bool isDouble = (now - lastPressMs) < listDoubleClickMs;
|
const bool isDouble = (now - lastPressMs) < listDoubleClickMs;
|
||||||
lastPressMs = now;
|
lastPressMs = now;
|
||||||
|
|||||||
Reference in New Issue
Block a user