Files
Lumotia/docs/architecture-map/02-tauri-runtime/commands/windows.md
jars a1f3f3f134 docs: architecture map (initial 5-slice generation, 105 pages)
Five-slice navigable map of the entire codebase under
docs/architecture-map/. Each slice is a self-contained
breadcrumbed sub-tree:

  01-frontend (16)              Svelte/SvelteKit UI
  02-tauri-runtime (26)         src-tauri commands + lifecycle
  03-audio-transcription (16)   audio + transcription crates
  04-llm-formatting-mcp (19)    llm, ai-formatting, mcp, cloud
  05-core-storage-hotkey-build  core, storage, hotkey, workspace,
                          (26) CI, dev glue

Plus master README.md and data-flow-end-to-end.md tracing
audio bytes from microphone to FTS5 search to MCP read.

Generated by 5 parallel subagents on 2026/05/09 against
HEAD 3c47000. Each page has YAML frontmatter, file:line code
refs, sibling cross-links, plain-English summaries.

Aggregated debt surfaced (full lists in master README):
RB-08 macOS power assertion, schema head drift v14 vs v15,
VAD blocked on ort version conflict, streaming primitives
not wired into live.rs, no prompt versioning, MCP has no
auth, cloud-providers in-memory keystore, SettingsPage
2 484 LOC, commands/live.rs 1 737 LOC, dual theme system,
brand rename to Lumenote pending across the codebase.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 14:04:13 +01:00

87 lines
5.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: Window management
type: architecture-map-page
slice: 02-tauri-runtime
last_verified: 2026/05/09
---
# `commands::windows`
> **Where you are:** [Architecture map](../../README.md) → [Tauri runtime](../README.md) → [Commands](README.md) → Window management
**Plain English summary.** The imperative builder for the three secondary windows: a floating always-on-top task list, a transcript viewer / editor, and a transient transcription preview overlay. Each command is idempotent: an existing window is shown and focused; otherwise a new one is built. Linux uses native KWin/Mutter decorations; macOS and Windows draw the custom frameless chrome. The preview overlay is configured to follow the user across virtual desktops and stay out of the alt-tab list (KWin sticky + GTK Utility hint). Android stubs return a clear error so the frontend can detect and route to in-window routes instead.
## At a glance
- Path: `src-tauri/src/commands/windows.rs`.
- LOC: 197.
- Tauri commands exposed (4 total):
- `open_task_window(app) -> Result<(), String>`.
- `open_preview_window(app) -> Result<(), String>`.
- `close_preview_window(app) -> Result<(), String>`.
- `open_viewer_window(app) -> Result<(), String>`.
- Events emitted: `task-window-focus` (no payload) when `open_task_window` brings an existing task float forward (`src-tauri/src/commands/windows.rs:49`).
- Depends on: `tauri::{Emitter, Manager, WebviewUrl, WebviewWindowBuilder}` (desktop-only). `gdk::WindowTypeHint`, `gtk::prelude::GtkWindowExt` for the Linux preview hint.
- Called from frontend at: dictation page (preview open / close around recording), Tasks page header button (task float), History page row click (viewer).
## What's in here
### Android stubs (`src-tauri/src/commands/windows.rs:14`)
`#[cfg(target_os = "android")]` versions of all four commands return `Err("Multi-window is not supported on Android; this command is desktop-only")`. The frontend detects Android via `isAndroid()` and routes the formerly-secondary content into routes inside the main window.
### `open_task_window` (`:43`)
If a `tasks-float` window already exists, show + focus and emit `task-window-focus`. Otherwise build a new one at `/float`, 480×520 (min 360×480), `always_on_top: true`, decorations native on Linux / frameless elsewhere, resizable. Inject the `PreferencesScript` if present so prefs land before Svelte mounts.
### `open_preview_window` (`:88`)
If a `transcription-preview` exists, show (NOT focus — the overlay must not steal focus from whatever the user is typing into). Otherwise build a new one at `/preview`, 420×200 (min 360×140, max 520×360), `always_on_top: true`, `skip_taskbar: true`, `visible_on_all_workspaces: true` (KWin sticky), `focused: false`, `visible: false` (built hidden so the GTK type-hint can be set pre-realize). Inject prefs.
After the build:
- On Linux, fetch the `gtk_window()` and call `set_type_hint(WindowTypeHint::Utility)`. This signals to Hyprland / Sway / GNOME Mutter compositors that the window is auxiliary and should not show in alt-tab. KWin already obeys SKIP_TASKBAR; this is defence in depth for non-KDE compositors.
Then call `window.show()` to actually surface it.
### `close_preview_window` (`:158`)
If the preview window exists, hide it (don't destroy — the next open is instant). No-op if it doesn't exist. Idempotent return Ok.
### `open_viewer_window` (`:168`)
If a `transcript-viewer` exists, show + focus. Otherwise build a new one at `/viewer`, 600×700 (min 560×520), Linux native decorations / frameless elsewhere, resizable. Inject prefs. NOT always-on-top — the viewer is a primary surface, not an overlay.
## Data flow
```
Tasks page header button -> invoke('open_task_window')
-> if exists: show + focus + emit('task-window-focus')
-> else: WebviewWindowBuilder('/float', ..., always_on_top=true)
Dictation start -> invoke('open_preview_window')
-> build hidden, set GTK Utility hint on Linux, show
Dictation end / paste -> invoke('close_preview_window') -> hide
History row click -> invoke('open_viewer_window')
-> if exists: show + focus
-> else: WebviewWindowBuilder('/viewer', ...)
```
## Watch-outs
- **No `ensure_main_window` guard, but the ACL guards effectively.** The main capability gates these commands; the secondary windows do not have permission to invoke them. If you ever expand the secondary-windows capability, double-check.
- **Preview overlay focus quirks.** Even with `focused: false`, KWin and Mutter Wayland sometimes route the next keystroke to the overlay. `commands::paste::hide_preview_overlay_for_paste` is the partner workaround that hides the preview before firing a paste.
- **The GTK type hint is set *before* `show()`** (`:151`). GTK3 only honours type hints pre-realize. Don't reorder.
- **Linux native decorations vs frameless.** The `let use_native_decorations = cfg!(target_os = "linux");` call is the cross-cutting decision: Linux wins native via Tauri's frameless-Wayland resize quirk; macOS and Windows draw the custom Titlebar. If you ever ship a Windows build, audit this.
- **`open_task_window` emits `task-window-focus` only on the "already exists" path.** A first-build does not emit it. The Tasks page should listen and re-render the float regardless of which path was taken — but if you have logic that fires only on the event, the first-build will silently miss.
- **`always_on_top` plus visible-on-all-workspaces** is the right combination for the preview, but it can feel intrusive. If the user's workflow shifts to a single-workspace setup, consider an opt-out toggle in Settings.
## See also
- [App lifecycle](../app-lifecycle.md) — `PreferencesScript` is what gets injected.
- [Capabilities and ACL](../capabilities-and-acl.md) — the secondary-windows capability is bound to the labels declared here.
- [Paste](paste.md) — `hide_preview_overlay_for_paste` is the partner hide call.
- [Tauri config](../tauri-config.md) — the main window is declared statically; the three windows here are imperative.