Fix multi-monitor workspace routing regression, add laptop auto-detect

- Restore desktop DP-3=primary/DP-2=secondary workspace mapping that
  broke when workspace routing switched from name-matching to raw
  geometric ordering.
- Extract shared laptop/desktop detection + output ranking into
  lib-outputs.sh (battery presence selects the profile automatically),
  sourced by both select-workspace.sh and the new apply-outputs.sh, so
  keybind routing and monitor placement can never disagree.
- Add apply-outputs.sh: on the laptop, automatically positions whatever
  external display is plugged in (and re-runs on hotplug via swaymsg
  -t subscribe), making it primary. No-op on the desktop, which keeps
  its static fixed-arrangement config.
This commit is contained in:
2026-08-21 23:08:01 -05:00
parent 5c57ee20f7
commit f1275e7870
5 changed files with 106 additions and 12 deletions
+12 -7
View File
@@ -1,5 +1,7 @@
#!/usr/bin/env bash
set -Eeuo pipefail
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/lib-outputs.sh"
slot=${1:-}
action=${2:-select}
@@ -9,15 +11,18 @@ if [[ ! "$slot" =~ ^([1-9]|10)$ ]]; then
exit 2
fi
# Outputs are ordered left-to-right by position, not by name, so this works
# unmodified whether there is one output (laptop) or several (desktop):
# the focused output's rank in that order selects its block of 10 workspaces.
outputs=$(swaymsg -t get_outputs -r | jq -c 'sort_by(.rect.x)')
index=$(jq -r '[.[] | .focused] | index(true)' <<<"$outputs")
if [[ "$index" == null ]]; then
printf 'No focused output found\n' >&2
mapfile -t ordered < <(output_order)
focused=$(swaymsg -t get_outputs -r | jq -r '.[] | select(.focused) | .name')
index=-1
for i in "${!ordered[@]}"; do
[[ "${ordered[$i]}" == "$focused" ]] && index=$i && break
done
if ((index < 0)); then
printf 'Focused output %s is not currently tracked\n' "$focused" >&2
exit 1
fi
workspace=$((slot + index * 10))
case "$action" in