Files
omarchycn/bin/omarchy-capture-screenshot
T
David Heinemeier HanssonandClaude Fable 5 362d97c151 Share one region picker between screenshot and recording
Both capture scripts carried the same pipeline: workspace rectangles
from hyprctl, a hyprpicker freeze, slurp, and the bare-click snap loop.
The copies had already diverged once (rotated-display handling), so the
pipeline now lives in one hidden helper, omarchy-capture-region-pick,
which prints the picked geometry in slurp format.

The two callers differ only in what they layer on top. The screenshot
needs the freeze to outlive the pick so grim captures frozen content:
--keep-freeze leaves hyprpicker running and prints its PID first, with
the caller owning the kill. The recording prefers native full-monitor
capture: --match-monitor prints monitor:NAME when the geometry exactly
matches a display.

One deliberate fix along the way: the screenshot snap regex rejected
negative coordinates, so bare clicks on monitors positioned left of or
above the origin never snapped. The helper uses the recording variant,
which handles them.

Verified with an 11-case shim harness (snap precedence, rotated-monitor
match, freeze ownership, cancellation, negative coordinates) and the
live end-to-end screenshot sanity test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:26:46 -07:00

75 lines
1.9 KiB
Bash
Executable File

#!/bin/bash
# omarchy:summary=Take a screenshot
# omarchy:group=capture
# omarchy:args=[smart|region|windows|fullscreen] [slurp|copy|save] [--editor=<name>]
# omarchy:examples=omarchy screenshot | omarchy capture screenshot region
# omarchy:aliases=omarchy screenshot
[[ -f ~/.config/user-dirs.dirs ]] && source ~/.config/user-dirs.dirs
OUTPUT_DIR="${OMARCHY_SCREENSHOT_DIR:-${XDG_PICTURES_DIR:-$HOME/Pictures}}"
if [[ ! -d $OUTPUT_DIR ]]; then
mkdir -p "$OUTPUT_DIR"
omarchy-notification-send "Created screenshot directory: $OUTPUT_DIR" -t 2000
fi
pkill slurp && exit 0
SCREENSHOT_EDITOR="${OMARCHY_SCREENSHOT_EDITOR:-tensaku-edit}"
# Parse --editor flag from any position
ARGS=()
for arg in "$@"; do
if [[ $arg == --editor=* ]]; then
SCREENSHOT_EDITOR="${arg#--editor=}"
else
ARGS+=("$arg")
fi
done
set -- "${ARGS[@]}"
open_editor() {
local filepath="$1"
"$SCREENSHOT_EDITOR" "$filepath"
}
MODE="${1:-smart}"
PROCESSING="${2:-slurp}"
# The picker leaves the screen freeze running (PID on its first output line)
# so grim captures the frozen overlay rather than live content shifting
# during teardown.
cleanup_freeze() {
[[ -n $FREEZE_PID ]] && kill $FREEZE_PID 2>/dev/null
}
trap cleanup_freeze EXIT
{ read -r FREEZE_PID; read -r SELECTION; } < <(omarchy-capture-region-pick "$MODE" --keep-freeze)
[[ -z $SELECTION ]] && exit 0
FILENAME="screenshot-$(date +'%Y-%m-%d_%H-%M-%S').png"
FILEPATH="$OUTPUT_DIR/$FILENAME"
case "$PROCESSING" in
slurp)
grim -g "$SELECTION" "$FILEPATH" || exit 1
echo "$FILEPATH"
wl-copy --type image/png <"$FILEPATH"
(
if [[ -n $(omarchy-notification-send "Screenshot saved to clipboard and file" "Edit with Super + Alt + , (or click this)" --image "$FILEPATH" -a) ]]; then
open_editor "$FILEPATH"
fi
) >/dev/null 2>&1 &
;;
copy)
grim -g "$SELECTION" - | wl-copy --type image/png
;;
save)
grim -g "$SELECTION" "$FILEPATH" || exit 1
echo "$FILEPATH"
;;
esac