fix(display): #148 — enforce dock intent without the auto-profiles toggle
All checks were successful
Check / eval (push) Successful in 3m37s
All checks were successful
Check / eval (push) Successful in 3m37s
Every nomarchy-home re-lit eDP-1 inside the shut lid: HM activation fires hyprctl reload, the catch-all monitor rule re-enables the panel, and the tick invariant built for exactly this (#142, enforce_dock_intent) never fired — it was gated on settings.displayProfileAuto, the *named-profile* auto-switch toggle, which is unrelated to dock intent and off unless opted into. Confirmed live on the incident machine: dockMode=true, displayProfileAuto unset, watcher journal empty — every tick returned at that guard. Fix: drop the auto_on gate. settings.display.dockMode alone is the user's recorded intent (written by the menu and the dock transition); the profile-active check remains as the real guard (a named profile outranks the dock heuristic). No fight with the #142 undock hammer: undock clears the intent before its rescue reload, so the enforcer stands down by ordering. tools/monitor-fallback.nix grows the reload-mid-dock scenario: fake lid closed, hyprctl reload, panel re-disabled within ~4s, action=re-dock logged — under displayProfileAuto's default false, i.e. the exact condition the bug shipped under. Verification: V2 — nix flake check --no-build green, checks.docking-ux green, monitor-fallback harness green three times (implementer twice, reviewer once, ~71s VM). V3 pending: relogin + nomarchy-home while docked-clamshell (HARDWARE-QUEUE; the watcher is exec-once, the fix arms at next login). Implementation by a Sonnet subagent; diagnosis, design and review on Fable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -600,12 +600,21 @@ ${lib.concatStringsSep "\n" (lib.mapAttrsToList
|
||||
#
|
||||
# `auto_dock` is already idempotent — it returns early unless the internal
|
||||
# is enabled — so this costs one `hyprctl monitors` per tick and does
|
||||
# nothing in the overwhelmingly common case. Gated on the same display
|
||||
# profile check as the event path: a profile is a deliberate, more specific
|
||||
# layout and outranks the dock heuristic.
|
||||
# nothing in the overwhelmingly common case. `settings.display.dockMode`
|
||||
# is the user's recorded intent — written by the menu and by the dock
|
||||
# transition itself (`set_dock_intent`, which `auto_dock` above reaches
|
||||
# via `$TRANSITION dock`) — and that alone is what this is gated on. It
|
||||
# used to also require `auto_on` (`settings.displayProfileAuto`), but that
|
||||
# toggle only controls *named-profile* auto-switching; gating the dock
|
||||
# invariant on it meant enforcement never fired for anyone who had not
|
||||
# separately opted into auto profiles, which is most users. A
|
||||
# `home-manager` activation's `hyprctl reload` re-applies the catch-all
|
||||
# monitor rule regardless, so the panel inside a shut lid came back on
|
||||
# every rebuild while docked (#148). The profile-active check right below
|
||||
# is the real, narrower guard this needs: a profile is a deliberate, more
|
||||
# specific layout and outranks the dock heuristic.
|
||||
enforce_dock_intent() {
|
||||
[ "$(${sync} get settings.display.dockMode 2>/dev/null)" = true ] || return
|
||||
auto_on || return
|
||||
[ "$(nomarchy-display-profile active 2>/dev/null || echo none)" = "none" ] || return
|
||||
internal=$(internal_output)
|
||||
[ -n "$internal" ] || return
|
||||
|
||||
Reference in New Issue
Block a user