Add touch gesture to open reader menu
Implements a press-and-hold gesture in the center touch zone (400ms threshold) that opens the reader menu, mirroring the Confirm button behavior. The center third of the screen is now reserved for this menu gesture, while left and right thirds continue to handle page turns. Applied to both EPUB and XTC readers.
This commit is contained in:
@@ -256,8 +256,16 @@ void EpubReaderActivity::loop() {
|
|||||||
requestUpdate();
|
requestUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enter reader menu activity.
|
// Touch reader controls mirror the side page buttons (left third = back, right
|
||||||
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
|
// third = forward, press-and-hold = long-press behavior) and the Confirm
|
||||||
|
// button (center press-and-hold = open menu). The top-left Back corner is
|
||||||
|
// consumed by wasReleased(Back) earlier, so it never reaches here. No-op on
|
||||||
|
// Xteink / when the setting is off. wasTouchTap is idempotent within a frame,
|
||||||
|
// so reading it here and again below is safe.
|
||||||
|
const auto touch = ReaderUtils::detectTouchPageTurn(renderer);
|
||||||
|
|
||||||
|
// Enter reader menu activity (Confirm release, or a center touch-and-hold).
|
||||||
|
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) || ReaderUtils::isTouchMenuGesture(touch)) {
|
||||||
if (ignoreNextConfirmRelease) {
|
if (ignoreNextConfirmRelease) {
|
||||||
ignoreNextConfirmRelease = false;
|
ignoreNextConfirmRelease = false;
|
||||||
} else {
|
} else {
|
||||||
@@ -338,12 +346,6 @@ void EpubReaderActivity::loop() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Touch reader controls mirror the side page buttons (left third = back,
|
|
||||||
// right third = forward, press-and-hold = long-press behavior). The top-left
|
|
||||||
// Back corner is consumed by wasReleased(Back) earlier, so it never reaches
|
|
||||||
// here. No-op on Xteink / when the setting is off.
|
|
||||||
const auto touch = ReaderUtils::detectTouchPageTurn(renderer);
|
|
||||||
|
|
||||||
auto [prevTriggered, nextTriggered, fromTilt] = ReaderUtils::detectPageTurn(mappedInput);
|
auto [prevTriggered, nextTriggered, fromTilt] = ReaderUtils::detectPageTurn(mappedInput);
|
||||||
prevTriggered = prevTriggered || touch.prev;
|
prevTriggered = prevTriggered || touch.prev;
|
||||||
nextTriggered = nextTriggered || touch.next;
|
nextTriggered = nextTriggered || touch.next;
|
||||||
|
|||||||
@@ -14,6 +14,9 @@ constexpr unsigned long GO_HOME_MS = 1000;
|
|||||||
constexpr unsigned long SKIP_HOLD_MS = 700;
|
constexpr unsigned long SKIP_HOLD_MS = 700;
|
||||||
constexpr unsigned long BOOKMARK_HOLD_MS = 400;
|
constexpr unsigned long BOOKMARK_HOLD_MS = 400;
|
||||||
constexpr unsigned long BOOKMARK_MESSAGE_DURATION_MS = 2500;
|
constexpr unsigned long BOOKMARK_MESSAGE_DURATION_MS = 2500;
|
||||||
|
// Press-and-hold in the center touch zone (see detectTouchPageTurn) opens the
|
||||||
|
// reader menu, the touch analogue of releasing the Confirm button.
|
||||||
|
constexpr unsigned long TOUCH_MENU_HOLD_MS = 400;
|
||||||
|
|
||||||
inline void applyOrientation(GfxRenderer& renderer, const uint8_t orientation) {
|
inline void applyOrientation(GfxRenderer& renderer, const uint8_t orientation) {
|
||||||
switch (orientation) {
|
switch (orientation) {
|
||||||
@@ -64,19 +67,21 @@ inline PageTurnResult detectPageTurn(const MappedInputManager& input) {
|
|||||||
|
|
||||||
// Touch reader controls: a tap on the left third of the (oriented) screen turns
|
// Touch reader controls: a tap on the left third of the (oriented) screen turns
|
||||||
// back a page, the right third turns forward, mirroring the side page buttons.
|
// back a page, the right third turns forward, mirroring the side page buttons.
|
||||||
// heldMs carries the contact duration so callers can apply the same long-press
|
// The center third opens the reader menu on press-and-hold (see center/heldMs;
|
||||||
// behavior (chapter skip / orientation change) as the buttons. The center column
|
// the menu/Back gesture is handled by each reader). heldMs carries the contact
|
||||||
// is left for the menu/Back gesture handled by each reader. Gated off the Xteink
|
// duration so callers can apply the same long-press behavior (chapter skip /
|
||||||
// devices (no touch) and behind the touchReaderControls setting; returns all-false
|
// orientation change) as the buttons. Gated off the Xteink devices (no touch)
|
||||||
// otherwise, so non-touch readers pay a single branch.
|
// and behind the touchReaderControls setting; returns all-false otherwise, so
|
||||||
|
// non-touch readers pay a single branch.
|
||||||
struct TouchPageTurn {
|
struct TouchPageTurn {
|
||||||
bool prev;
|
bool prev;
|
||||||
bool next;
|
bool next;
|
||||||
|
bool center;
|
||||||
unsigned long heldMs;
|
unsigned long heldMs;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline TouchPageTurn detectTouchPageTurn(GfxRenderer& renderer) {
|
inline TouchPageTurn detectTouchPageTurn(GfxRenderer& renderer) {
|
||||||
TouchPageTurn result{false, false, 0};
|
TouchPageTurn result{false, false, false, 0};
|
||||||
if (gpio.isXteinkDevice() || !SETTINGS.touchReaderControls) {
|
if (gpio.isXteinkDevice() || !SETTINGS.touchReaderControls) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -91,11 +96,19 @@ inline TouchPageTurn detectTouchPageTurn(GfxRenderer& renderer) {
|
|||||||
result.prev = true;
|
result.prev = true;
|
||||||
} else if (lx >= 2 * third) {
|
} else if (lx >= 2 * third) {
|
||||||
result.next = true;
|
result.next = true;
|
||||||
|
} else {
|
||||||
|
result.center = true;
|
||||||
}
|
}
|
||||||
result.heldMs = gpio.lastTouchHeldMs();
|
result.heldMs = gpio.lastTouchHeldMs();
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// True when the center zone was pressed and held long enough to open the reader
|
||||||
|
// menu (touch analogue of a Confirm release).
|
||||||
|
inline bool isTouchMenuGesture(const TouchPageTurn& touch) {
|
||||||
|
return touch.center && touch.heldMs >= TOUCH_MENU_HOLD_MS;
|
||||||
|
}
|
||||||
|
|
||||||
inline void displayWithRefreshCycle(const GfxRenderer& renderer, int& pagesUntilFullRefresh) {
|
inline void displayWithRefreshCycle(const GfxRenderer& renderer, int& pagesUntilFullRefresh) {
|
||||||
if (pagesUntilFullRefresh <= 1) {
|
if (pagesUntilFullRefresh <= 1) {
|
||||||
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
renderer.displayBuffer(HalDisplay::HALF_REFRESH);
|
||||||
|
|||||||
@@ -53,8 +53,14 @@ void XtcReaderActivity::onExit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void XtcReaderActivity::loop() {
|
void XtcReaderActivity::loop() {
|
||||||
// Enter chapter selection activity
|
// Touch reader controls mirror the side page buttons (left third = back, right
|
||||||
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm)) {
|
// third = forward, press-and-hold = chapter skip) and the Confirm button
|
||||||
|
// (center press-and-hold = chapter selection). No-op on Xteink / when the
|
||||||
|
// setting is off.
|
||||||
|
const auto touch = ReaderUtils::detectTouchPageTurn(renderer);
|
||||||
|
|
||||||
|
// Enter chapter selection activity (Confirm release, or a center touch-and-hold).
|
||||||
|
if (mappedInput.wasReleased(MappedInputManager::Button::Confirm) || ReaderUtils::isTouchMenuGesture(touch)) {
|
||||||
if (xtc && xtc->hasChapters() && !xtc->getChapters().empty()) {
|
if (xtc && xtc->hasChapters() && !xtc->getChapters().empty()) {
|
||||||
startActivityForResult(
|
startActivityForResult(
|
||||||
std::make_unique<XtcReaderChapterSelectionActivity>(renderer, mappedInput, xtc, currentPage),
|
std::make_unique<XtcReaderChapterSelectionActivity>(renderer, mappedInput, xtc, currentPage),
|
||||||
@@ -79,11 +85,6 @@ void XtcReaderActivity::loop() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Touch reader controls mirror the side page buttons (left third = back,
|
|
||||||
// right third = forward, press-and-hold = chapter skip). No-op on Xteink /
|
|
||||||
// when the setting is off.
|
|
||||||
const auto touch = ReaderUtils::detectTouchPageTurn(renderer);
|
|
||||||
|
|
||||||
auto [prevTriggered, nextTriggered, fromTilt] = ReaderUtils::detectPageTurn(mappedInput);
|
auto [prevTriggered, nextTriggered, fromTilt] = ReaderUtils::detectPageTurn(mappedInput);
|
||||||
prevTriggered = prevTriggered || touch.prev;
|
prevTriggered = prevTriggered || touch.prev;
|
||||||
nextTriggered = nextTriggered || touch.next;
|
nextTriggered = nextTriggered || touch.next;
|
||||||
|
|||||||
Reference in New Issue
Block a user