--- name: niri-all-monitor-screenshot-fix description: "Fix flameshot screenshot failures on niri with 2+ outputs: confirm portal outputs.len()==1 census, retire flameshot binds for niri-native equivalents, absolute script paths (niri spawn-sh PATH lacks ~/.local/bin)" --- # Niri all-monitor screenshot fix (flameshot retirement) ## Symptom fingerprints - "Bunch of flameshot errors after a delay" when docked (2+ outputs); fine on one output. - Journal census (ground truth): `journalctl --user -u niri --since today | grep -i screenshot` - FAIL: `WARN niri::niri: error taking a screenshot: Condition failed: outputs.len() == 1 (2 vs 1)` — one press of flameshot full emits 3 WARNs (composited screen + per-output portal requests). - SUCCESS: `DEBUG niri::niri: saving screenshot to ...` — per-file lines. - Timeline: count WARNs before/after a config reload to attribute presses to config states. ## Root cause Flameshot 14 on Wayland captures via xdg-desktop-portal → xdg-desktop-portal-gnome → niri's GNOME-Screenshot compatibility D-Bus API → `screenshot_all_outputs` → `ensure!(outputs.len() == 1)` (FIXME upstream). Upstream: niri#4313 (closed duplicate, unfixed in 26.04/8ed0da4), flameshot#4449. - NOT just `full`: live-verified docked, `flameshot full` AND `flameshot screen` both hang ~15 s (exit 124 under timeout), write no file. Assume ALL flameshot capture modes dead with 2+ outputs. ## Fix: retire flameshot binds; niri-native replacements (blankpad layout) | Chord | Action | |---|---| | Print / Ctrl+Shift+1 / Mod+Shift+S | `spawn-sh "/home/blank/.omp/scripts/screenshot-desk.sh"` — per-monitor PNGs | | Alt+Print / Ctrl+Shift+2 | `screenshot-screen;` — focused monitor → screenshot-path + clipboard | | Ctrl+Print / Ctrl+Shift+3 | `screenshot;` — interactive UI (Space saves, Esc cancels; single-output selection by design) | - Misc: `screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png"` at CONFIG ROOT (it is `config.screenshot_path`; a KDL `output { }` block REQUIRES a name arg — bare `output {}` is a parse error). - KDL comments are `//`, never `#` (parses as identifiers → cryptic "identifiers cannot be used as arguments"). - niri 26.04 screenshot UI: "allows only single-output selections for now" (src/ui/screenshot_ui.rs) — no built-in all-monitor composite; script needed. ## All-monitor script (scripts/screenshot-desk.sh) Per active output (`niri msg --json outputs | jq -r .[].name`): `niri msg action focus-monitor ` → sleep 0.15 → `niri msg action screenshot-screen --path "/… .png"` → restore prior focused monitor (`niri msg --json focused-output | jq -r .name`). No grim, no portal. `--path` must be absolute. ## THE SPAWN-SH PATH TRAP niri's spawn-sh PATH = system dirs only; `~/.local/bin` ABSENT. Proof: `tr '\0' '\n' < /proc/$(pgrep -x niri | head -1)/environ | grep ^PATH` → any bare user-script name in a keybind fails SILENTLY (no journal error, no file). Rule: keybinds use absolute script paths (`/home/blank/.omp/scripts/...`). Audit existing binds for bare names (desk.sh was dead too). ## Verifying a keybind end-to-end without a keyboard Reproduce niri's child env exactly: `env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl HOME=$HOME USER=$USER LOGNAME=$LOGNAME XDG_RUNTIME_DIR=/run/user/$(id -u) WAYLAND_DISPLAY=wayland-1 NIRI_SOCKET=/run/user/$(id -u)/niri.$WAYLAND_DISPLAY.$(pgrep -x niri | head -1).sock sh -c "/abs/path/script"` NIRI_SOCKET is NOT in niri's own environ (it is set on niri's children); socket path convention: `$XDG_RUNTIME_DIR/niri...sock`. ## Deploy mechanics (blankpad command-center) Live niri config = symlinks into the ~/.omp main checkout ("the checkout is the deployment"). Merge to main → niri auto-reloads (~1 s later journal `DEBUG niri_config: loaded config from ...`); verify that DEBUG line as the reload proof. Manual fallback: Mod+Shift+/. `niri msg` has NO keybinds subcommand — keybind proof = overlay (Mod+Shift+Escape) + journal census.