#!/bin/sh # Layout-aware navigation for Hyprland # Usage: layout-navigate [move] # direction: next|prev # move: if present, move window instead of focus DIR="$1" MOVE="$2" ACTIVE_JSON=$(hyprctl activewindow -j) FLOATING=$(echo "$ACTIVE_JSON" | jq -r '.floating') WS_NAME=$(echo "$ACTIVE_JSON" | jq -r '.workspace.name') LAYOUT=$(hyprctl getoption general:layout -j | jq -r '.str') # If the active window is in a special workspace (scratchpad overlay) and we # are navigating focus (not moving), hide the overlay first. layoutmsg/cyclenext # cannot cross the overlay→regular boundary, so without this the $mod+J key # gets trapped inside the scratchpad. case "$WS_NAME" in special:*) if [ "$MOVE" != "move" ]; then hyprctl dispatch togglespecialworkspace "${WS_NAME#special:}" # Re-read state: focus has moved to the regular workspace. ACTIVE_JSON=$(hyprctl activewindow -j) FLOATING=$(echo "$ACTIVE_JSON" | jq -r '.floating') fi ;; esac # If current window is floating, use cyclenext to reach tiled windows if [ "$FLOATING" = "true" ] && [ "$MOVE" != "move" ]; then if [ "$DIR" = "next" ]; then hyprctl dispatch cyclenext tiled else hyprctl dispatch cyclenext prev tiled fi exit 0 fi case "$LAYOUT" in scrolling) # J (next) goes left, K (prev) goes right if [ "$MOVE" = "move" ]; then if [ "$DIR" = "next" ]; then hyprctl dispatch swapwindow l else hyprctl dispatch swapwindow r fi else if [ "$DIR" = "next" ]; then hyprctl dispatch layoutmsg focus l else hyprctl dispatch layoutmsg focus r fi fi ;; *) # master, dwindle, etc. if [ "$MOVE" = "move" ]; then if [ "$DIR" = "next" ]; then hyprctl dispatch layoutmsg swapnext else hyprctl dispatch layoutmsg swapprev fi else if [ "$DIR" = "next" ]; then hyprctl dispatch layoutmsg cyclenext else hyprctl dispatch layoutmsg cycleprev fi fi ;; esac