#!/bin/bash # omarchy:summary=Pick a screen region over frozen screen content # omarchy:args=[region|windows|smart|fullscreen] [--keep-freeze] [--match-monitor] # omarchy:hidden=true # Prints the picked geometry in slurp's "X,Y WxH" format, or exits 1 when the # pick is cancelled. Shared by screenshot and screen recording so the picker # UX stays identical. # # region freeform selection # windows snap selection to a monitor or window rectangle # smart freeform with window/monitor rects hinted; a bare click # (area < 20px^2) snaps to the rectangle it landed in # fullscreen the focused monitor, no interaction # # --keep-freeze leave the hyprpicker screen freeze running and print its # PID as the first output line (empty when no freeze was # started); the caller owns killing it # --match-monitor print "monitor:NAME" instead when the picked geometry # exactly matches a monitor MODE=smart KEEP_FREEZE=false MATCH_MONITOR=false for arg in "$@"; do case $arg in --keep-freeze) KEEP_FREEZE=true ;; --match-monitor) MATCH_MONITOR=true ;; *) MODE=$arg ;; esac done # accounting for portrait/transformed displays JQ_MONITOR_GEO=' def format_geo: .x as $x | .y as $y | (.width / .scale | floor) as $w | (.height / .scale | floor) as $h | .transform as $t | if $t == 1 or $t == 3 then "\($x),\($y) \($h)x\($w)" else "\($x),\($y) \($w)x\($h)" end; ' get_rectangles() { local active_workspace=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .activeWorkspace.id') hyprctl monitors -j | jq -r --arg ws "$active_workspace" "${JQ_MONITOR_GEO} .[] | select(.activeWorkspace.id == (\$ws | tonumber)) | format_geo" hyprctl clients -j | jq -r --arg ws "$active_workspace" '.[] | select(.workspace.id == ($ws | tonumber)) | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' } FREEZE_PID="" freeze_screen() { hyprpicker -r -z >/dev/null 2>&1 & FREEZE_PID=$! sleep .1 } cleanup_freeze() { [[ $KEEP_FREEZE == true ]] && return [[ -n $FREEZE_PID ]] && kill $FREEZE_PID 2>/dev/null } trap cleanup_freeze EXIT case "$MODE" in region) freeze_screen SELECTION=$(slurp 2>/dev/null) ;; windows) freeze_screen SELECTION=$(get_rectangles | slurp -r 2>/dev/null) ;; fullscreen) SELECTION=$(hyprctl monitors -j | jq -r "${JQ_MONITOR_GEO} .[] | select(.focused == true) | format_geo") ;; smart | *) RECTS=$(get_rectangles) freeze_screen SELECTION=$(echo "$RECTS" | slurp 2>/dev/null) # A bare click (area < 20px^2) snaps to whichever rectangle it landed in, # so users don't end up with accidental 2px captures. X and Y can be # negative (Hyprland monitor positions in multi-display layouts). if [[ $SELECTION =~ ^(-?[0-9]+),(-?[0-9]+)[[:space:]]([0-9]+)x([0-9]+)$ ]] && ((BASH_REMATCH[3] * BASH_REMATCH[4] < 20)); then click_x=${BASH_REMATCH[1]} click_y=${BASH_REMATCH[2]} while IFS= read -r rect; do [[ $rect =~ ^(-?[0-9]+),(-?[0-9]+)[[:space:]]([0-9]+)x([0-9]+)$ ]] || continue rect_x=${BASH_REMATCH[1]} rect_y=${BASH_REMATCH[2]} rect_width=${BASH_REMATCH[3]} rect_height=${BASH_REMATCH[4]} if ((click_x >= rect_x && click_x < rect_x + rect_width && click_y >= rect_y && click_y < rect_y + rect_height)); then SELECTION="${rect_x},${rect_y} ${rect_width}x${rect_height}" break fi done <<<"$RECTS" fi ;; esac [[ $KEEP_FREEZE == true ]] && echo "$FREEZE_PID" [[ -n $SELECTION ]] || exit 1 if [[ $MATCH_MONITOR == true ]]; then monitor=$(hyprctl monitors -j | jq -r --arg geo "$SELECTION" "${JQ_MONITOR_GEO} .[] | select(format_geo == \$geo) | .name" | head -1) if [[ -n $monitor ]]; then echo "monitor:$monitor" exit 0 fi fi echo "$SELECTION"