fix(desktop): preserve maximized window state across startup and recovery - #2474
Merged
Conversation
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
marked this pull request as ready for review
August 25, 2026 02:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Win32
GetWindowPlacement, without rewriting unreliable normal geometry.after the main window becomes visible.
the state filename through the window-state plugin, and replace state files
atomically.
instead of dropping the cleanup future.
Type and Areas
Type:
Regression fix / bug fix
Areas:
Motivation / Impact
A maximized frameless main window could be persisted with
maximized: falseand monitor-sized normal bounds. Subsequent launches thenrestored 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-desktopcargo test -p bitfun-desktop window_state_supportcargo test -p bitfun-desktop webview_recoverygit diff --check HEAD~3..HEADThe test build still reports one unrelated existing
unused_assignmentswarning in
embedded_relay_host.rs.Manual Windows validation of maximize, quit/restart, and relaunch behavior was
not performed in this session.
Reviewer Notes
maximizedflag. It neverderives normal geometry from
rcNormalPosition, which is unreliable for amaximized undecorated window.
show()only on Windows.Other platforms retain their normal restore behavior.
ReplaceFileWwith write-through semantics onWindows and atomic rename behavior elsewhere. Replacement failures preserve
the original file.
schema migration or user-data reset is introduced.
scenarios were not exercised. The change is limited to the controller-local
Desktop window lifecycle and does not alter remote protocols.
Checklist