Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

### 2026-10-06

grimblast: support cursor in frozen area capture

### 2026-10-05

grimblast: create parent dirs when saving to file instead of failing when they don't exist.
Expand Down
23 changes: 17 additions & 6 deletions grimblast/grimblast
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,16 @@ get-mime-type() {
}

freezescreen() {
hyprpicker -rz &
local args=(-r -z)
[[ $CURSOR ]] && hyprpicker-supports-cursor && args+=(-c)
hyprpicker "${args[@]}" &
sleep 0.2
}

hyprpicker-supports-cursor() {
hyprpicker --help 2>&1 | grep -q -- '--cursor'
}

# Checks whether an individual tool is available
# If invoked with -q (quiet), no output is printed, useful for use in tests
# Exits with 0 if the tool is available, non-zero otherwise
Expand Down Expand Up @@ -156,7 +162,7 @@ screenshot() {
if [[ -n "$file" ]]; then
mkdir -p "$(dirname "$file")"
fi
xargs --verbose grim <<<"${CURSOR:+-c} ${SCALE:+-s \"$SCALE\"} -t \"$FILETYPE\" ${output:+-o \"$output\"} ${GEOM:+-g \"$GEOM\"} ${WINDOW:+-T \"$WINDOW\"} \"$file\""
xargs --verbose grim <<<"${CAPTURE_CURSOR:+-c} ${SCALE:+-s \"$SCALE\"} -t \"$FILETYPE\" ${output:+-o \"$output\"} ${GEOM:+-g \"$GEOM\"} ${WINDOW:+-T \"$WINDOW\"} \"$file\""
}

# Special actions: usage and check. These are special because they allow to exit early
Expand Down Expand Up @@ -217,11 +223,15 @@ output() {
}

area() {
local fullscreen_workspaces workspaces windows choice rects
[[ $CURSOR ]] && die "'-c|--cursor' cannot be used with TARGET 'area'"
local fullscreen_workspaces workspaces windows choice rects frozen_cursor
[[ $CURSOR && ! $FREEZE ]] && die "'-c|--cursor' can only be used with TARGET 'area' when '-f|--freeze' is also set"

if [[ $FREEZE ]] && grimblast::check -q hyprpicker; then
if [[ $FREEZE ]]; then
grimblast::check -q hyprpicker || die "'-f|--freeze' requires hyprpicker"
[[ ! $CURSOR ]] || hyprpicker-supports-cursor || die "'-c|--cursor' with TARGET 'area' and '-f|--freeze' requires a hyprpicker version with --cursor support"
freezescreen
frozen_cursor=$CURSOR
CURSOR=
fi

# disable animation for layer namespace "selection" (slurp)
Expand All @@ -244,7 +254,8 @@ area() {
# use `|` as separator for stableId label
choice="$(echo -n "$rects" | slurp -o "${SLURP_ARGS[@]}" -f "%x,%y %wx%h|%l")"

WINDOW="$(jq -r --arg c "$choice" '.[] | select("\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])|\(.stableId)" == $c) | .stableId' <<<"$windows")"
# toplevel capture is live, so it would miss the cursor drawn in the frozen preview
[[ $frozen_cursor ]] || WINDOW="$(jq -r --arg c "$choice" '.[] | select("\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])|\(.stableId)" == $c) | .stableId' <<<"$windows")"
[[ -z "$WINDOW" ]] && GEOM="${choice%|*}"

grimblast::wait
Expand Down
5 changes: 4 additions & 1 deletion grimblast/grimblast.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ grimblast - a helper for screenshots within Hyprland
Only works with --notify. Default: 3000.

*-c, --cursor*
Include cursors in the screenshot.
Include cursors in the screenshot. With the _area_ target, this option
requires *--freeze* so the cursor is included in the frozen preview and
not captured again at the final selection position. This also requires a
hyprpicker version with *--cursor* support.

*-f, --freeze*
Freezes the screen before area selection.
Expand Down
16 changes: 16 additions & 0 deletions grimblast/test/test.bats
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,22 @@ teardown() {
pngcheck -q "$outfile"
}

# bats test_tags=arguments
@test "Can screenshot area with freeze and cursor" {
DEFAULT_TARGET_DIR="$TEST_DIR" run --separate-stderr grimblast save area --freeze --cursor
assert_success
outfile="$(extract_outfile_from_output "$output")"
assert_file_exist "$outfile"
pngcheck -q "$outfile"
}

# bats test_tags=arguments
@test "Rejects cursor for area without freeze" {
run grimblast --cursor save area
assert_failure
assert_output --partial "can only be used with TARGET 'area' when '-f|--freeze' is also set"
}

# bats test_tags=arguments
@test "Can screenshot area, to a file, with freeze and notify at the end" {
run --separate-stderr grimblast save area "$TEST_DIR/test.png" --notify --freeze
Expand Down