Watch
1
0
Fork
You've already forked SouveraineOS
0
SouveraineOS/docs/tasks/17-keyboard-squeekboard-dictation.md

7.7 KiB

TASK 17 — Squeekboard + dictation polish

Status: single-OSK cutover installed 2026-08-11. Pixel3Arch CI 1362 built pkgrel 4; the phone runs it as the sole OSK, and the former second keyboard plus process switcher are uninstalled. Commit 3794aa9 advances pkgrel 5 with an explicit in-keyboard Daily/Terminal chooser and removes every dual-OSK living path; CI 1368 and phone installation/glass proof remain.

Current decision (2026-08-11)

One keyboard owns the phone: Squeekboard. Ordinary inputs select a four-row iOS-style Daily layout with no terminal modifiers, arrows, Fn layer, or permanent number row. Its mode key opens Squeekboard's own chooser, where Terminal selects the five-row layout with Tab, number row, Ctrl/Alt/Esc, arrows, and Fn/numpad. Terminal input purpose may select it automatically, but the visible chooser is the reliable manual route in either direction. Both layouts expose the same first-party dictation action and an explicit dismiss key. No process is swapped and no shell or pill gesture chooses a keyboard.

Pixel3Arch/pkgs/squeekboard now carries:

  • a dictate layout action that spawns packaged /usr/bin/souveraine-stt;
  • Daily and Terminal layouts with the mic available from their base rows;
  • the Daily mode key and upstream chooser entry that make Terminal reachable without relying on input-purpose hints;
  • a Cairo-drawn, state-honest mic: restrained violet at idle, three breathing violet bubbles while recording, a rotating broken ring while transcribing, and a red-violet error mark;
  • animation driven by $XDG_RUNTIME_DIR/souveraine-stt/state, polled only while the keyboard widget is mapped.

No bitmap was imported and no Stevia completion code was reused. Native Squeekboard word completion remains the next layer after the single-keyboard path is stable.

Earlier Stevia path (historical, no longer installed)

  • stevia is the OSK, patched to run under Hyprland. Upstream stevia hard-requires zphoc_device_state_v1 (phoc-private) before creating a keyboard surface, so under Hyprland it sat "Wayland not yet ready" forever and the phone had NO keyboard. Patched optional. Pixel3Arch/pkgs/stevia (0.56.0-3), builds native on-device. Squeekboard retired (SouveraineOS/blueline/squeekboard/ kept as layout reference only).
  • Mic/dictation key on every layout's bottom row (patch 0002): spawns souveraine-stt, a record→transcribe→type toggle CLI. Config (endpoint, enable) lives in Config.options.speech, surfaced in the new Settings → Speech page (souveraine 402e887), with a live /health probe. STT hits Casey's VPN faster-whisper box (see whisper-stt-server memory).
  • Terminal arrow keys (patch 0002): the terminal layout's bottom row gained ← ↓ ↑ → (the shortcuts bar always had them but sat under the pill).
  • Nav pill fix: the SystemGestureRail was lifting the pill 315px (a stale squeekboard height) which stacked it OVER the keys and stevia's upward-opening layout menu — "keyboard selection not working" was this. Now lifts to stevia's real 200px top edge; pill stays visible as the dismiss handle, clear of the keys (souveraine 5e5bf04).
  • souveraine-stt error honesty (67aeb25): distinguishes server 5xx / 4xx / unreachable from a genuine empty transcript. The old "didn't catch that" on any no-text result masked a whole server outage as a mic bug.

Historical follow-ons and retained evidence

  1. Dictation UX: the earlier Stevia implementation established the state contract. Squeekboard now renders that contract directly in the mic key; pkgrel 5 publication, install, and glass proof remain.

    2026-07-30 progress:

    • souveraine-stt now writes a 3-state file $XDG_RUNTIME_DIR/souveraine-stt/state (idle|recording|transcribing|error) and --status reads it (with reconciliation). notify toasts fire at every transition. Deployed on the phone.
    • Real "last word didn't type" cause found + fixed: whisper wraps output in embedded \n, and ydotool type typed \n as Enter — chopping/ submitting the dictation mid-stream. The CLI now collapses newlines→spaces (+ --key-delay) before typing.
    • stevia patch 0006 (pkgs/stevia/0006-dictate-key-status-animation.patch, Pixel3Arch e9320be, pkgrel 2): polls the state file from pos-osk-widget and swaps the dictation key's icon by state (recording = mic pulse, transcribing = content-loading, error = warning). Written, applies clean, NOT YET BUILT — archdev's aarch64 GTK3 sysroot + cross-file aren't set up where build-cross.sh expects; building 0.56.0-2 is the remaining step (then pacman -U + systemctl --user restart souveraine-stevia, verify with grim).
  2. Size: Casey settled on gsettings set mobi.phosh.osk scaling "[]" (200px, no auto-scale). The taller auto value is ['auto-portrait','auto-landscape'] (348px). Applies live, no restart. Not a bug — just record the chosen default so a reflash keeps it.

  3. Layouts: the vendored Squeekboard us+apple reference produced the four-row Daily board. Dense work keys remain a separate Terminal layout; the explicit mode key and chooser connect them inside one process. A permanent number row on Daily is deliberately absent. Native completion remains the follow-on; it must be built in Squeekboard rather than copied from the retired implementation.

  4. Hyprland key safety: Pixel3Arch a5fdbf6 ships stevia 0.56.0-5 with high virtual eventcodes plus zeroed fallback modifiers. Keep the compositor-collision hammer test (bound letters/digits must never dispatch Hyprland actions or shutdown) in every later layout patch.

  5. TTS: no server unblocked 2026-07-28. souveraine-speech serves POST /audio/speech at 10.10.20.123:7863 (chatterbox.cpp on ArchDev's RX 560), deliberately API-compatible with the retired VibeVoice route. Config.options.speech.tts and the Settings field are ready — this is now filling in a URL, not building a service.

Context

  • Retired dual-OSK implementation and its patches: Pixel3Arch/archive/retired-dual-osk-2026-08-11/. This is evidence only; no build, overlay, compositor startup, or package workflow reads it.
  • CLI: Pixel3Arch/rootfs-overlay/usr/local/bin/souveraine-stt.
  • Shell: souveraine/surfaces/quickshell/modules/settings/SpeechConfig.qml, modules/common/Config.qml (speech block), settings-phone.qml.
  • The OSK D-Bus plumbing (sm.puri.OSK0 SetVisible, GlobalStates.oskOpen, the "osk" IPC target) is unchanged from squeekboard — stevia's unit claims the same bus name, so shell chrome tracking needed no changes.

Acceptance

Squeekboard raises from ordinary and terminal inputs, types letters/numbers, and survives at least five dismiss/reopen cycles. Daily's mode key opens the chooser; Terminal exposes Tab, number row, Ctrl/Alt/Esc, arrows and Fn; the chooser returns to Daily without losing the focused field. Its mic key dictates real speech into the focused field and visibly traverses idle → recording → transcribing → idle; the error state is also forced once. The AI side panels must not dismiss or strand it. Stevia and souveraine-osk-switch are already removed from the live phone; no acceptance path may silently reinstall them. Native word completion is a following acceptance step, not a blocker for the single-keyboard cutover.

Connects to

whisper-stt-server (the STT backend), TASK-15 (dictation is a network fetcher the idle coordinator must wake for). Under viewtop the OSK's z-order is structurally enforced by the compositor (ad2b6cb, TASK-43) — a layer derived from the surface's furniture role, not a layerrule — so the layer-collision class this task fought in quickshell does not arise there.