101 lines
2.8 KiB
Bash
Raw Permalink Normal View History

2026-03-09 00:07:31 -04:00
#!/usr/bin/env bash
set -uo pipefail
SAME_MONITOR=0
while [ $# -gt 0 ]; do
case "$1" in
--same)
SAME_MONITOR=1
shift
;;
*)
shift
;;
esac
done
WINDOWS=$(hyprctl activewindow -j)
MONITORS=$(hyprctl monitors -j)
WORKSPACES=$(hyprctl workspaces -j)
ACTIVE_WORKSPACE=$(hyprctl activeworkspace -j)
CURRENT_WS_ID=$(echo "$WINDOWS" | jq '.workspace.id')
CURRENT_MONITOR=$(echo "$WINDOWS" | jq -r '.monitor')
CURRENT_NAME=$(echo "$MONITORS" | jq -r ".[$CURRENT_MONITOR].name")
ACTIVE_WS_ID=$(echo "$ACTIVE_WORKSPACE" | jq -r '.id')
TARGET_INDEX=$CURRENT_MONITOR
if [[ $SAME_MONITOR -eq 0 ]]; then
TARGET_INDEX=$((1 - CURRENT_MONITOR))
fi
TARGET=$(echo "$MONITORS" | jq -r ".[$TARGET_INDEX].name")
next_empty_workspace() {
local start_search_id=$1
local current_workspaces=$2
local i=$start_search_id
while jq -e ".[] | select(.id == $i)" <<< "$current_workspaces" > /dev/null; do
i=$((i + 1))
done
echo "$i"
}
check_current_workspaces() {
local target_monitor_name=$1
local ws_json=$2
echo "$ws_json" | jq -r --arg tmn "$target_monitor_name" '
[ .[] | select(.monitor == $tmn and .windows == 0) ] |
if length > 0 then (min_by(.id) | .id) else empty end
'
}
NEW_WORKSPACE=""
if [[ $CURRENT_MONITOR -eq 0 && $SAME_MONITOR -eq 1 ]]; then
if ! jq -e '.[] | select(.id == 2 and .windows > 0)' <<< "$WORKSPACES" > /dev/null; then
NEW_WORKSPACE=2
fi
fi
if [[ -z "$NEW_WORKSPACE" ]]; then
CANDIDATE_WS_ON_MONITOR=$(check_current_workspaces "$TARGET" "$WORKSPACES")
if [[ -n "$CANDIDATE_WS_ON_MONITOR" ]]; then
NEW_WORKSPACE="$CANDIDATE_WS_ON_MONITOR"
fi
fi
if [[ -z "$NEW_WORKSPACE" ]]; then
_START_FIND_ID=1
if [[ $CURRENT_MONITOR -eq 0 && $SAME_MONITOR -eq 0 ]]; then
_START_FIND_ID=2
fi
NEW_WORKSPACE=$(next_empty_workspace "$_START_FIND_ID" "$WORKSPACES")
fi
DEFAULT_WORKSPACE=$((CURRENT_MONITOR + 1))
FLOATING_ADDRESS=$(echo "$WINDOWS" | jq -r 'select(.floating == true) | .address // empty')
if [[ -n "$FLOATING_ADDRESS" ]]; then
hyprctl dispatch "togglefloating address:$FLOATING_ADDRESS"
fi
NO_WINDOWS=$(echo "$WORKSPACES" | jq ".[] | select(.id == $CURRENT_WS_ID) | .windows // 0")
hyprctl dispatch movewindow mon:"$TARGET"
hyprctl dispatch movetoworkspace "$NEW_WORKSPACE"
if [[ $CURRENT_WS_ID -lt 0 ]]; then
# Don't change workspaces when moving from a negative workspace ID
hyprctl dispatch workspace "$ACTIVE_WS_ID"
elif [[ $SAME_MONITOR -eq 1 ]]; then
hyprctl dispatch workspace "$NEW_WORKSPACE"
elif [[ $NO_WINDOWS -eq 1 ]]; then
hyprctl dispatch focusmonitor "$CURRENT_NAME"
hyprctl dispatch workspace "$DEFAULT_WORKSPACE"
else
hyprctl dispatch workspace "$CURRENT_WS_ID"
fi