Skip to content

fix(desktop): preserve maximized window state across startup and recovery - #2474

Merged
wsp1911 merged 3 commits into
GCWing:mainfrom
wsp1911:main
Aug 25, 2026
Merged

fix(desktop): preserve maximized window state across startup and recovery#2474
wsp1911 merged 3 commits into
GCWing:mainfrom
wsp1911:main

Conversation

@wsp1911

@wsp1911 wsp1911 commented Aug 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Correct the persisted maximized flag after explicit window-state saves using
    Win32 GetWindowPlacement, without rewriting unreliable normal geometry.
  • Restore hidden-window geometry first and reapply the persisted maximized state
    after the main window becomes visible.
  • Separate full-state persistence from geometry-only startup repairs, resolve
    the state filename through the window-state plugin, and replace state files
    atomically.
  • Ensure WebView2 recovery exits and restarts await graceful process cleanup
    instead of dropping the cleanup future.

Type and Areas

Type:

Regression fix / bug fix

Areas:

  • Desktop/Tauri
  • Windows window-state persistence and restoration
  • WebView2 recovery
  • Web UI startup contract test

Motivation / Impact

A maximized frameless main window could be persisted with
maximized: false and monitor-sized normal bounds. Subsequent launches then
restored a degenerate near-fullscreen normal window instead of the user's
remembered geometry.

Startup geometry repair could also overwrite the maximized state, while
non-atomic state-file replacement risked losing the existing record on failure.
Additionally, WebView2 recovery paths created the asynchronous shutdown cleanup
future without polling it, so restart and exit could bypass graceful cleanup.

This change preserves the native maximized state across save, startup, recovery,
exit, and restart boundaries while keeping existing window-state records
compatible.

Verification

  • cargo check -p bitfun-desktop
    • Passed with the dropped cleanup-future warnings removed.
  • cargo test -p bitfun-desktop window_state_support
    • Passed: 10 tests.
  • cargo test -p bitfun-desktop webview_recovery
    • Passed: 9 tests.
  • git diff --check HEAD~3..HEAD
    • Passed.

The test build still reports one unrelated existing unused_assignments
warning in embedded_relay_host.rs.

Manual Windows validation of maximize, quit/restart, and relaunch behavior was
not performed in this session.

Reviewer Notes

  • The native correction only changes the persisted maximized flag. It never
    derives normal geometry from rcNormalPosition, which is unreliable for a
    maximized undecorated window.
  • Maximized restoration is deferred until after show() only on Windows.
    Other platforms retain their normal restore behavior.
  • State-file replacement uses ReplaceFileW with write-through semantics on
    Windows and atomic rename behavior elsewhere. Replacement failures preserve
    the original file.
  • Missing, partial, or invalid persisted records remain tolerated; no persisted
    schema migration or user-data reset is introduced.
  • No user-facing strings or locale resources were added.
  • Remote workspace, remote control, Peer Device Mode, and Detached Dispatch
    scenarios were not exercised. The change is limited to the controller-local
    Desktop window lifecycle and does not alter remote protocols.

Checklist

  • This PR is focused and does not include secrets, temporary prompts, generated scratch files, or unrelated artifacts.
  • Relevant verification is recorded above, or skipped checks are explained.
  • User-facing strings, docs, and locales are updated where applicable.

Tant and others added 3 commits August 25, 2026 09:27
The tauri plugin window-state flow already persists the main window
geometry, but a maximized undecorated window was saved as
maximized:false together with its stretched frame stored as normal
bounds. Every launch then restored that degenerate near-fullscreen
normal window instead of the remembered geometry.

Fix both sides on Windows:

- After each explicit save, treat GetWindowPlacement as the
  authoritative maximized signal and flip the persisted flag when it
  disagrees. Geometry fields are never rewritten from the placement:
  rcNormalPosition is unreliable for maximized undecorated windows and
  previously blended the pre-restore centered origin with monitor-sized
  dimensions, which moved the restored window off-screen.
- Skip maximizing during the hidden restore phase and re-assert the
  persisted maximized flag after the window becomes visible, because
  maximizing a hidden undecorated window is dropped on show.

Save call sites now carry a reason for failure diagnostics.
A maximized frameless main window could be persisted with stretched normal bounds or lose its maximized flag during startup geometry repair. The correction path also replaced the state file by deleting the existing file first and assumed the plugin's default filename.

Keep the persisted state reliable across startup and explicit save boundaries:

- Separate full-state saves from geometry-only saves so startup size repair cannot overwrite maximized.

- Defer maximized restoration only on Windows, where maximizing a hidden undecorated window is not reliable.

- Resolve the state path through tauri-plugin-window-state's filename API.

- Replace the state file atomically with ReplaceFileW and write-through semantics on Windows, and rename it atomically on other platforms.

- Add regression coverage for replacement failures, preserved state, and platform-specific state flags.

Validation: cargo check -p bitfun-desktop; cargo build -p bitfun-desktop; git diff --check.

Refs: GCWing#2435
Drive WebView recovery restart cleanup on the Tauri async runtime.

Mark shutdown clean and request restart only after cleanup completes.

Reuse the unified desktop exit flow for recovery dialog exits.
@wsp1911
wsp1911 marked this pull request as ready for review August 25, 2026 02:18
@wsp1911
wsp1911 merged commit 90014a7 into GCWing:main Aug 25, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant