Menu

Window Management

Relevant source files

Purpose and Scope

This document describes the Windows plugin (tauri-plugin-windows) that manages application window lifecycle, navigation, and state in the Hyprnote desktop application. The plugin provides a type-safe abstraction over Tauri's window management with special behaviors for different window types, particularly the Main window. It handles window creation, visibility states, inter-window navigation, and analytics tracking.

For information about the UI layouts rendered within these windows, see Application Layout and Navigation. For the routing system that defines paths within windows, see Routing System.


Window Types and Routes

The Windows plugin defines seven distinct window types through the AppWindow enum, each serving a specific purpose and mapped to dedicated routes in the application.

Window Type Definitions:

AppWindow TypeRoutePurposeSpecial Behavior
Main/app/mainPrimary workspace for sessions and notesHides instead of closing; analytics tracking
Onboarding/app/onboardingFirst-run setup flowStandard lifecycle
Settings/app/settingsApplication configurationStandard lifecycle
Auth(varies)Authentication flowsStandard lifecycle
Chat(varies)AI chat interfaceStandard lifecycle
Devtool/app/devtoolDeveloper toolsStandard lifecycle
Control/app/controlControl panelStandard lifecycle

Sources: plugins/windows/js/bindings.gen.ts87 apps/desktop/src/routeTree.gen.ts87-161


Window Lifecycle Management

The Windows plugin implements a sophisticated lifecycle management system with distinct behaviors for each window type.

Window Lifecycle State Machine

Sources: plugins/windows/src/ext.rs72-111 plugins/windows/src/events.rs9-51

Core Lifecycle Methods

The AppWindow enum implements the WindowImpl trait through extension methods in plugins/windows/src/ext.rs The lifecycle operations are:

1. show() - Create or Show Window plugins/windows/src/ext.rs72-111

fn show(&self, app: &AppHandle) -> Result<WebviewWindow>

This method:

  • Checks if the window already exists via get()
  • If exists: calls show() and set_focus()
  • If not exists: calls build_window() to create it
  • For Main window specifically:
    • Sets macOS activation policy to Regular
    • Emits "show_main_window" analytics event
    • Calls handle_main_window_visibility(true) for state tracking

2. hide() - Hide Window plugins/windows/src/ext.rs48-54

fn hide(&self, app: &AppHandle) -> Result<()>

Hides the window from view without destroying it. The window remains in memory and can be shown again.

3. close() - Close Window plugins/windows/src/ext.rs56-62

fn close(&self, app: &AppHandle) -> Result<()>

Closes the window, typically destroying it. However, the Main window has special handling (see below).

4. destroy() - Destroy Window plugins/windows/src/ext.rs64-70

fn destroy(&self, app: &AppHandle) -> Result<()>

Immediately destroys the window, removing it from the application.

Sources: plugins/windows/src/ext.rs7-111

Special Main Window Behavior

The Main window (AppWindow::Main) has unique lifecycle handling to improve user experience:

Implementation Details plugins/windows/src/events.rs13-26:

  • When CloseRequested event fires on Main window
  • Calls window.hide() instead of allowing close
  • Calls api.prevent_close() to stop the close operation
  • Updates visibility state via handle_main_window_visibility(false)

This behavior allows the Main window to persist in the background, enabling faster reopening and maintaining application state.

Sources: plugins/windows/src/events.rs9-51 plugins/windows/src/ext.rs79-107


The Windows plugin provides two mechanisms for navigating windows: direct navigation and event-based navigation.

Sources: plugins/windows/src/ext.rs8-41 plugins/windows/src/events.rs63-93

The Navigate event carries navigation information between windows plugins/windows/src/events.rs63-93:

The event can be parsed from URL strings:

  • Input: "hypr://hyprnote.com/app/new?calendarEventId=123&record=true"
  • Parsed to: { path: "/app/new", search: { calendarEventId: "123", record: "true" } }

Sources: plugins/windows/src/events.rs70-93

Direct Navigation: navigate()

Direct navigation immediately changes the window's URL plugins/windows/src/ext.rs19-41:

fn navigate(&self, app: &AppHandle, path: impl AsRef<str>) -> Result<()>

Process:

  1. Gets the target window via self.get(app)
  2. Obtains current URL via window.url()
  3. Parses the path string to separate path and query parameters
  4. Updates the URL path and query string
  5. Calls window.navigate(url) to trigger navigation

This method is synchronous and directly manipulates the webview's navigation.

Sources: plugins/windows/src/ext.rs19-41

Event-Based Navigation: emit_navigate()

Event-based navigation sends a Navigate event to the target window plugins/windows/src/ext.rs8-17:

fn emit_navigate(&self, app: &AppHandle, event: Navigate) -> Result<()>

Process:

  1. Checks if the target window exists
  2. Emits the Navigate event to the window's label
  3. The window's frontend listens for this event and handles navigation

This approach is asynchronous and allows the target window to decide how to handle navigation, enabling more complex routing logic.

