tauri-plugin-window-system
Tauri 2 plugin for multi-window lifecycle management.
Publish Scope
- This crate is the plugin core published to crates.io.
- The validation host in
examples/solid-hoststays internal and is not part of the published crate. - The TypeScript API and Solid wrapper are published separately as npm packages.
Public Contract
The plugin is the source of truth for window lifecycle, registry state, and message routing.
Commands
plugin:window-system|open_windowplugin:window-system|close_windowplugin:window-system|list_windowsplugin:window-system|restore_windowsplugin:window-system|emit_to_windowplugin:window-system|send_window_messageplugin:window-system|broadcast_window_messagewindow-system:registry-changedapplication eventwindow-system:messageapplication event
Rust Responsibilities
- Window creation
- Registry management
- Size and position persistence
- Parent-child close chaining
- Window event routing
- Registry-change notifications for frontend resync
- Typed window-bus dispatch for direct, broadcast, and request/response flows
- Startup recovery for tracked windows
child_labels_offor close-oriented child traversalchildren_offor display/diagnostics-oriented descriptor traversal
child_labels_of is the close path: it returns only labels so close_window_tree can stay lightweight and label-based.
children_of is the display path: it expands those labels into descriptors for UI surfaces and diagnostics that need metadata.
Minimal Usage
open_window
Rules
labelis requiredlabel,parent, andtitleare trimmed before useparentmust refer to an existing labelurldefaults toindex.html- blank
urlvalues are normalized toindex.html geometryoverrides restored values when present- error strings are prefixed with stable machine-readable codes
open_window() returns the created WindowDescriptor.
Restore Behavior
restore_windows() returns a RestoreWindowsResult with camelCase fields:
restoredalreadyAliveskipped
Skipped entries use RestoreSkippedWindow with reason: "missing-parent" when a persisted child cannot be resolved.
Tracked windows are restored parent-first.
Children whose parent is still missing are reported in skipped and then pruned from the persisted snapshot during startup cleanup.
Close Behavior
close_windowand native close events share the same teardown logic- the first
CloseRequestedis prevented so the plugin can finish child-first teardown safely - child windows are closed before their parent is removed
- saved geometry is preserved across close/reopen cycles
- tracked windows are restored from
app_data_dir/window-system/windows.jsonduring startup sync - windows are created hidden and shown after geometry restoration to reduce startup flash
- identical geometry updates are skipped so move/resize storms do not thrash the registry or persistence layer
- identical tracked-window descriptors are ignored so repeated syncs do not rewrite unchanged state
- geometry persistence uses coalesced writes during normal operation
- the plugin keeps a Drop fallback for the final geometry flush
- registry/list/update operations emit
window-system:registry-changed restore_windowsreturns restored, already-alive, and skipped window groupssend_window_messageroutes a typed envelope to one live windowbroadcast_window_messageemits a typed envelope to all live windowscreateWindowBus()on the frontend centralizes listen/send/request/reply handling- open/restore timings are emitted in debug builds, or in release builds with the
window-timingsfeature enabled
Typed Topics
The frontend bus is topic-aware through TypeScript generics.
WindowMessageTopicDefinition<Request, Response>defines the payload contract for one topic- event-only topics omit the response payload
- request/response topics should declare both sides so
bus.request()andbus.reply()stay aligned - the broker only validates delivery and lifecycle boundaries; topic payload shapes live in the frontend API layer
Event Shapes
RegistryChangedEventserializes as{ kind, label, windows }RegistryChangeKindserializes asopened,closed, orgeometry-changedWindowMessageEnvelopeserializes with camelCase fieldsWindowMessageScopeserializes asdirectorbroadcastWindowMessageKindserializes asevent,request, orresponse
Native Parent Handling
parentis resolved to a live Tauri window before the child is created- the child is linked to the OS-native parent/owner relation through Tauri's builder API
- if the parent label does not exist or is already closing, window creation is rejected
Persistence
Saved to app_data_dir/window-system/windows.json.
The store is updated from move/resize events, but identical values are ignored so repeated notifications do not trigger extra writes.
The plugin relies on a Drop fallback for the final flush so the latest geometry is durably written before shutdown.
Error Codes
Stable machine-readable codes are emitted from WindowSystemErrorKind and preserved in Rust error strings:
invalid-labelwindow-already-existswindow-cannot-be-its-own-parentparent-window-not-foundwindow-not-foundwindow-reservation-not-foundwindow-registry-lock-poisonedwindow-state-store-lock-poisoned
Permissions
permissions/default.toml enables:
allow-open-windowallow-close-windowallow-list-windowsallow-restore-windowsallow-emit-to-window
Tests
- registry insert / list / child filtering
- geometry persist / restore
- restore planning and cleanup
- command / event / message serialization contracts
cargo check -p tauri-plugin-window-system