Compare commits

...
Author SHA1 Message Date
Uri Tauber 205fa71c16 chore: remove unnesessary swallowing code 2026-08-13 00:25:57 +03:00
26 changed files with 76 additions and 260 deletions

No files matched your search

+2 -2
View File
@@ -42,11 +42,11 @@ void UiListActivity::onRowAction(const fui::ActionEvent& event) {
}
bool UiListActivity::handleButtons() {
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
onBackButton();
return true;
}
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
const int selected = activeNav().selected;
if (selected >= 0 && selected < listCount()) activateIndex(selected);
return true;
@@ -51,8 +51,6 @@ void OpdsBookBrowserActivity::onEnter() {
searchTemplate = "";
currentPath = "";
selectorIndex = 0;
consumeConfirm = false;
consumeBack = false;
errorMessage.clear();
statusMessage = tr(STR_CHECKING_WIFI);
@@ -115,15 +113,6 @@ void OpdsBookBrowserActivity::loop() {
return;
}
if (consumeConfirm && mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
consumeConfirm = false;
return;
}
if (consumeBack && mappedInput.wasReleased(MappedInputManager::Button::Back)) {
consumeBack = false;
return;
}
if (state == BrowserState::ERROR) {
int tx = 0;
int ty = 0;
@@ -555,10 +544,6 @@ void OpdsBookBrowserActivity::launchSearch() {
auto keyboard = std::make_unique<KeyboardEntryActivity>(renderer, mappedInput, tr(STR_SEARCH));
startActivityForResult(std::move(keyboard), [this](const ActivityResult& result) {
// Swallow the release of the Confirm press that closed the keyboard only
// when that button is actually still held on resume — a blanket flag set
// at launch went stale on touch flows and ate the next genuine Confirm.
consumeConfirm = mappedInput.isPressed(MappedInputManager::Button::Confirm);
state = BrowserState::BROWSING;
if (!result.isCancelled) {
performSearch(std::get<KeyboardResult>(result.data).text);
@@ -37,8 +37,6 @@ class OpdsBookBrowserActivity final : public Activity, private UiAppHost {
std::vector<std::string> navigationHistory;
std::string currentPath;
std::string searchTemplate;
bool consumeConfirm = false;
bool consumeBack = false;
int selectorIndex = 0;
std::string errorMessage;
std::string statusMessage;
+4 -24
View File
@@ -110,17 +110,11 @@ void FileBrowserActivity::onEnter() {
return;
}
// If Confirm was held while this activity opened (typical when launched from a menu), ignore
// its release — otherwise we'd immediately auto-open whatever is at index 0.
lockNextConfirmRelease = mappedInput.isPressed(MappedInputManager::Button::Confirm);
auto root = Storage.open(basepath.c_str());
if (!root) {
basepath = "/";
loadFiles();
} else if (!root.isDirectory()) {
lockLongPressBack = mappedInput.isPressed(MappedInputManager::Button::Back);
const std::string oldPath = basepath;
basepath = FsHelpers::extractFolderPath(basepath);
loadFiles();
@@ -240,11 +234,7 @@ void FileBrowserActivity::onRowLongPress(const int index) {
activateSelected(/*forceDelete=*/true);
}
void FileBrowserActivity::activateSelected(const bool forceDelete, const bool fromButton) {
if (fromButton && lockNextConfirmRelease) {
lockNextConfirmRelease = false;
return;
}
void FileBrowserActivity::activateSelected(const bool forceDelete) {
if (files.empty()) return;
const std::string& entry = files[nav.selected];
@@ -268,11 +258,6 @@ void FileBrowserActivity::activateSelected(const bool forceDelete, const bool fr
const std::string fullPath = cleanBasePath + entry;
auto handler = [this, fullPath](const ActivityResult& res) {
// The confirmation popup acts on button press; if that button is still
// held when we resume, swallow its release so it doesn't also act here
// (Back would go up a directory, Confirm would open the selection).
lockLongPressBack = mappedInput.isPressed(MappedInputManager::Button::Back);
lockNextConfirmRelease = mappedInput.isPressed(MappedInputManager::Button::Confirm);
if (!res.isCancelled) {
LOG_DBG("FileBrowser", "Attempting to delete: %s", fullPath.c_str());
if (removeDirFile(fullPath)) {
@@ -319,8 +304,8 @@ void FileBrowserActivity::activateSelected(const bool forceDelete, const bool fr
bool FileBrowserActivity::handleCustomInput() {
// Long press BACK (1s+) goes to root folder (Books mode only).
// In firmware-pick mode we keep navigation simple: short Back = up dir / cancel.
if (mode == Mode::Books && mappedInput.isPressed(MappedInputManager::Button::Back) &&
mappedInput.getHeldTime() >= GO_HOME_MS && basepath != "/" && !lockLongPressBack) {
if (mode == Mode::Books && mappedInput.wasReleased(MappedInputManager::Button::Back) &&
mappedInput.getHeldTime() >= GO_HOME_MS && basepath != "/") {
basepath = "/";
loadFiles();
nav.selected = 0;
@@ -329,17 +314,12 @@ bool FileBrowserActivity::handleCustomInput() {
return true;
}
if (lockLongPressBack && mappedInput.wasReleased(MappedInputManager::Button::Back)) {
lockLongPressBack = false;
return true;
}
return false;
}
bool FileBrowserActivity::handleButtons() {
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
activateSelected(/*forceDelete=*/false, /*fromButton=*/true);
activateSelected();
return true;
}
+1 -8
View File
@@ -15,11 +15,6 @@ class FileBrowserActivity final : public UiListActivity {
// Deletion
bool removeDirFile(const std::string& fullPath);
bool lockLongPressBack = false;
// True when this activity was entered while Confirm was already held; we must swallow the next
// release so we don't immediately auto-open the first entry.
bool lockNextConfirmRelease = false;
Mode mode = Mode::Books;
// Files state
@@ -57,9 +52,7 @@ class FileBrowserActivity final : public UiListActivity {
void drawFooter() override;
// forceDelete routes the touch long-press to the delete branch; button
// navigation leaves it false and relies on getHeldTime() instead.
// fromButton: only the physical Confirm path may consume the
// lockNextConfirmRelease swallow — a touch tap has no pending release.
void activateSelected(bool forceDelete = false, bool fromButton = false);
void activateSelected(bool forceDelete = false);
// Data loading
void loadFiles();
+2 -5
View File
@@ -220,13 +220,10 @@ void HomeActivity::loop() {
return;
}
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) backPressSeen = true;
// Back is otherwise unused on the home menu: open the most recently read
// book directly (recentBooks is most-recent-first and already pruned of
// files missing from the SD card). backPressSeen guards against the stale
// release of the Back press that closed the previous activity.
if (mappedInput.wasReleased(MappedInputManager::Button::Back) && backPressSeen && !recentBooks.empty()) {
// files missing from the SD card).
if (mappedInput.wasReleased(MappedInputManager::Button::Back) && !recentBooks.empty()) {
onSelectBook(recentBooks[0].path);
return;
}
-3
View File
@@ -18,9 +18,6 @@ class HomeActivity final : public Activity {
bool hasOpdsServers = false;
bool coverRendered = false; // Track if cover has been rendered once
bool coverBufferStored = false; // Track if cover buffer is stored
// Home can be entered while Back is still held (e.g. leaving Settings with
// Back): ignore that stale release until a fresh press is seen here.
bool backPressSeen = false;
uint8_t* coverBuffer = nullptr; // HomeActivity's own buffer for cover image
size_t coverBufferSize = 0; // Bytes allocated to coverBuffer
// Logical rect last passed to drawRecentBookCover. The cover snapshot only
+5 -20
View File
@@ -76,28 +76,13 @@ void RecentBooksActivity::onRowLongPress(const int index) {
}
bool RecentBooksActivity::handleButtons() {
// After a long-press has fired, swallow input until Confirm is physically released
// (so the release doesn't also open the book; re-arm only once the button is up).
if (longPressFired) {
if (!mappedInput.isPressed(MappedInputManager::Button::Confirm)) {
longPressFired = false;
}
return true;
}
// Long-press Confirm on the selected book: prompt to remove it from the list.
// Fires when the hold times out while still held (firmware hold-to-act pattern,
// cf. FileBrowserActivity BACK long-press).
if (!recentBooks.empty() && nav.selected < listCount() &&
mappedInput.isPressed(MappedInputManager::Button::Confirm) && mappedInput.getHeldTime() >= LONG_PRESS_MS) {
longPressFired = true;
promptRemoveBook(recentBooks[nav.selected].path, recentBooks[nav.selected].title);
return true;
}
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (!recentBooks.empty() && nav.selected < listCount()) {
activateIndex(nav.selected);
if (mappedInput.getHeldTime() >= LONG_PRESS_MS) {
promptRemoveBook(recentBooks[nav.selected].path, recentBooks[nav.selected].title);
} else {
activateIndex(nav.selected);
}
return true;
}
}
@@ -24,10 +24,6 @@ class RecentBooksActivity final : public UiListActivity {
const char* headerTitle() const override { return tr(STR_MENU_RECENT_BOOKS); }
void drawFooter() override;
// Set when a long-press has fired; input is swallowed until Confirm is released
// again so the release doesn't also open the book.
bool longPressFired = false;
std::vector<RecentBook> recentBooks;
// Row buffer, built in loadRecentBooks() (not buildScreen(), which reuses
// it on every repaint instead of rebuilding a ListItem vector per render).
@@ -346,7 +346,7 @@ void CrossPointWebServerActivity::loop() {
// for back button checking
mappedInput.update();
// Check for exit button inside loop for responsiveness
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
onGoHome();
return;
}
@@ -356,7 +356,7 @@ void CrossPointWebServerActivity::loop() {
}
// Handle exit on Back button (also check outside loop)
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
onGoHome();
return;
}
@@ -235,13 +235,11 @@ void DictionaryWordSelectActivity::loop() {
return;
}
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) confirmPressSeen = true;
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
finish();
return;
}
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) && confirmPressSeen && !words.empty()) {
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) && !words.empty()) {
performLookup();
return;
}
@@ -83,8 +83,4 @@ class DictionaryWordSelectActivity final : public Activity {
int16_t snapshotW = 0;
int16_t snapshotH = 0;
int snapshotIdx = -1;
// The activity is entered while Confirm is still held (long-press trigger):
// ignore the stale release until a fresh press is seen.
bool confirmPressSeen = false;
};
+31 -53
View File
@@ -500,13 +500,38 @@ void EpubReaderActivity::loop() {
requestUpdate();
}
const bool confirmReleased = mappedInput.wasReleased(MappedInputManager::Button::Confirm);
if (confirmReleased) {
switch (SETTINGS.longPressMenuFunction) {
case CrossPointSettings::LP_MENU_BOOKMARK:
if (mappedInput.getHeldTime() >= ReaderUtils::BOOKMARK_HOLD_MS) {
addBookmark();
showBookmarkMessage = true;
bookmarkMessageTime = millis();
requestUpdate();
return;
}
break;
case CrossPointSettings::LP_MENU_KOSYNC:
if (mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS && launchKOReaderSync()) return;
break;
case CrossPointSettings::LP_MENU_DICTIONARY:
if (mappedInput.getHeldTime() >= ReaderUtils::BOOKMARK_HOLD_MS) {
openDictionaryWordSelect();
return;
}
break;
case CrossPointSettings::LP_MENU_DISABLED:
default:
break;
}
}
// While the end screen suggestion menu is showing it owns Confirm/Back/navigation
// input. Anything it doesn't handle (e.g. long-press Back to the file browser) falls
// through to the regular handlers below; page turns are absorbed by the end-of-book
// block. A Confirm release after a long-press function (bookmark/sync) fired is left
// to the regular Confirm handler below, which consumes it via ignoreNextConfirmRelease.
if (atEndOfBook && endOfBookOptionsReady.load(std::memory_order_acquire) && endOfBookOptions->menuActive() &&
!(ignoreNextConfirmRelease && mappedInput.wasReleased(MappedInputManager::Button::Confirm))) {
// block.
if (atEndOfBook && endOfBookOptionsReady.load(std::memory_order_acquire) && endOfBookOptions->menuActive()) {
std::string openPath;
switch (endOfBookOptions->handleMenuInput(mappedInput, &openPath)) {
case EndOfBookOptions::Action::OpenBook:
@@ -529,55 +554,8 @@ void EpubReaderActivity::loop() {
}
}
// Enter reader menu activity on short-press Confirm, the board's menu edge-swipe, or a
// middle-third tap (see ReaderUtils::isTouchMenuGesture). A long-press
// that fired a bound function (bookmark or KOReader sync) sets ignoreNextConfirmRelease so the release
// following the hold does not also open the menu.
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) ||
ReaderUtils::isTouchMenuGesture(renderer, mappedInput)) {
if (ignoreNextConfirmRelease) {
ignoreNextConfirmRelease = false;
} else {
openReaderMenu();
}
}
// Long-press Confirm runs the user-selected function (SETTINGS.longPressMenuFunction).
if (mappedInput.isPressed(MappedInputManager::Button::Confirm)) {
switch (SETTINGS.longPressMenuFunction) {
case CrossPointSettings::LP_MENU_BOOKMARK:
// Hold ~0.4s drops a bookmark at the current page.
if (mappedInput.getHeldTime() >= ReaderUtils::BOOKMARK_HOLD_MS && !showBookmarkMessage) {
addBookmark();
showBookmarkMessage = true;
ignoreNextConfirmRelease = true; // Prevent accidental menu open after adding bookmark
bookmarkMessageTime = millis();
requestUpdate();
}
break;
case CrossPointSettings::LP_MENU_KOSYNC:
// Hold ~1s launches KOReader sync. If sync can't run (no credentials stored), fall
// through so the normal Confirm-release still opens the reader menu.
if (mappedInput.getHeldTime() >= ReaderUtils::GO_HOME_MS) {
if (launchKOReaderSync()) {
ignoreNextConfirmRelease = true; // sync launched or error shown; suppress menu open
return;
}
}
break;
case CrossPointSettings::LP_MENU_DICTIONARY:
// Hold ~0.4s starts dictionary word selection on the current page.
if (mappedInput.getHeldTime() >= ReaderUtils::BOOKMARK_HOLD_MS && !showDictionaryMessage) {
ignoreNextConfirmRelease = true; // Prevent menu open on the release that follows
openDictionaryWordSelect();
return;
}
break;
case CrossPointSettings::LP_MENU_DISABLED:
default:
break;
}
}
// Short Confirm opens the reader menu; long Confirm actions returned above.
if (confirmReleased || ReaderUtils::isTouchMenuGesture(renderer, mappedInput)) openReaderMenu();
// Short press Back restores position when viewing a footnote (takes priority over navigation)
if (footnoteDepth > 0 && mappedInput.wasReleased(MappedInputManager::Button::Back) &&
@@ -60,7 +60,6 @@ class EpubReaderActivity final : public Activity {
// "No dictionary set" popup, shown when a lookup is triggered without a configured dictionary.
bool showDictionaryMessage = false;
unsigned long dictionaryMessageTime = 0UL;
bool ignoreNextConfirmRelease = false;
bool currentPageBookmarked = false;
// Idle-time glyph prewarm: after a page settles, scan the LIKELY next page
// (scan mode draws nothing) and load its missing glyphs from SD during idle,
@@ -115,24 +115,7 @@ void EpubReaderBookmarksActivity::onRowLongPress(const int index) {
bool EpubReaderBookmarksActivity::handleCustomInput() {
// Delete confirmation popup
if (confirmPopup.handleInput(mappedInput, [this] { requestUpdate(); })) {
// The popup acts on button press; if that input closed it, the trailing
// release must be swallowed below (Back would leave the activity, Confirm
// would open the selected bookmark).
popupClosing = !confirmPopup.isActive();
return true;
}
if (popupClosing) {
if (mappedInput.isPressed(MappedInputManager::Button::Back) ||
mappedInput.isPressed(MappedInputManager::Button::Confirm)) {
return true; // closing press still held
}
popupClosing = false;
if (mappedInput.wasReleased(MappedInputManager::Button::Back) ||
mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
return true; // swallow the release that closed the popup
}
}
if (confirmPopup.handleInput(mappedInput, [this] { requestUpdate(); })) return true;
if (confirmingDelete) {
// Popup dismissed without a selection (Back button or tap outside): cancel delete
confirmingDelete = false;
@@ -151,17 +134,15 @@ bool EpubReaderBookmarksActivity::handleButtons() {
return true;
}
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) { // Open
openSelectedBookmark();
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (mappedInput.getHeldTime() > ENTER_DELETE_MODE_MS) {
showDeleteConfirmation();
} else {
openSelectedBookmark();
}
return true;
}
if (mappedInput.isPressed(MappedInputManager::Button::Confirm) && mappedInput.getHeldTime() > ENTER_DELETE_MODE_MS) {
// No pass-consumed return here: the legacy loop fell through to swipe and
// button navigation after arming the confirmation.
showDeleteConfirmation();
}
return false;
}
@@ -25,9 +25,6 @@ class EpubReaderBookmarksActivity final : public UiListActivity {
void rebuildBookmarkRowItems();
bool confirmingDelete = false;
OptionPopup confirmPopup;
// True while the button press that closed the popup is still held; its release
// must not fall through to the list's own Back/Confirm handlers.
bool popupClosing = false;
public:
explicit EpubReaderBookmarksActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
@@ -111,25 +111,7 @@ void EpubReaderMenuActivity::activateIndex(const int index) {
}
bool EpubReaderMenuActivity::handleCustomInput() {
if (optionPopup.handleInput(mappedInput, [this] { requestUpdate(); })) {
// The popup acts on button press; if that input closed it, the trailing
// release must be swallowed below (Back would close the menu, Confirm
// would re-activate the selected item).
popupClosing = !optionPopup.isActive();
return true;
}
if (popupClosing) {
if (mappedInput.isPressed(MappedInputManager::Button::Back) ||
mappedInput.isPressed(MappedInputManager::Button::Confirm)) {
return true; // closing press still held
}
popupClosing = false;
if (mappedInput.wasReleased(MappedInputManager::Button::Back) ||
mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
return true; // swallow the release that closed the popup
}
}
return false;
return optionPopup.handleInput(mappedInput, [this] { requestUpdate(); });
}
bool EpubReaderMenuActivity::handleButtons() {
@@ -56,7 +56,7 @@ class EpubReaderMenuActivity final : public UiListActivity {
int listCount() const override { return static_cast<int>(menuItems.size()); }
void buildScreen(UiScreen& screen) override;
void activateIndex(int index) override;
// Popup input/close-swallow runs before any button or touch handling.
// Popup input runs before any button or touch handling.
bool handleCustomInput() override;
// Back closes on RELEASE and Confirm activates on RELEASE; everything else
// (row navigation, page jumps) falls through to the base handler.
@@ -70,9 +70,6 @@ class EpubReaderMenuActivity final : public UiListActivity {
const std::vector<MenuItem> menuItems;
OptionPopup optionPopup;
// True while the button press that closed the popup is still held; its release
// must not fall through to the menu's own Back/Confirm handlers.
bool popupClosing = false;
std::string title = "Reader Menu";
uint8_t pendingOrientation = 0;
uint8_t selectedPageTurnOption = 0;
+9 -17
View File
@@ -196,29 +196,21 @@ inline bool handleBackNavigation(const MappedInputManager& mappedInput, Activity
// board: the bottom-edge up-swipe already exits, and in swipe page-turn
// mode a right swipe must page back instead. Back swipes stay available in menus and other activities; only
// this reader-surface handler ignores them. Physical Back buttons are
// unaffected: isPressed() is button-only, and this guard skips just the
// unaffected: this guard skips just the
// gesture's own release frame.
if (mappedInput.wasBackGesture()) {
return false;
}
if (mappedInput.isPressed(MappedInputManager::Button::Back) && mappedInput.getHeldTime() >= GO_BACK_OR_HOME_MS) {
if (SETTINGS.backShortToFileBrowser) {
goHome.fn(goHome.ctx);
} else {
activityManager.goToFileBrowser(filePath);
}
return true;
if (!mappedInput.wasReleased(MappedInputManager::Button::Back)) return false;
const bool longPress = mappedInput.getHeldTime() >= GO_BACK_OR_HOME_MS;
if (longPress != SETTINGS.backShortToFileBrowser) {
activityManager.goToFileBrowser(filePath);
} else {
goHome.fn(goHome.ctx);
}
if (mappedInput.wasReleased(MappedInputManager::Button::Back) && mappedInput.getHeldTime() < GO_BACK_OR_HOME_MS) {
if (SETTINGS.backShortToFileBrowser) {
activityManager.goToFileBrowser(filePath);
} else {
goHome.fn(goHome.ctx);
}
return true;
}
return false;
return true;
}
} // namespace ReaderUtils
+3 -3
View File
@@ -222,7 +222,7 @@ void SettingsActivity::stepTab(const int direction) {
}
bool SettingsActivity::handleButtons() {
if (mappedInput.wasPressed(MappedInputManager::Button::Confirm)) {
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
if (ringPos() == 0) {
stepTab(1);
} else {
@@ -232,7 +232,7 @@ bool SettingsActivity::handleButtons() {
return true;
}
if (mappedInput.wasPressed(MappedInputManager::Button::Back)) {
if (mappedInput.wasReleased(MappedInputManager::Button::Back)) {
if (ringPos() > 0) {
activeNav().selected = 0;
requestUpdate();
@@ -401,7 +401,7 @@ void SettingsActivity::openSleepTimeoutPicker() {
std::make_unique<IntervalSelectionActivity>(
renderer, mappedInput, "SleepTimeoutInterval", StrId::STR_TIME_TO_SLEEP, SETTINGS.sleepTimeoutMinutes,
CrossPointSettings::MIN_SLEEP_TIMEOUT_MINUTES, CrossPointSettings::MAX_SLEEP_TIMEOUT_MINUTES, 1, 5,
StrId::STR_SLEEP_TIMER_VALUE_FORMAT, false, true, StrId::STR_SLEEP_NEVER),
StrId::STR_SLEEP_TIMER_VALUE_FORMAT, false, StrId::STR_SLEEP_NEVER),
[this](const ActivityResult& result) {
if (!result.isCancelled) {
SETTINGS.sleepTimeoutMinutes = static_cast<uint8_t>(std::get<IntervalResult>(result.data).value);
Loaded 20 of 26 files, more files were not shown because too many files have changed in this diff. Show more