Merge pull request #71 from jpirnay/fix-activitiy-bleeding

fix: Fix activity bleeding
This commit is contained in:
jpirnay
2026-04-13 11:16:08 +02:00
committed by GitHub
2 changed files with 34 additions and 1 deletions
+28 -1
View File
@@ -54,7 +54,26 @@ void ActivityManager::renderTaskLoop() {
}
void ActivityManager::loop() {
if (currentActivity) {
// Drain leftover input after an activity transition so that the button press/release
// used to leave one activity cannot bleed into the next. We consume events until
// every button is released and no press/release edges remain.
if (drainInput) {
if (mappedInput.wasAnyPressed() || mappedInput.wasAnyReleased() ||
mappedInput.isPressed(MappedInputManager::Button::Back) ||
mappedInput.isPressed(MappedInputManager::Button::Confirm) ||
mappedInput.isPressed(MappedInputManager::Button::Left) ||
mappedInput.isPressed(MappedInputManager::Button::Right) ||
mappedInput.isPressed(MappedInputManager::Button::Up) ||
mappedInput.isPressed(MappedInputManager::Button::Down)) {
// Still have pending input — skip the activity loop but continue with
// the rest (pending-action processing, render flushing) so that
// transitions and screen updates are not delayed.
} else {
drainInput = false;
}
}
if (!drainInput && currentActivity) {
// Note: do not hold a lock here, the loop() method must be responsible for acquire one if needed
currentActivity->loop();
}
@@ -109,6 +128,10 @@ void ActivityManager::loop() {
handler(pendingResult);
}
// Arm input drain so the button that triggered the pop doesn't bleed into the
// restored activity (or into a new activity the handler just pushed).
drainInput = true;
// Request an update to ensure the popped activity gets re-rendered
if (pendingAction == PendingAction::None) {
requestUpdate();
@@ -141,6 +164,10 @@ void ActivityManager::loop() {
lock.unlock(); // onEnter may acquire its own lock
currentActivity->onEnter();
// Arm input drain so the button that triggered the transition doesn't bleed
// into the new activity.
drainInput = true;
// onEnter may request another pending action, we will handle it in the next loop iteration
continue;
}
+6
View File
@@ -62,6 +62,12 @@ class ActivityManager {
// This variable must only be set by the main loop, to avoid race conditions
bool requestedUpdate = false;
// When true, input events are consumed (discarded) until all buttons are released
// and no press/release events remain. Armed automatically on activity transitions
// (push / pop / replace) so that the button used to leave one activity cannot bleed
// into the next one.
bool drainInput = false;
public:
explicit ActivityManager(GfxRenderer& renderer, MappedInputManager& mappedInput)
: renderer(renderer), mappedInput(mappedInput), renderingMutex(xSemaphoreCreateMutex()) {