Files
dotfiles/dot_config/niri/scripts/executable_niri-focus.sh
T

42 lines
1.5 KiB
Bash
Raw Normal View History

#!/usr/bin/env bash
# Cascade focus: window → occupied workspace → monitor (cycles at edges)
# Skips the trailing empty workspace — jumps to the monitor instead.
# usage: niri-focus.sh up|down
set -euo pipefail
dir="${1:?usage: niri-focus.sh up|down}"
opp=$([ "$dir" = down ] && echo up || echo down)
out() { niri msg --json focused-output | jq -r '.name // "none"'; }
win() { niri msg --json focused-window | jq -r '.id // "none"'; }
# 1) window within the column
w0=$(win); niri msg action "focus-window-$dir" >/dev/null 2>&1 || true
[ "$(win)" != "$w0" ] && exit 0
# 2) occupied workspace in that direction (skip the empty trailing one)
wss=$(niri msg --json workspaces)
wins=$(niri msg --json windows)
cwsid=$(jq -r 'map(select(.is_focused)) | .[0].id' <<<"$wss")
real_neighbor=$(jq -n --argjson wss "$wss" --argjson wins "$wins" \
--argjson cwsid "$cwsid" --arg dir "$dir" '
($wss[] | select(.id==$cwsid)) as $c
| [ $wss[]
| select(.output==$c.output)
| select(if $dir=="down" then .idx>$c.idx else .idx<$c.idx end)
| .id as $wid
| select([$wins[] | select(.workspace_id==$wid)] | length > 0) ]
| length > 0')
if [ "$real_neighbor" = "true" ]; then
niri msg action "focus-workspace-$dir" >/dev/null 2>&1 || true
exit 0
fi
# 3) adjacent monitor… or wrap to the far-end monitor
o0=$(out); niri msg action "focus-monitor-$dir" >/dev/null 2>&1 || true
[ "$(out)" != "$o0" ] && exit 0
while :; do
prev=$(out)
niri msg action "focus-monitor-$opp" >/dev/null 2>&1 || true
[ "$(out)" = "$prev" ] && break
done