fix(engine): re-poll safe-area insets after app resume #121

Merged
funman300 merged 1 commits from fix/safe-area-resume-repoll into master 2026-07-06 19:52:59 +00:00
Owner

Problem

refresh_insets gated its poll loop on insets.is_populated(), so once insets resolved at first launch, rearm_on_resumed's poll-counter reset was a no-op — JNI was never queried again for the lifetime of the process. Insets that changed while backgrounded (fold/unfold, rotation, gesture ↔ 3-button nav switch) stayed stale until app restart.

Fix

  • Gate the loop on the poll counter alone; settle a cycle by exhausting the counter once a populated reading arrives, so each resume re-arms a fresh ~2s poll window.
  • Rewrite the cached SafeAreaInsets only when the value actually differs — resumes where nothing changed trigger no change detection and no relayout, preserving the no-flash resume behaviour.
  • Correct the stale on_app_resumed doc comment that still described the old inset-zeroing approach.

Known limitation (pre-existing): a transition to genuinely zero insets is indistinguishable from the not-yet-laid-out state, so it still can't be detected.

Verification

  • cargo clippy --workspace -- -D warnings clean
  • cargo ndk -t arm64-v8a clippy -p solitaire_engine -- -D warnings clean (the changed code is cfg(target_os = "android")-gated)
  • cargo test --workspace all passing

Closes #116

🤖 Generated with Claude Code

## Problem `refresh_insets` gated its poll loop on `insets.is_populated()`, so once insets resolved at first launch, `rearm_on_resumed`'s poll-counter reset was a no-op — JNI was never queried again for the lifetime of the process. Insets that changed while backgrounded (fold/unfold, rotation, gesture ↔ 3-button nav switch) stayed stale until app restart. ## Fix - Gate the loop on the poll counter alone; settle a cycle by exhausting the counter once a populated reading arrives, so each resume re-arms a fresh ~2s poll window. - Rewrite the cached `SafeAreaInsets` only when the value actually differs — resumes where nothing changed trigger no change detection and no relayout, preserving the no-flash resume behaviour. - Correct the stale `on_app_resumed` doc comment that still described the old inset-zeroing approach. Known limitation (pre-existing): a transition to genuinely zero insets is indistinguishable from the not-yet-laid-out state, so it still can't be detected. ## Verification - `cargo clippy --workspace -- -D warnings` clean - `cargo ndk -t arm64-v8a clippy -p solitaire_engine -- -D warnings` clean (the changed code is `cfg(target_os = "android")`-gated) - `cargo test --workspace` all passing Closes #116 🤖 Generated with [Claude Code](https://claude.com/claude-code)
funman300 added 1 commit 2026-07-06 19:50:21 +00:00
refresh_insets gated its loop on insets.is_populated(), so once insets
resolved at first launch, rearm_on_resumed's poll-counter reset was a
no-op and JNI was never queried again. Insets that changed while the
app was backgrounded (fold/unfold, rotation, gesture/3-button nav
switch) stayed stale until process restart.

Gate the loop on the poll counter alone and settle a cycle by
exhausting it once a populated reading arrives. The cached resource is
rewritten only when the value actually differs, so resumes where
nothing moved trigger no change detection and no relayout — preserving
the no-flash resume behaviour. Also correct the stale on_app_resumed
doc that still described the old inset-zeroing approach.

Closes #116

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
funman300 merged commit 005efa2ee4 into master 2026-07-06 19:52:59 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: funman300/Ferrous-Solitaire#121