Files
Lumotia/docs/architecture-map/02-tauri-runtime/commands/paste.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

8.9 KiB

name, type, slice, last_verified
name type slice last_verified
Paste at cursor architecture-map-page 02-tauri-runtime 2026/05/09

commands::paste

Where you are: Architecture mapTauri runtimeCommands → Paste

Plain English summary. Auto-insert-at-cursor: copy the transcript onto the clipboard and synthesise the platform's paste keystroke (Ctrl+V / Cmd+V) so the text lands in whatever app the user was already focused on. Adds a replace-with-raw flow that fires undo first. Skips the keystroke when the focused window is a terminal emulator (terminals duplicate the keystroke through the PTY). Hides the always-on-top preview overlay before the keystroke so a Wayland compositor doesn't accidentally route the paste back into Magnotia. Restores the user's prior clipboard 300 ms after the paste to honour the "never silently clobber the user's clipboard" contract.

At a glance

  • Path: src-tauri/src/commands/paste.rs.
  • LOC: 790.
  • Tauri commands exposed:
    • paste_text(app, text: String) -> Result<PasteOutcome, String>. Copy + paste at cursor. Returns a PasteOutcome { backend, pasted, copied, message }.
    • paste_text_replacing(app, text: String) -> Result<PasteOutcome, String>. Replace flow: undo → 60 ms gap → paste. Same return shape.
    • detect_paste_backends() -> Vec<String>. Pure probe used by Settings: returns the names of available backends on the current OS / session.
  • Events emitted: none.
  • Depends on: arboard::Clipboard, tauri::Manager (to find and hide the preview window), std::process::Command (every backend shells out).
  • Called from frontend at: dictation result toast / replace-with-raw button (the two main user-facing actions).

What's in here

