Window State
Automatically remember window size, position, and state across app restarts in Local.ts.
Local.ts uses the Tauri window state plugin to automatically remember your window size, position, and state across app restarts.
This creates a polished desktop experience where users don't have to resize their window every time they open the app.
What Gets Saved
The window state plugin tracks:
| Property | Description |
|---|---|
| Size | Window width and height |
| Position | Window X and Y coordinates |
| Maximized | Whether the window is maximized |
| Fullscreen | Whether the window is in fullscreen |
| Decorations | Whether window decorations are visible |
How It Works
Initialization
The plugin is initialized during app setup and restores state for all windows:
// src-tauri/src/lib.rs
.setup(|app| {
plugins::logging::init(app);
// Initialize window state plugin
#[cfg(desktop)]
plugins::window_state::init(app)?;
// ... other setup code
Ok(())
})The init function registers the plugin and restores saved state.
Saving State
Window state is saved automatically when the window closes:
// src-tauri/src/lib.rs
.on_window_event(|window, event| {
#[cfg(desktop)]
if let tauri::WindowEvent::CloseRequested { .. } = event {
plugins::window_state::on_close_requested(window);
}
})The on_close_requested function handles the save operation.
Customizing What's Saved
You can choose which properties to persist by modifying the StateFlags in the plugin module:
// src-tauri/src/plugins/window_state.rs
pub fn init<R: Runtime>(app: &App<R>) -> Result<(), Box<dyn std::error::Error>> {
// ... plugin registration ...
// Only restore size and position
let flags = StateFlags::SIZE | StateFlags::POSITION;
for (label, window) in windows {
if let Err(err) = window.restore_state(flags) {
log::warn!("Failed to restore state for window '{}': {}", label, err);
}
}
Ok(())
}
pub fn on_close_requested<R: Runtime>(window: &Window<R>) {
// Only save size and position
let flags = StateFlags::SIZE | StateFlags::POSITION;
if let Err(err) = window.app_handle().save_window_state(flags) {
log::warn!(
"Failed to save window state for '{}': {}",
window.label(),
err
);
}
}Available flags:
| Flag | What It Saves |
|---|---|
StateFlags::SIZE | Window dimensions |
StateFlags::POSITION | Window location |
StateFlags::MAXIMIZED | Maximized state |
StateFlags::VISIBLE | Visibility state |
StateFlags::DECORATIONS | Window decorations |
StateFlags::FULLSCREEN | Fullscreen state |
StateFlags::all() | All of the above |
Default Window Size
Set default dimensions in src-tauri/tauri.conf.json for first launch before any state is saved:
{
"windows": [{
"title": "Local.ts",
"label": "main",
"visible": false,
"width": 1280,
"height": 720,
"center": true
}]
}These defaults are used only on first launch.
Error Handling
The window state plugin uses proper error handling with logging:
- Restore failures are logged as warnings but don't prevent the app from starting
- Save failures are logged as warnings to help debug state persistence issues
- Window labels are included in error messages for easier troubleshooting
This ensures that state management issues won't crash your application.
Saving State Periodically
Instead of (or in addition to) saving on close, you can save state periodically by adding a function to the plugin:
// src-tauri/src/plugins/window_state.rs
use std::time::Duration;
pub fn start_periodic_save<R: Runtime>(app: &App<R>) {
let app_handle = app.handle().clone();
std::thread::spawn(move || {
loop {
std::thread::sleep(Duration::from_secs(300)); // 5 minutes
if let Err(err) = app_handle.save_window_state(StateFlags::all()) {
log::warn!("Failed to save window state periodically: {}", err);
}
}
});
}Then call it from your setup:
// src-tauri/src/lib.rs
.setup(|app| {
#[cfg(desktop)]
{
plugins::window_state::init(app)?;
plugins::window_state::start_periodic_save(app);
}
Ok(())
})This protects against state loss if the app crashes.
The spawned thread runs for the application's entire lifetime — it will only exit when the application terminates, so make sure any resources accessed from that thread are safe to use for the duration of the process.
Removing Window State
If you don't need window state persistence:
-
Remove the plugin module at
src-tauri/src/plugins/window_state.rs -
Remove the initialization from
src-tauri/src/lib.rs:- #[cfg(desktop)] - plugins::window_state::init(app)?; -
Remove the window event handler from
src-tauri/src/lib.rs:- .on_window_event(|window, event| { - #[cfg(desktop)] - if let tauri::WindowEvent::CloseRequested { .. } = event { - plugins::window_state::on_close_requested(window); - } - }) -
Remove the dependency from
src-tauri/Cargo.toml:- tauri-plugin-window-state = "2" -
Remove permissions from
src-tauri/capabilities/default.json:- "window-state:default"
Last updated on