#!/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