fix(injection): align fallback ladder to portal>wtype>ydotool>xdotool>manual

Ticket #31 review found startup and demote paths preferring ydotool
over wtype, with a KDE ydotool-first exception, contradicting the
decided order in spec #16 (portal first where a backend implements
it, then direct keysym typing, then the virtual-input tool, then
XWayland-only injection, then manual paste).

- Auto-selection is now portal, wtype, ready ydotool, daemonless
  ydotool, xdotool on every desktop including KDE; the __init__ wtype
  probe validates wtype and demotes on compositor rejection.
- Portal-deny demotion, IBus-fallback switch, XWayland recovery, and
  a new wtype runtime-failure retry all follow the same rung order
  with partial-type accounting preserved.
- Ladder suite grows to 14 tests pinning KDE portal selection,
  wtype-before-ydotool selection, and each demotion trigger.
- USER_GUIDE states the full rung order and portal-first on KDE.
This commit is contained in:
soubarnak
2026-11-06 09:21:13 +05:30
parent da97b676a7
commit e100af7bcd
5 changed files with 265 additions and 97 deletions
+12 -7
View File
@@ -383,10 +383,15 @@ as a niri recommendation — there is nothing for it to talk to. IBus stays
excluded on niri as well: it would report the text as delivered while native
windows silently receive nothing.
**GNOME / KDE Plasma.** The portal leads where a backend implements it.
Nothing asks at startup: the handshake stays lazy and the compositor asks
once, for keyboard access only, at the first actual dictation. A granted
session keeps its restore token so later launches skip the prompt where the
desktop supports persistence. Denying closes that session and is not retried
within the run; the pending dictation is still typed through the next
fallback rung, so saying no costs a fallback rather than the dictation.
**GNOME / KDE Plasma.** The portal leads on both: GNOME and KDE Plasma
implement `org.freedesktop.portal.RemoteDesktop`, so it is the first rung
on either desktop. After it the order is direct keysym typing (`wtype`),
then the virtual-input tool (`ydotool`, needs a ready `ydotoold`), then
XWayland-only typing (`xdotool`), then clipboard copy with manual paste as
the last resort. Nothing asks at startup: the handshake stays lazy and the
compositor asks once, for keyboard access only, at the first actual
dictation. A granted session keeps its restore token so later launches
skip the prompt where the desktop supports persistence. Denying closes
that session and is not retried within the run; the pending dictation is
still typed through direct typing, so saying no costs a fallback rather
than the dictation.