C.W.K.
Stream
Lesson 03 of 06 · published

Multi-Window Apps

~13 min · tauri, windows, multi-window, architecture

Level 0Web Tourist
0 XP0/56 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete
"Each window is its own little browser tab. They don't share a single line of JavaScript — so the truth has to live somewhere they both can reach: the core."

Separate Webviews, Separate Worlds

Every window is an independent webview with its own JavaScript context. Your React state in the main window does not exist in the settings window — they're as isolated as two browser tabs. This surprises people: opening a second window doesn't 'share' your store. If two windows must agree on data, that data belongs in the Rust core (managed state), and each window reads it through commands. The core is the single source of truth; windows are views onto it.

Talking Between Windows

Windows coordinate through the core. To push something to a specific window, use emit_to("label", …); to broadcast to all, emit. A common flow: the settings window saves a preference via a command (updating managed state), then the core emits a settings-changed event that the main window listens for and reacts to. No window calls another directly — they all go through the core, which keeps the data consistent.

Lifecycle: show, hide, close

Windows have a lifecycle you control: show(), hide(), close(), plus events you can listen to like close-requested (to confirm before closing) or focus changes. Hiding instead of closing keeps a window's webview alive (fast to reopen, state preserved); closing destroys it (frees resources, fresh state next time). Choose based on whether reopening should be instant or clean.

Code

Windows coordinate through the core, not directly·rust
use tauri::{Manager, Emitter};

// The core is the shared truth; windows sync through it.
#[tauri::command]
fn set_theme(app: tauri::AppHandle, theme: String, state: tauri::State<Prefs>) {
    *state.theme.lock().unwrap() = theme.clone();   // update shared state
    let _ = app.emit("settings-changed", theme);     // tell every window
}

// Intercept a window closing to confirm first.
fn guard_close(win: &tauri::WebviewWindow) {
    let w = win.clone();
    win.on_window_event(move |event| {
        if let tauri::WindowEvent::CloseRequested { api, .. } = event {
            api.prevent_close();           // stop the default close
            let _ = w.emit("confirm-close", ()); // ask the UI to confirm
        }
    });
}

External links

Exercise

Open a second window and prove the isolation: set some React state in the main window, open the second window, and confirm that state isn't there. Then make them agree by storing the value in managed Rust state and having both windows read it via a command. You've just rediscovered why the core is the source of truth.
Hint
The second window starts fresh — your main-window store is gone. Move the shared value into a Mutex in managed state; both windows call a get command (and listen for a changed event) to stay in sync.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.