Skip to content

Desktop Integration

Saco Song edited this page Jul 30, 2026 · 8 revisions

Desktop Integration

简体中文 · Home

Hyprland controls

Voice Input does not grab keys. Hyprland runs small client commands that connect to the daemon control socket.

The installed snippet is:

source = ~/.local/share/voice-input/omarchy-hyprland-snippet.conf

Its main binding is toggle mode:

bindd = SUPER CTRL, X, Voice input, exec, voice-input record toggle

Toggle is the robust choice when release events are unreliable. Each toggle client includes a request timestamp; the daemon ignores one that spent more than 750 ms queued behind finalization.

For push-to-talk, pair press and release:

bind = SUPER CTRL, X, exec, voice-input record start
bindr = SUPER CTRL, X, exec, voice-input record stop

The release must reach Hyprland. If a multi-modifier release is unreliable, return to toggle. hotkey.mode does not install a binding by itself; it affects generated output from:

voice-input setup hyprland

Cancel without output:

voice-input record cancel

Quickshell HUD

The primary HUD is a separate service:

systemctl --user status voice-input-hud.service
systemctl --user restart voice-input-hud.service

The unit runs:

/usr/bin/qs --no-duplicate --path ~/.local/share/voice-input/quickshell

It sets XDG_RUNTIME_DIR=%t, creates one PanelWindow variant per screen, displays only on the focused Hyprland monitor, uses the overlay layer, requests no keyboard focus, ignores exclusive-zone layout, and subtracts its complete input mask so it is click-through.

HUD data paths

$XDG_RUNTIME_DIR/voice-input/state.json
$XDG_RUNTIME_DIR/voice-input/waveform.sock

StateStore.qml polls the atomic JSON state every 50 ms during active phases and every 100 ms while idle. A Quickshell local socket receives newline-delimited waveform frames independently and reconnects after 400 ms when disconnected. Long transcript display uses a four-line viewport anchored to the newest text, with an edge fade over older content.

The HUD is exclusively Quickshell and remains independent from recognition:

  • restarting the daemon does not restart Quickshell;
  • a HUD crash does not stop ASR/output;
  • [hud].enabled = false hides the HUD surface while the resident service can remain running; stop/disable voice-input-hud.service to remove the process;
  • each state snapshot carries hud_enabled, hud_margin_bottom, hud_height, hud_position, hud_offset_x, and hud_offset_y, and Quickshell honors those values.

Theme

Quickshell watches:

~/.config/omarchy/current/theme/colors.toml

It maps accent, foreground, color3, color5, and color1 to phase colors and retains built-in colors if the file cannot be read or parsed. This theme file is optional.

HUD placement

The current position and offsets live in config and runtime state:

voice-input hud position bottom-left
voice-input hud move right
voice-input hud move up 12
voice-input hud center
voice-input hud reset
  • move uses [hud].nudge_step unless an amount is given.
  • Positive X moves right; positive Y raises the HUD.
  • center selects bottom-center and clears X only.
  • reset selects bottom-center and clears both offsets.

Suggested optional bindings:

bind = SUPER CTRL ALT, left,  exec, voice-input hud move left
bind = SUPER CTRL ALT, right, exec, voice-input hud move right
bind = SUPER CTRL ALT, up,    exec, voice-input hud move up
bind = SUPER CTRL ALT, down,  exec, voice-input hud move down
bind = SUPER CTRL ALT, c,     exec, voice-input hud center

Quickshell Settings

Settings is a second Quickshell configuration, separate from the resident HUD:

~/.local/share/voice-input/quickshell-settings

Open it with:

voice-input settings

The command first uses non-secret Quickshell IPC to activate an existing voiceInputSettings instance. Otherwise it starts:

/usr/bin/qs --daemonize --no-duplicate --path ~/.local/share/voice-input/quickshell-settings

This configuration creates a regular FloatingWindow, not a layer-shell panel, and exits when the window closes. It is on demand and has no systemd unit. The supplied Hyprland snippet floats and centers the Voice Input Settings client so the compositor honors its requested 900 × 620 utility-window size instead of tiling it across the workspace.

The full-height navigation opens Overview, Speech, Refinement, Output, Appearance, and Hotkey & state. Overview shows a read-only local service report and summaries of the current Speech, Refinement, Output, and Appearance configuration. Detail pages use flat desktop-form sections with clear dividers instead of a dashboard of nested cards. Provider-specific fields appear conditionally, and technical fields remain available in expandable Advanced sections on the relevant pages; no configuration field is discarded when hidden. The header provides an unsaved-change indicator, a language menu, a Reload settings overflow action, and Close.

Its QML starts one dedicated Rust child backend and communicates using versioned NDJSON over stdin/stdout. QML does not write TOML or credentials directly. runtime.get returns only allowlisted service and runtime metadata for Overview; it is independent from configuration save state and does not claim provider connectivity.

Waybar

The supplied JSONC fragment defines custom/voice-input:

voice-input setup waybar

Its command is:

voice-input status --follow --format json --extended

status --follow checks state every 250 ms and prints only when the payload changes. The snippet maps phase classes to icons, opens Settings on right click, and opens the model setup wizard on left click.

Merge the object into your Waybar configuration and add custom/voice-input to the desired module list. The setup command prints a fragment; it does not edit an existing Waybar file or restart Waybar.

Wayland and XWayland output targeting

At recording start, the CLI asks Hyprland whether the active window is XWayland and passes a hint to the daemon. At output time the daemon queries again. If either the captured hint or current target says XWayland, it takes the XWayland route.

Target Direct type Clipboard Paste
Wayland wtype wl-copy wl-copy + wtype chord
XWayland wtype if explicitly allowed xclip xclip + xdotool

The default prefer_paste_for_xwayland = true avoids direct typing in XWayland. Text over 120 characters also switches from type to paste on Wayland. Paste backs up and restores the target clipboard; clipboard mode copies only.

Hyprland discovery first tries the command socket and falls back to hyprctl. It can import HYPRLAND_INSTANCE_SIGNATURE, WAYLAND_DISPLAY, DISPLAY, and XDG_RUNTIME_DIR from the systemd user-manager environment. If a service cannot see the session, update that environment from your graphical-session startup and restart the service rather than hard-coding another user's runtime path.

See also: Troubleshooting · Configuration

Clone this wiki locally