#!/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 "${@}"