machine_setup/nix/configuration/roles/sway/files/workspace_helper.bash
2026-03-07 16:39:21 -05:00

174 lines
6.0 KiB
Bash

#!/usr/bin/env bash
#
# A helper to manage workspaces across multiple monitors.
set -euo pipefail
IFS=$'\n\t'
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# TODO: Only move output if it is on the wrong monitor
############## Setup #########################
# function cleanup {
# log "Killing child process $wlsunset_pid"
# kill "$wlsunset_pid"
# true
# }
# for sig in EXIT; do
# trap "set +e; cleanup" "$sig"
# done
function die {
local status_code="$1"
shift
(>&2 echo "${@}")
exit "$status_code"
}
function log {
(>&2 echo "${@}")
}
############## Program #########################
function main {
local cmd="$1"
shift
if [ "$cmd" = "go_to_next_monitor" ]; then
go_to_next_monitor "${@}"
elif [ "$cmd" = "send_to_next_monitor" ]; then
send_to_next_monitor "${@}"
elif [ "$cmd" = "go_to_previous_monitor" ]; then
go_to_previous_monitor "${@}"
elif [ "$cmd" = "send_to_previous_monitor" ]; then
send_to_previous_monitor "${@}"
elif [ "$cmd" = "go_to_workspace" ]; then
go_to_workspace "${@}"
elif [ "$cmd" = "send_to_workspace" ]; then
send_to_workspace "${@}"
else
die 1 "Unrecognized command $cmd"
fi
}
function go_to_next_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index+1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg workspace "${target}" \; move workspace to output "$output"
}
function send_to_next_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index+1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg move container to workspace "${target}" \; workspace "$target" move to output "$output"
}
function go_to_previous_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index-1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg workspace "${target}" \; move workspace to output "$output"
}
function send_to_previous_monitor {
local monitor_index workspace_index workspace
workspace=$(swaymsg -t get_workspaces | jq -r '.[] | select(.focused == true) | .name')
workspace_index=$(parse_workspace_index "${workspace}")
# monitor_index=$(parse_monitor_index "${workspace}")
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
local target output target_monitor
target_monitor=$(normalize_monitor_index "$((monitor_index-1))")
target=$(encode_workspace "${target_monitor}" "${workspace_index}")
output=$(get_output "${target_monitor}")
swaymsg move container to workspace "${target}" \; workspace "$target" move to output "$output"
}
function go_to_workspace {
local monitor_index workspace_index workspace output
workspace_index="$1"
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
workspace=$(encode_workspace "$monitor_index" "$workspace_index")
output=$(get_output "${monitor_index}")
swaymsg workspace "${workspace}" \; move workspace to output "$output"
}
function send_to_workspace {
local monitor_index workspace_index workspace output
workspace_index="$1"
monitor_index=$(swaymsg -t get_outputs | jq 'map(.focused) | to_entries | .[] | select(.value) | .key')
workspace=$(encode_workspace "$monitor_index" "$workspace_index")
output=$(get_output "${monitor_index}")
swaymsg move container to workspace "${workspace}" \; workspace "${workspace}" move to output "$output"
}
function get_output {
local monitor_index output
monitor_index="$1"
output=$(swaymsg -t get_outputs | jq -r ".[${monitor_index}].name")
echo "$output"
}
function encode_workspace {
local monitor_index workspace_index
monitor_index="$1"
workspace_index="$2"
if [ "$monitor_index" = "0" ]; then
echo "$workspace_index"
else
echo "${monitor_index}-${workspace_index}"
fi
}
function parse_monitor_index {
local workspace="$1"
if [[ $workspace = *-* ]]; then
cut -d '-' -f 1 <<<"$workspace"
else
echo "0"
fi
}
function parse_workspace_index {
local workspace="$1"
if [[ $workspace = *-* ]]; then
cut -d '-' -f 2 <<<"$workspace"
else
echo "$workspace"
fi
}
function normalize_monitor_index {
local monitor_index num_monitors
monitor_index="$1"
num_monitors=$(swaymsg -t get_outputs | jq length)
while [ "$monitor_index" -lt 0 ]; do
monitor_index=$((monitor_index + num_monitors))
done
while [ "$monitor_index" -ge "$num_monitors" ]; do
monitor_index=$((monitor_index - num_monitors))
done
echo "$monitor_index"
}
main "${@}"