From b8584cd6a6fd0707a629140d958d43978c0d7300 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 30 Oct 2026 15:54:43 -0700 Subject: [PATCH] docs(niri): own the portable desk and the no-match defect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit displays.md still described desk-2-portable as an EDID-pending skeleton and left the PM1601 identity unnamed. record the second desk's rig, its position math, and the law that a rig with no eligible profile runs the previous desk's values rather than "unchanged" — the failure that left the portable panels on 3440x1440@180 fallbacks for weeks. --- omp-docs/log.md | 16 +++++++++++ omp-docs/tools/niri/displays.md | 47 ++++++++++++++++++++++++++++++--- omp-docs/tools/niri/index.md | 2 +- 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/omp-docs/log.md b/omp-docs/log.md index 431cf65..d3e1792 100644 --- a/omp-docs/log.md +++ b/omp-docs/log.md @@ -22,6 +22,22 @@ not restated here — entry, then pointer. That is what the 2026-10-21 audit pas newest twelve entries: the facts stayed, the duplicates went, `git log --follow` keeps the long form. +## 2026-10-30 + +### A desk with no matching profile is silently misconfigured + +`desk-2-portable.kdl` stopped being a skeleton: the two PM1601 16" panels are +identity-keyed (`PNP(XYM) PM1601 0000000000000`, `… demoset-1`), the laptop sits +centred against their 1920-tall band, and `display.kdl` points at it. Law: a rig +with no eligible profile does not run "unchanged" — it runs whatever the *last* +profile said. Here that was the home profile, whose Sceptre identity block never +matched and whose connectors still carried `3440x1440@180.000`, so niri fell back +to preferred and every panel in force had a mode written for another desk. +`desk.sh match` reporting "no desk profile matches connected outputs" is the +defect signature, and `blankpad-desk-autoswitch` exits at its initial match — +check `is-active` after any profile edit. Page: +[tools/niri/displays.md](tools/niri/displays.md). + ## 2026-10-29 ### A vendor-cloud provider must be named the way the harness names it diff --git a/omp-docs/tools/niri/displays.md b/omp-docs/tools/niri/displays.md index 364aece..ec64e60 100644 --- a/omp-docs/tools/niri/displays.md +++ b/omp-docs/tools/niri/displays.md @@ -8,7 +8,7 @@ tags: - monitors - rotation - desk-profiles -verified: 2026-10-21 +verified: 2026-10-30 --- # Display Configuration @@ -49,7 +49,7 @@ the dock and the cable, which is why the config keys on the EDID long name inste | Panel | EDID long name | Keyed by | Notes | |-------|----------------|----------|-------| | Sceptre M34 ultrawide | `Sceptre Tech Inc Sceptre M34 Unknown` | identity | `mode "3440x1440@180.000"`, **deliberate** — the panel also offers `3440x1440@239.998`, `144.001` and `120.000`; 180 is driven while the link is degraded (see the law below) — `focus-at-startup` | -| PM1601 portrait | *not captured* | connector `HDMI-A-1` | dock-dependent; run `desk.sh capture` when plugged in, then re-key | +| PM1601 portrait | captured 2026-10-30 — the two panels are `PNP(XYM) PM1601 0000000000000` and `PNP(XYM) PM1601 demoset-1` | connector `HDMI-A-1` in *this* profile; identity on the portable desk | dock-dependent; the identity key is known now, so re-key the block when the panel next rotates through a dock | | eDP-1 laptop panel | `Lenovo Group Limited 0x40A9 Unknown` | identity | scale **1.0** (deliberate; Ghostty grid at 1.25 rejected 2026-10-09), second `focus-at-startup` | VRR: the M34 supports it (its connector today is `DP-1`); **left disabled by @@ -58,6 +58,40 @@ decision** (2026-10-09). Add `variable-refresh-rate` per output if that ever cha `focus-at-startup` on both M34 and eDP-1: niri focuses in config order, so the ultrawide wins when present and the laptop panel is the fallback. +## The desk-2 rig (portable) + +Laptop plus two 16" PM1601 panels in portrait, side by side as one 2400x1920 +band. Profile: `cfg/desk-2-portable.kdl` (`display.kdl` symlinks to it). + +``` +┌──────────────┬──────────┬──────────┐ +│ │ PM1601 │ PM1601 │ eDP-1 1920x1080 normal x=0,y=420 +│ │ rot 90 │ rot 90 │ DP-2 1200x1920 rot 90 x=1920,y=0 +│ eDP-1 │ 1200x1920│ 1200x1920│ HDMI-A-1 1200x1920 rot 90 x=3120,y=0 +│ 1920x1080 │ (DP-2) │(HDMI-A-1)│ +│ │ │ │ The laptop is pinned 420 px down so its +└──────────────┴──────────┴──────────┘ centre (960) meets the band's centre: + x=0,y=420 x=1920,0 x=3120,0 no dead corner when the cursor crosses. +``` + +All three blocks are identity-keyed and pin their mode string verbatim. The +`requires:` list names all three panels, so the matcher only claims this profile +when the whole rig is present — unplug one 16" panel and the watcher leaves the +current layout alone rather than shuffling the survivors. + +**The stale-profile trap this fixed (2026-10-30).** Before this profile existed, +the portable rig ran with `display.kdl` → `desk-1-home.kdl`, whose identity +blocks belong to the Sceptre ultrawide that is *not* connected and whose +connector-keyed fallbacks carried `mode "3440x1440@180.000"`. niri found no such +mode on a 1920x1200 panel, logged the fallback, and drove it at preferred — so +the panels looked fine while every position and refresh value in force had been +written for a different desk. `desk.sh match` reported "no desk profile matches +connected outputs" and `blankpad-desk-autoswitch.service` therefore died at its +initial match, leaving the laptop pinned to the wrong profile indefinitely. +Law: **a desk with no matching profile is not "unchanged", it is silently +misconfigured** — `desk.sh match` saying "no match" is a defect to fix before +anything else on that desk behaves strangely. + ## Desk switching ```mermaid @@ -80,8 +114,13 @@ graph LR - **Manual override:** `Mod+Shift+D` cycles profiles (wrong auto-pick, or same panels, new layout). - **New desk:** `desk.sh capture` prints connected long names → copy into a - new `desk-N-.kdl` (see `desk-2-portable.kdl` skeleton, portable - monitor EDID pending first capture). + new `desk-N-.kdl` with one identity block per panel (template: + [the desk-2 rig](#the-desk-2-rig-portable)). +- **A dead watcher is a signal, not a crash to ignore:** the unit exits at + startup when `desk.sh match` finds no eligible profile, so "no match" on a + desk that clearly has panels means a missing profile, not an idle daemon. + Check `systemctl --user is-active blankpad-desk-autoswitch` after touching + desk profiles. - Unit: `blankpad-desk-autoswitch.service` (systemd user, `ConditionHost=blankpad`). diff --git a/omp-docs/tools/niri/index.md b/omp-docs/tools/niri/index.md index 06fad4c..a4a7884 100644 --- a/omp-docs/tools/niri/index.md +++ b/omp-docs/tools/niri/index.md @@ -18,7 +18,7 @@ Niri is a scrollable-tiling Wayland compositor. Windows are arranged in columns ├── autostart.kdl # Startup applications (noctalia, handy --start-hidden) ├── display.kdl # SYMLINK to the active desk-*.kdl profile (see displays) ├── desk-1-home.kdl # Desk profile: home rig (EDID-keyed) - ├── desk-2-portable.kdl # Desk profile: portable monitor (skeleton) + ├── desk-2-portable.kdl # Desk profile: portable rig (2x PM1601 portrait) ├── input.kdl # Keyboard, touchpad, mouse ├── keybinds.kdl # All key bindings ├── layout.kdl # Gaps, column widths, struts