fix(autoswitch): WorkspacesChanged output-set diff; unit paths; deploy symlinks
- niri 26.04 has no hotplug event: OutputConfigChanged is only an ACK (niri-ipc). Watch WorkspacesChanged, diff sorted output set, apply on change. Proven live: eDP-1 off/on -> 3 output-set transitions, each matched + applied + reloaded. - unit: %h/.local/bin/desk-autoswitch.sh, quoted Environment, drop User/Group (user unit); add desk-autoswitch.sh bin symlink - desk.sh: silence validate/load-config/notify stdout - deploy.sh: deploy repo symlinks (find -type l), so .local/bin links land - docs: event semantics corrected (displays diagram, log)
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
# scripts/desk-autoswitch.sh — hotplug daemon: apply the matching desk profile
|
||||
# whenever niri reports an OutputsChanged event.
|
||||
# when the SET OF OUTPUTS changes.
|
||||
#
|
||||
# niri has no dedicated hotplug event (verified on 26.04):
|
||||
# - WorkspacesChanged carries every workspace's `output`, so the sorted
|
||||
# unique set of outputs changes exactly on connect/disconnect.
|
||||
# - OutputConfigChanged is only an ACK that an IPC/config output change was
|
||||
# Applied (niri-ipc), NOT a hotplug signal.
|
||||
#
|
||||
# Usage: desk-autoswitch.sh watch
|
||||
#
|
||||
@@ -8,7 +14,7 @@
|
||||
# DESK_AUTO_HOSTNAME only run on this hostname (default: blankpad)
|
||||
# DESK_SCRIPT path to desk.sh (default ~/.local/bin/desk.sh)
|
||||
# DESK_NIRI niri binary (default niri)
|
||||
# DESK_DEBOUNCE_S debounce window in seconds (default 1.5)
|
||||
# DESK_DEBOUNCE_S min seconds between applies (default 1.5)
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -17,8 +23,10 @@ DESK="${DESK_SCRIPT:-$HOME/.local/bin/desk.sh}"
|
||||
NIRI="${DESK_NIRI:-niri}"
|
||||
DEBOUNCE="${DESK_DEBOUNCE_S:-1.5}"
|
||||
|
||||
usage() {
|
||||
sed -n '2,12p' "$0" | sed 's/^# \{0,1\}//'
|
||||
usage() { sed -n '2,18p' "$0" | sed 's/^# \{0,1\}//'; }
|
||||
|
||||
outputs_from_event() { # $1 = one JSON event line
|
||||
jq -r '[.WorkspacesChanged.workspaces[]?.output // empty] | unique | join(" ")' <<<"$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
watch_mode() {
|
||||
@@ -26,16 +34,20 @@ watch_mode() {
|
||||
echo "desk-autoswitch: initial match"
|
||||
"$DESK" match --apply || true
|
||||
|
||||
local last=0 now
|
||||
local seen="" last_seen="" last=0 now
|
||||
# One JSON event per line; reconnect forever (niri restart drops the stream).
|
||||
while "$NIRI" msg --json event-stream 2>/dev/null | while IFS= read -r line; do
|
||||
case "$line" in
|
||||
*OutputsChanged*)
|
||||
*WorkspacesChanged*)
|
||||
seen="$(outputs_from_event "$line")"
|
||||
[ -n "$seen" ] || continue
|
||||
[ "$seen" = "$last_seen" ] && continue
|
||||
last_seen="$seen"
|
||||
now="$(date +%s.%N)"
|
||||
# swallow bursts inside the debounce window
|
||||
if awk -v l="$last" -v n="$now" -v d="$DEBOUNCE" 'BEGIN { exit !(n - l >= d) }'; then
|
||||
last="$now"
|
||||
echo "desk-autoswitch: OutputsChanged"
|
||||
echo "desk-autoswitch: outputs changed [$seen]"
|
||||
"$DESK" match --apply || true
|
||||
fi
|
||||
;;
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ requires() {
|
||||
|
||||
notify() {
|
||||
# shellcheck disable=SC2086 # word splitting of the prefix is intended
|
||||
$NOTIFY "Desk" "$1" 2>/dev/null || true
|
||||
$NOTIFY "Desk" "$1" >/dev/null 2>/dev/null || true
|
||||
}
|
||||
|
||||
# Apply a profile: relink, validate live config, roll back on failure,
|
||||
|
||||
Reference in New Issue
Block a user