From 432ad4736df65ff7a4b3d39c109856902389da43 Mon Sep 17 00:00:00 2001 From: Juan Tamayo Date: Tue, 7 Oct 2025 19:02:22 -0500 Subject: [PATCH 1/3] Add monitor swap functionality --- default/hypr/bindings/utilities.conf | 3 +++ omarchy-swap-monitors | 35 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100755 omarchy-swap-monitors diff --git a/default/hypr/bindings/utilities.conf b/default/hypr/bindings/utilities.conf index c8b3efdbd5..c6ae00627e 100644 --- a/default/hypr/bindings/utilities.conf +++ b/default/hypr/bindings/utilities.conf @@ -24,6 +24,9 @@ bindd = SUPER CTRL, I, Toggle locking on idle, exec, omarchy-toggle-idle # Toggle nightlight bindd = SUPER CTRL, N, Toggle nightlight, exec, omarchy-toggle-nightlight +# Swap between monitors +bindd = SUPER CTRL, M, Swap monitors, exec, omarchy-swap-monitors + # Control Apple Display brightness bindd = CTRL, F1, Apple Display brightness down, exec, omarchy-cmd-apple-display-brightness -5000 bindd = CTRL, F2, Apple Display brightness up, exec, omarchy-cmd-apple-display-brightness +5000 diff --git a/omarchy-swap-monitors b/omarchy-swap-monitors new file mode 100755 index 0000000000..6dc7bcd612 --- /dev/null +++ b/omarchy-swap-monitors @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# Safe workspace swap between two monitors in Hyprland/Omarchy + +readonly TMP_WORKSPACE=999 +readonly APP_NAME="Omarchy" + +mapfile -t MONITORS < <(hyprctl monitors -j | jq -r '.[].name') + +if (( ${#MONITORS[@]} < 2 )); then + notify-send "$APP_NAME" "Only one monitor detected — nothing to swap." + exit 0 +fi + +readonly MON1="${MONITORS[0]}" +readonly MON2="${MONITORS[1]}" + +get_active_workspace() { + hyprctl monitors -j | jq -r ".[] | select(.name==\"$1\") | .activeWorkspace.id" +} + +WS1=$(get_active_workspace "$MON1") +WS2=$(get_active_workspace "$MON2") + +if [[ -z "$WS1" || -z "$WS2" ]]; then + notify-send "$APP_NAME" "Could not detect active workspaces on both monitors." + exit 1 +fi + +hyprctl dispatch workspace "$TMP_WORKSPACE" +hyprctl dispatch moveworkspacetomonitor "$TMP_WORKSPACE" "$MON1" +hyprctl dispatch moveworkspacetomonitor "$WS1" "$MON2" +hyprctl dispatch moveworkspacetomonitor "$WS2" "$MON1" +hyprctl dispatch workspace "$WS2" + +notify-send "$APP_NAME" "Swapped workspaces between $MON1 and $MON2." From c242d320ae6c48bb793d375352354df27a6ee4c5 Mon Sep 17 00:00:00 2001 From: Juan Tamayo Date: Wed, 8 Oct 2025 11:28:18 -0500 Subject: [PATCH 2/3] address woopstar suggestions --- bin/omarchy-swap-monitors | 42 +++++++++++++++++++++++++++++++++++++++ omarchy-swap-monitors | 35 -------------------------------- 2 files changed, 42 insertions(+), 35 deletions(-) create mode 100755 bin/omarchy-swap-monitors delete mode 100755 omarchy-swap-monitors diff --git a/bin/omarchy-swap-monitors b/bin/omarchy-swap-monitors new file mode 100755 index 0000000000..92409abff5 --- /dev/null +++ b/bin/omarchy-swap-monitors @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Rotate workspaces across all monitors in Hyprland/Omarchy + +readonly TMP_WORKSPACE=999 +readonly APP_NAME="Omarchy" + +mapfile -t MONITORS < <(hyprctl monitors -j | jq -r '.[].name') + +if (( ${#MONITORS[@]} < 2 )); then + notify-send "$APP_NAME" "Only one monitor detected — nothing to rotate." + exit 0 +fi + +get_active_workspace() { + hyprctl monitors -j | jq -r ".[] | select(.name==\"$1\") | .activeWorkspace.id" +} + +# Store all active workspaces +declare -a WORKSPACES +for mon in "${MONITORS[@]}"; do + ws=$(get_active_workspace "$mon") + if [[ -z "$ws" ]]; then + notify-send "$APP_NAME" "Could not detect workspace on $mon." + exit 1 + fi + WORKSPACES+=("$ws") +done + +# Move current workspace to temp +hyprctl dispatch workspace "$TMP_WORKSPACE" +hyprctl dispatch moveworkspacetomonitor "$TMP_WORKSPACE" "${MONITORS[0]}" + +# Rotate: each monitor gets the workspace from the previous monitor +for (( i=${#MONITORS[@]}-1; i>=0; i-- )); do + prev_idx=$(( (i - 1 + ${#MONITORS[@]}) % ${#MONITORS[@]} )) + hyprctl dispatch moveworkspacetomonitor "${WORKSPACES[$prev_idx]}" "${MONITORS[$i]}" +done + +# Focus the workspace that moved to the first monitor +hyprctl dispatch workspace "${WORKSPACES[-1]}" + +notify-send "$APP_NAME" "Rotated workspaces across ${#MONITORS[@]} monitors." diff --git a/omarchy-swap-monitors b/omarchy-swap-monitors deleted file mode 100755 index 6dc7bcd612..0000000000 --- a/omarchy-swap-monitors +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Safe workspace swap between two monitors in Hyprland/Omarchy - -readonly TMP_WORKSPACE=999 -readonly APP_NAME="Omarchy" - -mapfile -t MONITORS < <(hyprctl monitors -j | jq -r '.[].name') - -if (( ${#MONITORS[@]} < 2 )); then - notify-send "$APP_NAME" "Only one monitor detected — nothing to swap." - exit 0 -fi - -readonly MON1="${MONITORS[0]}" -readonly MON2="${MONITORS[1]}" - -get_active_workspace() { - hyprctl monitors -j | jq -r ".[] | select(.name==\"$1\") | .activeWorkspace.id" -} - -WS1=$(get_active_workspace "$MON1") -WS2=$(get_active_workspace "$MON2") - -if [[ -z "$WS1" || -z "$WS2" ]]; then - notify-send "$APP_NAME" "Could not detect active workspaces on both monitors." - exit 1 -fi - -hyprctl dispatch workspace "$TMP_WORKSPACE" -hyprctl dispatch moveworkspacetomonitor "$TMP_WORKSPACE" "$MON1" -hyprctl dispatch moveworkspacetomonitor "$WS1" "$MON2" -hyprctl dispatch moveworkspacetomonitor "$WS2" "$MON1" -hyprctl dispatch workspace "$WS2" - -notify-send "$APP_NAME" "Swapped workspaces between $MON1 and $MON2." From 72c817ec910b01449de0c595502a95223d7efd66 Mon Sep 17 00:00:00 2001 From: Juan Tamayo Date: Wed, 8 Oct 2025 13:51:10 -0500 Subject: [PATCH 3/3] remove temp workspace and use swapactiveworkspaces instead --- bin/omarchy-swap-monitors | 48 ++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/bin/omarchy-swap-monitors b/bin/omarchy-swap-monitors index 92409abff5..fb8a1f21de 100755 --- a/bin/omarchy-swap-monitors +++ b/bin/omarchy-swap-monitors @@ -1,9 +1,25 @@ #!/usr/bin/env bash # Rotate workspaces across all monitors in Hyprland/Omarchy -readonly TMP_WORKSPACE=999 readonly APP_NAME="Omarchy" +dispatch() { + local output + if ! output=$(hyprctl dispatch "$@" 2>&1); then + notify-send "$APP_NAME" "hyprctl dispatch failed: $output" + exit 1 + fi + + if [[ "$output" != "ok" ]]; then + notify-send "$APP_NAME" "$output" + exit 1 + fi +} + +get_active_workspace() { + hyprctl monitors -j | jq -r ".[] | select(.name==\"$1\") | .activeWorkspace.id" +} + mapfile -t MONITORS < <(hyprctl monitors -j | jq -r '.[].name') if (( ${#MONITORS[@]} < 2 )); then @@ -11,32 +27,28 @@ if (( ${#MONITORS[@]} < 2 )); then exit 0 fi -get_active_workspace() { - hyprctl monitors -j | jq -r ".[] | select(.name==\"$1\") | .activeWorkspace.id" -} +ORIGINAL_MONITOR=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name') + +if [[ -z "$ORIGINAL_MONITOR" || "$ORIGINAL_MONITOR" == "null" ]]; then + notify-send "$APP_NAME" "Could not detect the focused monitor." + exit 1 +fi -# Store all active workspaces -declare -a WORKSPACES +# Validate that every monitor has an active workspace before rotating. for mon in "${MONITORS[@]}"; do ws=$(get_active_workspace "$mon") - if [[ -z "$ws" ]]; then + if [[ -z "$ws" || "$ws" == "null" ]]; then notify-send "$APP_NAME" "Could not detect workspace on $mon." exit 1 fi - WORKSPACES+=("$ws") done -# Move current workspace to temp -hyprctl dispatch workspace "$TMP_WORKSPACE" -hyprctl dispatch moveworkspacetomonitor "$TMP_WORKSPACE" "${MONITORS[0]}" - -# Rotate: each monitor gets the workspace from the previous monitor -for (( i=${#MONITORS[@]}-1; i>=0; i-- )); do - prev_idx=$(( (i - 1 + ${#MONITORS[@]}) % ${#MONITORS[@]} )) - hyprctl dispatch moveworkspacetomonitor "${WORKSPACES[$prev_idx]}" "${MONITORS[$i]}" +# Swap neighbouring monitors from right-to-left to rotate without creating temps. +for (( i=${#MONITORS[@]}-1; i>=1; i-- )); do + dispatch swapactiveworkspaces "${MONITORS[$((i-1))]}" "${MONITORS[$i]}" done -# Focus the workspace that moved to the first monitor -hyprctl dispatch workspace "${WORKSPACES[-1]}" +# Ensure focus returns to the monitor the user was on. +dispatch focusmonitor "$ORIGINAL_MONITOR" notify-send "$APP_NAME" "Rotated workspaces across ${#MONITORS[@]} monitors."