fix(engine): poll decor-view size to catch fold resizes winit misses (#130) #152

Merged
funman300 merged 1 commits from fix/130-fold-stale-relayout into master 2026-07-07 18:12:57 +00:00
Owner

Implements the candidate fix from #130: a continuous JNI decor-view size poller (every 30 frames, ~0.5s) in safe_area.rs's Android module.

On mismatch with Bevy's cached Window resolution it:

  1. writes the real physical size into window.resolution (renderer reconfigures; window.width() readers see truth),
  2. emits a synthetic WindowResized in logical px so on_window_resized relayouts the board,
  3. re-arms the inset poller — closing the '#116 re-poll may never fire' hole, since fold cycles move the system bars too.

Deliberately continuous rather than WillResume-gated: the winit Android backend's missing lifecycle forwarding is the root cause, so the fix cannot depend on those same events. A new evidence log in rearm_on_resumed will settle on-device whether WillResume fires at all (investigation step 2 of #130).

Gates: cargo test --workspace green, cargo clippy --workspace -- -D warnings clean, plus cargo ndk … clippy -p solitaire_engine clean for aarch64-linux-android.

Needs on-device verification on the Fold 7: fold/unfold foreground and backgrounded, watch adb logcat -s RustStdoutStderr for safe_area: decor view is … and layout: resize to … lines.

Closes #130

🤖 Generated with Claude Code

Implements the candidate fix from #130: a continuous JNI decor-view size poller (every 30 frames, ~0.5s) in `safe_area.rs`'s Android module. On mismatch with Bevy's cached `Window` resolution it: 1. writes the real physical size into `window.resolution` (renderer reconfigures; `window.width()` readers see truth), 2. emits a synthetic `WindowResized` in logical px so `on_window_resized` relayouts the board, 3. re-arms the inset poller — closing the '#116 re-poll may never fire' hole, since fold cycles move the system bars too. Deliberately continuous rather than `WillResume`-gated: the winit Android backend's missing lifecycle forwarding is the root cause, so the fix cannot depend on those same events. A new evidence log in `rearm_on_resumed` will settle on-device whether `WillResume` fires at all (investigation step 2 of #130). Gates: `cargo test --workspace` green, `cargo clippy --workspace -- -D warnings` clean, plus `cargo ndk … clippy -p solitaire_engine` clean for aarch64-linux-android. **Needs on-device verification on the Fold 7**: fold/unfold foreground and backgrounded, watch `adb logcat -s RustStdoutStderr` for `safe_area: decor view is …` and `layout: resize to …` lines. Closes #130 🤖 Generated with [Claude Code](https://claude.com/claude-code)
funman300 added 1 commit 2026-07-07 17:49:19 +00:00
winit's Android backend does not forward content-rect changes that happen
while backgrounded (open TODOs in winit 0.30 logged on every resume), so a
fold/unfold cycle can leave Bevy rendering and laying out for the previous
screen: tableau clipped off the left edge, bottom third empty (#130).

Add a continuous decor-view size poller (JNI, every 30 frames) that, on
mismatch with the cached Window resolution: writes the real physical size
into window.resolution, emits a synthetic WindowResized in logical pixels,
and re-arms the safe-area inset poller — covering both the fold-size and
inset-staleness cases in one mechanism, without relying on
AppLifecycle::WillResume being delivered (it may never be; a new evidence
log in rearm_on_resumed settles that question on-device).

Closes #130

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
funman300 force-pushed fix/130-fold-stale-relayout from 5323c26a0d to 38b81a4004 2026-07-07 17:49:19 +00:00 Compare
funman300 merged commit ff8c00d2f4 into master 2026-07-07 18:12:57 +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#152