fix(docking): make clamshell hotplug safe and discoverable
All checks were successful
Check / eval (push) Successful in 3m32s
All checks were successful
Check / eval (push) Successful in 3m32s
Real dock QA exposed pointer-bound menus, an absent default rescue watcher, the unsafe zero-output panel-off path, missing keyboard/audio hotplug coverage, and unpainted new outputs. Route Rofi to the focused output; replace panel disable with safe workspace migration; always run and reconnect the display watcher and repaint hotplugged outputs; expose a default per-device keyboard picker; handle audio card availability transitions. Verified: V1 — nix flake check --no-build; checks.docking-ux real Home Manager artifact build; option-docs/template-sot; Nix parse, py_compile, and git diff --check. V2 unavailable: no readable KVM. V3 pending in agent/HARDWARE-QUEUE.md.
This commit is contained in:
@@ -11,54 +11,27 @@ the **T14s** (webcam case).
|
||||
|
||||
## Any machine (dev box is fine)
|
||||
|
||||
- [ ] **#86 clamshell lid + external display** — V2 asserts
|
||||
`HandleLidSwitchDocked=ignore` in logind.conf. On a laptop with a
|
||||
real external monitor: open a session, plug external, close lid —
|
||||
machine must **stay awake** (no suspend); external panel remains
|
||||
usable (or wakes with keyboard if DPMS). Unplug external, close lid
|
||||
— should suspend as usual. Optional: with a docked display-profile
|
||||
(`eDP-1` disable), confirm clamshell layout still looks right after
|
||||
lid close. Pass = no surprise suspend when docked.
|
||||
- [ ] **#87 round 2: dock audio auto-follow (watcher)** — round 1 result
|
||||
(Newton, 2026-07-12): audio stayed on speakers when docking; the
|
||||
running generation had no `90-nomarchy-dock-audio` rules yet, and
|
||||
live testing showed the priority rules alone can never win anyway —
|
||||
WirePlumber's stored default (`default-nodes` state, written by any
|
||||
past explicit pick) outranks `priority.session`, and this machine
|
||||
(like most) has one. Fix shipped: the `nomarchy-dock-audio` user
|
||||
service `pactl set-default-sink`s dock-class sinks on hotplug;
|
||||
EasyEffects follows the default (verified live: EE's output links
|
||||
moved to a fake dock-named null sink mid-playback). Retest after
|
||||
pull+rebuild+home on ≥ this rev: play audio, plug the dock →
|
||||
toast "Audio → <monitor/dock>" and sound moves with EE effects
|
||||
still active; unplug → sound returns to speakers; while docked,
|
||||
picking speakers in the Audio menu sticks until the next replug.
|
||||
If it does NOT switch, capture for diagnosis: `pactl subscribe`
|
||||
output during the plug, `pactl --format=json list sinks` while
|
||||
docked (sink names may not match the dock regexes, or the sink
|
||||
node may pre-exist and only flip route availability — the watcher
|
||||
keys on new-sink events).
|
||||
- [ ] **Docked display/audio menu rows** (2026-07-12) — with a real
|
||||
external monitor: Display menu shows "Laptop screen off ·
|
||||
everything → <ext>" (only with >1 active output), "Screen on ·
|
||||
<name>" after a disable, "Move workspace · → next monitor", "Swap
|
||||
workspaces" (exactly 2 outputs). Laptop-off must move its
|
||||
workspaces to the external; Screen on restores it (preferred/auto —
|
||||
declared scale/pos return at the next relogin/switch). Audio menu
|
||||
shows "Send output → <dock sink>" when one exists and isn't
|
||||
default; picking it moves output + toasts. Pass = rows appear/act
|
||||
as described, and none of them show on a single-display session.
|
||||
Also — **run this one with nothing important open**: with the
|
||||
laptop screen off via the menu, physically unplug the dock. The
|
||||
panel should re-enable within ~2s (`rescue_blackout` in the
|
||||
display watcher). Known risk from the VM harness
|
||||
(tools/monitor-fallback.nix): on Hyprland 0.55.4 the zero-output
|
||||
state itself can crash the compositor faster than any rescue
|
||||
(softGL VM: 4/5 runs; control with the panel active survives
|
||||
always) — a crash on real DRM ends the session to the greeter on
|
||||
the re-lit panel. If that happens on hardware, the "Laptop screen
|
||||
off" row needs a rework (mirror instead of disable, or drop until
|
||||
a Hyprland bump) — file it as a NOW bug with the coredump.
|
||||
- [ ] **Docking correction round 3 (2026-07-13 hardware-QA follow-up)** —
|
||||
prior result: lid-close stayed awake, but SUPER+M rendered on the
|
||||
hidden laptop workspace; the keyboard never prompted; audio stayed
|
||||
on speakers; the old laptop-off action lost some applications and
|
||||
abrupt undock left eDP black. After updating to the commit carrying
|
||||
this entry and rebuilding Home Manager, start with the laptop open
|
||||
and play audio. Close the lid and plug the monitor/keyboard: SUPER+M
|
||||
must render on the external focused workspace; the new keyboard must
|
||||
ask for a searchable XKB layout (or set/change it at System ›
|
||||
Keyboard); audio must toast and move to the monitor. System › Audio ›
|
||||
Output device remains the manual fallback; the current wallpaper must
|
||||
cover the external output/workspaces within ~2s. Open Display and choose
|
||||
**Dock mode**: all eDP workspaces/windows move intact to the external
|
||||
and focus follows; no terminal/application exits. Yank the cable: the
|
||||
internal panel is already the logical fallback, lights immediately,
|
||||
and the moved workspaces/windows survive. Replug then manually choose
|
||||
speakers: volume/mute changes must not force the monitor again; only a
|
||||
fresh replug should. If audio still misses, capture `pactl subscribe`
|
||||
during plug plus `pactl --format=json list sinks` while docked. If the
|
||||
menu is still misplaced, capture `hyprctl monitors -j` immediately
|
||||
before SUPER+M (the `.focused` field is the discriminator).
|
||||
- [ ] **Parallel fingerprint-or-password on the real reader** (AMD dev
|
||||
box, 2026-07-12) — with a finger enrolled and
|
||||
`fingerprint.pam = true` (parallel is the default): `sudo -k true`
|
||||
|
||||
@@ -19,6 +19,24 @@ Template:
|
||||
|
||||
---
|
||||
|
||||
## 2026-07-13 — Docking hardware-QA corrections (interactive feedback)
|
||||
- **Task:** Bernardo's real clamshell QA: menu on hidden eDP, no keyboard
|
||||
layout route, audio stayed on speakers, laptop-off lost apps, abrupt
|
||||
undock never restored eDP.
|
||||
- **Did:** Rofi → focused output; replaced eDP disable with safe Dock mode
|
||||
(move workspaces/focus, keep fallback); display watcher now unconditional,
|
||||
reconnecting and race-tolerant. Keyboard watcher runs by default with all
|
||||
XKB layouts + System › Keyboard. Audio also reacts to card/port changes;
|
||||
monitor-added re-applies the current awww wallpaper to the new output.
|
||||
Corrected the fallback harness assumption; added `checks.docking-ux` and
|
||||
synced README/template/ROADMAP/hardware queue.
|
||||
- **Verified:** V1 — `nix flake check --no-build`; `checks.docking-ux`
|
||||
built the real HM generation and passed syntax/invariant/layout-catalog
|
||||
assertions; option docs 90/90, template SoT 4/4; Nix parse + Python
|
||||
compile + diff check. V2 unavailable (no readable KVM).
|
||||
- **Pending:** hardware retest in HARDWARE-QUEUE (docking correction round 3).
|
||||
- **Next suggestion:** hardware retest this exact dock sequence.
|
||||
|
||||
## 2026-07-12 — #89 slice 3: Documented Signal tray icon limitation (no commit)
|
||||
- **Task:** BACKLOG #89 slice 3 — Signal's tray icon is full-colour blue and doesn't match the monochrome bar.
|
||||
- **Did:** Researched Signal's Linux tray icon behavior. Found it is a hardcoded, dynamically generated pixmap (`Signal_status_icon_1`) driven by its Electron wrapper with no built-in toggle for a monochrome icon. Added an entry to `docs/ROADMAP.md`'s known issues noting that certain Electron apps cannot be natively themed. Closed out #89 from the backlog without introducing brittle `app.asar` repacking hacks.
|
||||
@@ -608,4 +626,3 @@ Template:
|
||||
- **Pending:** slices 2 (systemd sunrise/sunset timers + login apply, V2)
|
||||
and 3 (Look & Feel menu) remain under #79.
|
||||
- **Next suggestion:** #79 slice 2 — the timer/hook (V2 runNixOSTest).
|
||||
|
||||
|
||||
@@ -162,6 +162,10 @@ iteration would otherwise rediscover.
|
||||
- Hyprland 0.55 renames `stayfocused` → `stay_focused` (and similar
|
||||
underscore effects); `stayfocused 1` is `invalid field type` at parse
|
||||
(§ polkit workspace rules, 2026-07-10 hardware).
|
||||
- Never gate a safety listener behind the optional feature it also serves:
|
||||
the display menu existed with no profiles while its blackout rescue did
|
||||
not. Rofi defaults to mouse-pointer output (`monitor=-5`), which is stale
|
||||
in clamshell mode; use focused output (`-1`) for keyboard-launched UI.
|
||||
- Hyprland 0.53 rewrote window rules: `windowrulev2` is a hard error and
|
||||
the old rule-first `float, class:^…$` no longer parses — both surface a
|
||||
red config-error banner on the default desktop. Hyprlang legacy form is
|
||||
|
||||
Reference in New Issue
Block a user