Sources: plugins/windows/src/ext.rs8-17


State Management

The Windows plugin maintains internal state to track window visibility and analytics sessions.

ManagedState Architecture

Sources: plugins/windows/src/lib.rs20-39

WindowState Structure

Each window in the state map has a WindowState plugins/windows/src/lib.rs22-34:

Default State:

  • id: New UUID v4
  • visible: false

Sources: plugins/windows/src/lib.rs22-34

Visibility State Tracking

The handle_main_window_visibility() method manages Main window visibility state with analytics plugins/windows/src/ext.rs142-191:

Key Behaviors:

  • Only emits analytics when visibility actually changes
  • Generates a new session_id when transitioning from hidden to visible
  • Preserves session_id when transitioning from visible to hidden
  • Includes user_id from Auth plugin in analytics events

Sources: plugins/windows/src/ext.rs142-191

Window Destroyed Event

When a window is destroyed, it's removed from the state plugins/windows/src/events.rs28-48:

  1. Parse window label to AppWindow enum
  2. Lock the ManagedState
  3. Remove the window entry from HashMap
  4. Emit WindowDestroyed event with the window type
  5. For Main window, call handle_main_window_visibility(false)

Sources: plugins/windows/src/events.rs28-48


Analytics Integration

The Windows plugin integrates with the Analytics plugin to track Main window usage patterns.

Analytics Events

EventTriggerPayload
show_main_windowMain window becomes visibleuser_id, session_id
hide_main_windowMain window becomes hiddenuser_id, session_id

Session ID Behavior:

  • A new session_id (UUID v4) is generated each time the Main window transitions from hidden to visible
  • The same session_id persists while the window remains visible
  • When hidden, the session_id is preserved for potential "hide_main_window" events

Analytics Flow

Implementation Points:

Sources: plugins/windows/src/ext.rs79-90 plugins/windows/src/ext.rs142-191


Commands and Frontend Interface

The Windows plugin exposes Tauri commands that are automatically bound to TypeScript via tauri-specta.

Available Commands

Command Interface plugins/windows/src/commands.rs:

CommandParametersReturnDescription
window_showwindow: AppWindowResult<(), String>Creates or shows a window
window_destroywindow: AppWindowResult<(), String>Destroys a window
window_navigatewindow: AppWindow, path: StringResult<(), String>Directly navigates window to path
window_emit_navigatewindow: AppWindow, event: NavigateResult<(), String>Emits Navigate event to window
window_is_existswindow: AppWindowResult<bool, String>Checks if window exists

TypeScript Bindings plugins/windows/js/bindings.gen.ts9-66:

Sources: plugins/windows/src/commands.rs1-55 plugins/windows/js/bindings.gen.ts9-66

Events Interface

Available Events plugins/windows/js/bindings.gen.ts71-79:

EventPayloadDescription
navigateNavigateInter-window navigation request
windowDestroyedWindowDestroyedWindow has been destroyed
mainWindowStateMainWindowStateMain window UI state changes

TypeScript Event Listeners:

Sources: plugins/windows/js/bindings.gen.ts71-93


Fake Window Overlay System

The Windows plugin includes a fake window bounds system for managing overlays and floating UI elements.

Overlay Management

The plugin maintains a FakeWindowBounds state to track overlay positions plugins/windows/src/overlay.rs:

OverlayBound Structure plugins/windows/js/bindings.gen.ts91:

Overlay Commands

set_fake_window_bounds plugins/windows/src/commands.rs88-97:

  • Associates a named overlay with bounds within a window
  • Creates nested HashMap entries: window_label -> name -> bounds

remove_fake_window plugins/windows/src/commands.rs99-107:

  • Removes a named overlay from a window
  • Cleans up empty window entries from the HashMap

This system allows the frontend to track positions of floating UI elements (like tooltips, dropdowns, or panels) without creating actual OS windows.

Sources: plugins/windows/src/commands.rs57-107 plugins/windows/src/overlay.rs


WindowsPluginExt Trait

The WindowsPluginExt trait extends AppHandle with window management methods plugins/windows/src/ext.rs113-235:

This trait provides a unified interface for window operations accessible from any AppHandle instance throughout the application.

Sources: plugins/windows/src/ext.rs113-235


Platform-Specific Behavior

macOS Activation Policy

On macOS, the Windows plugin manages the application activation policy plugins/windows/src/ext.rs76-77:

This ensures the application appears in the Dock and application switcher when windows are shown.

Sources: plugins/windows/src/ext.rs76-77


Plugin Initialization

The Windows plugin is initialized during application startup plugins/windows/src/lib.rs61-82:

Initialization Steps:

  1. Creates tauri-specta builder with commands and events
  2. Mounts event handlers for Navigate, WindowDestroyed, MainWindowState
  3. Registers ManagedState for window state tracking
  4. Registers FakeWindowBounds for overlay management

Sources: plugins/windows/src/lib.rs41-82