Watch
1
0
Fork
You've already forked SouveraineOS
0

TASK-18: shipped-partial; detection settled, chip still not tappable

This commit is contained in:
Fimeg 2026-07-29 18:17:13 -04:00
commit d811870fae

View file

@ -1,8 +1,53 @@
# TASK 18 — shell: highlight/selection action menu
**Status:** open, design captured (2026-07-21). Component first; backends
light up as they earn it (doctrine §6). **Read Aloud is no longer gated**
`souveraine-speech` serves TTS at `10.10.20.123:7863` as of 2026-07-28.
**Status:** shipped-partial 2026-07-29, live on blueline. Component first;
backends light up as they earn it (doctrine §6). **Read Aloud is no longer
gated** — TTS is Qwen3-TTS on `10.10.20.123:7865`, with the old contract shimmed
on `:7863`, as of 2026-07-29.
## Shipped 2026-07-29
- **Selection detection is settled: compositor-level, no per-app hooks, no
viewtop.** blueline's Hyprland advertises `zwp_primary_selection_device_manager_v1`
and both data-control managers, so `wl-paste --primary --watch` sees every
selection. Verified firing on device. This closes the open question below.
- `services/Selection.qml` — watcher, 220 ms settle debounce (a drag fires
continuously as it grows), pointer anchor via `hyprctl cursorpos`.
**Opt-in** (`Config.options.selection.enable`, default false) because it
observes every highlight on the device including passwords; the watcher is
killed while locked and selection text is never persisted, logged or trailed.
- `modules/souveraine/selection/` — chip → action list. `WlrLayer.Overlay`,
`keyboardFocus: None`. The chip shows a **character count, never a preview**:
it floats over the app that owns the selection, so a preview both duplicates
what is on screen and creates a surface that can outlive its context.
- `services/DeviceEvidence.qml` — reports to the state machine's existing
`Request::Input { trigger }` with an `intent` label, so a new input surface is
not another isolated actor (DEVICE-STATE-MACHINE §1). **The OSK still does not
report and should**: an open keyboard is stronger presence evidence than §4's
`touch.active` +0.1. Testable hypothesis: if stevia's
`zwp_virtual_keyboard_v1` events do not reset Hyprland's idle notifier, the
screen can dim mid-sentence while typing.
**Anchoring is limited and it shaped the UX.** No Wayland protocol exposes the
selection's bounding rectangle — Android does this at the toolkit layer
(ActionMode/FloatingToolbar), Apple in-app. So "tap on the highlighted text" is
not directly detectable; we know *what* is selected, never *where*. Hence the
chip near the touch point. True selection-rect anchoring is the one thing viewtop
would buy.
**Still broken (Casey, on device 2026-07-29): the chip is not tappable or
dismissable.** It appears, and it correctly follows a new selection, but neither
the body nor the ✕ responds. Two attempts failed: a fullscreen shield with
`mask: Region { item: card }`, then a window sized to the card and moved by
margins (`147f7f2`, last state). Untested by Casey. Next step is to determine
whether the layer surface receives touch at all — the `WlrKeyboardFocus.None` +
`ExclusionMode.Ignore` combination on Overlay is the prime suspect, and DialHost
(which works) uses `OnDemand`. It also "fights a bit with Firefox's own highlight
selection stuff".
Not yet wired: both agent actions (need the side-shoot / primary-conversation
seams in `Ai.qml`) and all three reference lookups. They render with the reason
they cannot act rather than dead-tapping.
**Repo:** `~/Projects/souveraine` `surfaces/quickshell` (shell surface),
plus per-action backends noted below.
@ -63,9 +108,8 @@ this menu's Read Aloud action should call the same singleton. Gate:
— the full set is long for a phone screen.
- **Reference actions and the agent:** strictly local/dumb, or may they
fall through to the agent? Default: never touch the agent.
- **Selection-detection mechanism:** compositor-level (Wayland
primary-selection / text-input-v3) vs per-app hooks. Decides whether
"works everywhere" is free or per-app wiring.
- ~~**Selection-detection mechanism.**~~ **Settled 2026-07-29**: compositor-level
via primary-selection + data-control. Works everywhere, no per-app wiring.
- **Z-order / exclusion contract:** which layer the menu renders on and
how it coexists with the OSK. The stevia pill/menu layer-collision bug
(fixed by pill→`WlrLayer.Top` + oskLift, souveraine 271e4f2) is the