Constants (src-tauri/src/commands/paste.rs:29)

  • CLIPBOARD_RESTORE_MS = 300 — window after paste before restoring the user's prior clipboard.
  • PREVIEW_HIDE_SETTLE_MS = 80 — compositor settle time after hiding the preview overlay.
  • UNDO_PASTE_GAP_MS = 60 — gap between undo and follow-up paste in the replace flow (brief item #17).

PasteOutcome (src-tauri/src/commands/paste.rs:43)

Frontend-facing struct: backend: Option<String> (e.g. "wtype", "xdotool", "ydotool", "osascript", "sendkeys"), pasted: bool, copied: bool, message: Option<String>.

paste_text (src-tauri/src/commands/paste.rs:67)

Step-by-step:

  1. Snapshot the current clipboard text via arboard::Clipboard::get_text (or None for non-text content).
  2. Write the transcript onto the clipboard. If this fails, return immediately with copied=false and the error.
  3. Probe the focused window via detect_focused_terminal(). If a known terminal class hits, return with a "Terminal detected" message; the user can finish manually with Ctrl+Shift+V or right-click. Note: prior clipboard is intentionally NOT restored here, because the user's recovery path needs the transcript on the clipboard.
  4. hide_preview_overlay_for_paste(&app).await — find the transcription-preview window if it exists and is visible, hide it, sleep 80 ms.
  5. trigger_paste_keystroke() — per-OS dispatch.
  6. If the keystroke fired, schedule restore_prior_clipboard 300 ms later via a detached tokio::spawn.

paste_text_replacing (src-tauri/src/commands/paste.rs:185)

Same shape as paste_text but with an extra step: after copying and hiding the preview, fire trigger_undo_keystroke(), sleep 60 ms, then paste. The undo removes whatever text Magnotia already inserted (the cleaned-up transcript), the paste inserts the raw text. Used by the "replace with raw" frontend button per brief item #17.

detect_paste_backends (src-tauri/src/commands/paste.rs:258)

Pure probe: Linux returns the subset of ["wtype", "xdotool", "ydotool"] that resolve via command -v; macOS always returns ["osascript"]; Windows always returns ["sendkeys"]. Settings uses this to tell the user "install wtype" when Linux is empty.

Terminal classifier

  • KNOWN_TERMINAL_CLASSES (src-tauri/src/commands/paste.rs:292) — substring list ordered longest-first so windowsterminal wins over terminal. Covers Windows (PowerShell, conhost, console, pwsh, cmd, WindowsTerminal), macOS (Terminal, iTerm, iTerm2), Linux (alacritty, konsole, gnome-terminal-server, kitty, wezterm, foot, st, urxvt, xterm, hyper, tilix).
  • classify_terminal(raw) (src-tauri/src/commands/paste.rs:331) — case-insensitive substring search over the list.
  • detect_focused_window_class() plus per-OS implementations (:345).

Per-OS focused-window probes

  • Linux X11: xdotool getactivewindow getwindowclassname (:365).
  • Linux Wayland: returns None. No reliable probe from an unprivileged client. Documented as "by design".
  • macOS: osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true' (:386).
  • Windows: PowerShell P/Invoke wrapper around GetForegroundWindow + GetWindowThreadProcessId + Get-Process (:407).

Per-OS paste / undo backends

  • Linux: linux_paste / linux_undo walk pick_linux_backend_order (:502), which flips the preference order based on session type (wtype, ydotool, xdotool for Wayland; xdotool, ydotool, wtype for X11). Each tool is invoked via Command::new; wtype uses -M ctrl v -m ctrl, xdotool uses key ctrl+v, ydotool uses raw linux input keycodes (29:1 47:1 47:0 29:0). Undo replaces V (47) with Z (44).
  • macOS: osascript -e 'tell ... to keystroke "v" using command down' (:594). Undo swaps in "z".
  • Windows: powershell -Command "(New-Object -ComObject WScript.Shell).SendKeys('^v')" (:634). Undo uses '^z'.

Helpers

  • snapshot_clipboard_text (:125) — wraps arboard.
  • schedule_clipboard_restore (:137) — fires a tokio::spawn that sleeps CLIPBOARD_RESTORE_MS and calls restore_prior_clipboard.
  • restore_prior_clipboard (:152) — reads the current clipboard, calls should_restore (:171), and writes back the prior content if and only if the clipboard still holds the transcript we wrote (i.e. the user has not copied something else in the interim).
  • hide_preview_overlay_for_paste (:240) — find the preview window, check visibility, hide, sleep 80 ms.

Data flow

frontend invoke('paste_text', { text })
  -> snapshot clipboard
  -> write transcript to clipboard
  -> detect terminal: yes -> early return with "manual paste needed" message
  -> hide preview overlay (Wayland focus quirk)
  -> trigger paste keystroke per OS
  -> spawn 300 ms timer -> restore prior clipboard if clipboard still holds the transcript
  -> return PasteOutcome

Replace flow inserts an undo keystroke and a 60 ms gap between hide and paste.

Watch-outs

  • Focus must already be on the target window when the keystroke fires. The global hotkey flow preserves this naturally; clicking Magnotia's own UI does not. The frontend Settings page surfaces the caveat next to the toggle.
  • Wayland focused-window probe is intentionally absent. No way to do this from an unprivileged Wayland client. Result: terminal detection on Wayland-Kitty users will miss; they fall back to the manual Ctrl+Shift+V they already use.
  • Clipboard restore is best-effort. If the user copies something else within the 300 ms window, should_restore will (correctly) decline to write back. If a slow Wayland compositor delays the keystroke past 300 ms, we restore too early and the synthesised Ctrl+V pastes the user's old clipboard. Tradeoff documented in Handy #921.
  • Linux backend order is session-aware. A user with XDG_SESSION_TYPE=wayland and only xdotool installed will fall through to xdotool with a warning; their X11-app focus on a Wayland session works fine but Wayland-native apps will not see the keystroke.
  • No backend = clipboard-only. If trigger_paste_keystroke fails on Linux (no tools installed), the user still has the transcript on the clipboard; Settings shows the install-wtype hint via detect_paste_backends.
  • PowerShell process spawn cost on Windows. Each paste spawns a fresh PowerShell. Acceptable for one-off paste invocations; if you ever build a streaming-paste mode, switch to native SendInput via the windows crate.
  • Permissions. The macOS path requires the user to have granted Accessibility permissions to Magnotia (System Settings → Privacy → Accessibility). Without that, osascript returns success but the keystroke is silently dropped. There is no probe today; flag this in onboarding.

See also

  • Window managementtranscription-preview is the window that gets hidden by hide_preview_overlay_for_paste.
  • Small commands → clipboard — the bare copy_to_clipboard command, used when the user explicitly wants clipboard-only.
  • Live transcription — the upstream of the dictation result that gets pasted.
  • Hotkey bridge — the global hotkey path that preserves focus on the target window.