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>
87 lines
5.9 KiB
Markdown
87 lines
5.9 KiB
Markdown
---
|
||
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.
|