|
#!/bin/bash |
|
# <https://gist.github.com/mildred/8c6983295fe5ff8522028e7a2c7c7a0b> |
|
|
|
subscribe_workspaces(){ |
|
swaymsg -t subscribe -m '["workspace"]' \ |
|
| jq --unbuffered -r '[ .old.num, .old.output, .current.num, .current.output, .current.focused ] | join(";")' |
|
} |
|
|
|
index_of(){ |
|
local i=0 |
|
local resval="$1" |
|
local needle="$2" |
|
shift 2 |
|
|
|
for item in "$@"; do |
|
if [[ $item == $needle ]]; then |
|
eval "${resval}=\$i" |
|
return 0 |
|
fi |
|
let i++ |
|
done |
|
eval "${resval}=" |
|
return 1 |
|
} |
|
|
|
log(){ |
|
( set -x |
|
"$@" |
|
) |
|
} |
|
|
|
update_other_workspaces(){ |
|
local num="$1" |
|
local current_output="$2" |
|
local current_output_index="$3" |
|
|
|
local group_index |
|
let group_index=num%10 |
|
local json_workspaces="$(swaymsg -r -t get_workspaces)" |
|
local need_move_back=false |
|
|
|
local i=-1 |
|
for target_output in "${outputs[@]}"; do |
|
let i++ |
|
local target_num |
|
let target_num=i*10+group_index |
|
|
|
if [[ $target_output = $current_output ]]; then |
|
continue |
|
fi |
|
|
|
#echo "Workspace $num on $current_output_index:$current_output maps to $target_num on $i:$target_output" |
|
|
|
target_workspace_output="$(<<<"$json_workspaces" \ |
|
jq -r --arg num "$target_num" \ |
|
'.[] | select(.num == ($num|tonumber)) | .output')" |
|
|
|
target_workspace_visible="$(<<<"$json_workspaces" \ |
|
jq -r --arg num "$target_num" \ |
|
'.[] | select(.num == ($num|tonumber)) | .visible')" |
|
|
|
if [[ $target_workspace_visible = true ]]; then |
|
# Target workspace already visible, do nothing |
|
true |
|
elif [[ -z "$target_workspace_output" ]]; then |
|
echo "$num on $current_output_index:$current_output -> (new) $target_num on $i:$target_output" |
|
# The workspace does not exists, create it and switch to it |
|
log swaymsg workspace $target_num output $target_output |
|
log swaymsg workspace $target_num |
|
ignore+=($target_num) |
|
need_move_back=true |
|
elif [[ $target_workspace_output = $target_output ]]; then |
|
echo "$num on $current_output_index:$current_output -> (existing) $target_num on $i:$target_output" |
|
# The workspace exists and is already on correct output, switch to it |
|
log swaymsg workspace $target_num |
|
ignore+=($target_num) |
|
need_move_back=true |
|
else |
|
echo "Workspace $target_num is already on output $target_workspace_output, not moving to $target_output" |
|
fi |
|
done |
|
|
|
if $need_move_back; then |
|
# Switch back to current workspace if needed |
|
echo "$num on $current_output_index:$current_output (move back)" |
|
log swaymsg workspace $num |
|
ignore+=($num) |
|
need_move_back=false |
|
fi |
|
} |
|
|
|
update_workspace_on_output_change(){ |
|
local ws="$1" |
|
local target_num |
|
|
|
let target_num=current_output_index*10+ws |
|
|
|
target_workspace_output="$(<<<"$json_workspaces" \ |
|
jq -r --arg num "$target_num" \ |
|
'.[] | select(.num == ($num|tonumber)) | .output')" |
|
|
|
target_workspace_visible="$(<<<"$json_workspaces" \ |
|
jq -r --arg num "$target_num" \ |
|
'.[] | select(.num == ($num|tonumber)) | .visible')" |
|
|
|
if [[ $target_workspace_visible = true ]]; then |
|
# Target workspace already visible, do nothing |
|
echo "$target_num visible on $target_workspace_output" |
|
true |
|
elif [[ $num != $target_num ]] && [[ -z "$target_workspace_output" ]]; then |
|
echo "=> (new) $target_num on $current_output_index:$current_output" |
|
# The workspace does not exists, create it and switch to it |
|
log swaymsg workspace $target_num output $current_output |
|
log swaymsg workspace $target_num |
|
# ignore+=($target_num) |
|
elif [[ $num != $target_num ]] && [[ $target_workspace_output = $current_output ]]; then |
|
# The workspace exists and is already on correct output, switch to it |
|
echo "=> (existing) $target_num on $current_output_index:$current_output" |
|
log swaymsg workspace $target_num |
|
# ignore+=($target_num) |
|
else |
|
echo "$target_num already on $current_output_index:$current_output" |
|
fi |
|
} |
|
|
|
ignore=() |
|
|
|
subscribe_workspaces | while IFS=';' read last_num last_output num current_output focused; do |
|
if [[ ${ignore[0]} == $num ]]; then |
|
echo "ignore event" |
|
ignore=("${ignore[@]:1}") |
|
continue |
|
#elif [[ -n "${ignore[0]}" ]]; then |
|
# echo "Ignore event: $num $current_output (not in list, expect ${ignore[0]})" |
|
# continue |
|
fi |
|
|
|
outputs=($(swaymsg -r -t get_outputs | jq -r '.[] | .name')) |
|
|
|
if ! index_of current_output_index "$current_output" "${outputs[@]}"; then |
|
echo -n "[$last_num on $last_output_index:$last_output -> $num on $current_output_index:$current_output] " |
|
>&2 echo "Failed to recognize current workspace $num output $current_output in (${outputs[@]})" |
|
continue |
|
fi |
|
|
|
if ! index_of last_output_index "$last_output" "${outputs[@]}"; then |
|
echo -n "[$last_num on $last_output_index:$last_output -> $num on $current_output_index:$current_output] " |
|
>&2 echo "Failed to recognize last workspace $num output $last_output in (${outputs[@]})" |
|
continue |
|
fi |
|
|
|
# echo "detect workspace change $num on $current_output_index:$current_output (focused: $focused)" |
|
echo -n "[$last_num on $last_output_index:$last_output -> $num on $current_output_index:$current_output] " |
|
|
|
|
|
let expected_output_index=num/10 |
|
if [[ $expected_output_index != $current_output_index ]]; then |
|
echo "Workspace $num should be on output ${outputs[$expected_output_index]} and not ${outputs[$current_output_index]}" |
|
last_num="$num" |
|
last_output="$current_output" |
|
last_output_index= |
|
continue |
|
fi |
|
|
|
if [[ -z "$ws" ]]; then |
|
let ws=last_num%10 |
|
fi |
|
|
|
if [[ $last_output = $current_output ]]; then |
|
let ws=num%10 |
|
echo "ws=$ws" |
|
else |
|
update_workspace_on_output_change "$ws" |
|
fi |
|
|
|
# update_other_workspaces "$num" "$current_output" "$current_output_index" |
|
|
|
done |