Files
omarchycn/bin/omarchy-capture-screenshot
T
David Heinemeier HanssonandClaude Fable 5 fa2b997513 Keep software-composited cursors out of screenshots
Hyprland falls back to compositing the cursor into the frame on GPUs
without working hardware cursors, so grim would capture it. Force
hardware cursors for the duration of the capture and restore after.

Closes #6142

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18 15:42:01 -07:00

88 lines
2.4 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.
#
# Software-composited cursors (Hyprland's fallback on GPUs without working
# hardware cursors) are baked into the frames grim captures, so force
# hardware cursors until after grim runs and restore the setting on exit.
NO_HW_CURSORS=$(hyprctl getoption cursor:no_hardware_cursors -j | jq '.int')
set_no_hw_cursors() {
hyprctl eval "hl.config({ cursor = { no_hardware_cursors = $1 } })" &>/dev/null ||
hyprctl keyword cursor:no_hardware_cursors "$1" &>/dev/null
}
cleanup() {
[[ -n $FREEZE_PID ]] && kill $FREEZE_PID 2>/dev/null
set_no_hw_cursors "$NO_HW_CURSORS"
}
trap cleanup EXIT
set_no_hw_cursors 0
{ read -r FREEZE_PID; read -r SELECTION; } < <(omarchy-capture-region "$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