feat: screenshots answer with a thumbnail notification
All four Print binds go through hypr/scripts/shot.sh. Every capture lands on the clipboard and posts a notification showing the picture, with Open, Save (for clipboard captures, which wait in the runtime dir) and Edit when satty is installed. Cancelling the region picker does nothing. Notification cards now load images passed as a path hint: Quickshell routes those through the icon provider, which returned a placeholder.
This commit is contained in:
1 parent
373584f34e
commit
31b57f4f8c
3 files changed
+88
-5
No files matched your search
@@ -5,10 +5,13 @@ local scripts = os.getenv("HOME") .. "/.config/hypr/scripts/"
|
|||||||
-- ------------------------------------------------------------- screenshots
|
-- ------------------------------------------------------------- screenshots
|
||||||
-- PRINT selects a region, CTRL grabs the focused window, SHIFT saves to disk
|
-- PRINT selects a region, CTRL grabs the focused window, SHIFT saves to disk
|
||||||
-- instead of the clipboard.
|
-- instead of the clipboard.
|
||||||
hl.bind("PRINT", hl.dsp.exec_cmd('grim -g "$(slurp)" - | wl-copy'))
|
-- All four go through scripts/shot.sh, which also posts a notification with
|
||||||
hl.bind("SHIFT + PRINT", hl.dsp.exec_cmd('grim -g "$(slurp)" ~/Pictures/Screenshots/$(date +\'%Y-%m-%d_%H-%M-%S\').png'))
|
-- the capture as its thumbnail (Open, Edit with satty, Save).
|
||||||
hl.bind("CTRL + PRINT", hl.dsp.exec_cmd(scripts .. "screenshot_window.sh copy"))
|
local shot = scripts .. "shot.sh "
|
||||||
hl.bind("CTRL + SHIFT + PRINT", hl.dsp.exec_cmd(scripts .. "screenshot_window.sh save"))
|
hl.bind("PRINT", hl.dsp.exec_cmd(shot .. "region copy"), { description = "screenshot an area to the clipboard" })
|
||||||
|
hl.bind("SHIFT + PRINT", hl.dsp.exec_cmd(shot .. "region save"), { description = "screenshot an area to a file" })
|
||||||
|
hl.bind("CTRL + PRINT", hl.dsp.exec_cmd(shot .. "window copy"), { description = "screenshot the window to the clipboard" })
|
||||||
|
hl.bind("CTRL + SHIFT + PRINT", hl.dsp.exec_cmd(shot .. "window save"), { description = "screenshot the window to a file" })
|
||||||
|
|
||||||
-- ------------------------------------------------------- replay and camera
|
-- ------------------------------------------------------- replay and camera
|
||||||
-- On release, so the shortcut is not caught mid-chord.
|
-- On release, so the shortcut is not caught mid-chord.
|
||||||
|
|||||||
Executable
+73
@@ -0,0 +1,73 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Screenshots with a receipt: every capture lands on the clipboard and comes
|
||||||
|
# back as a notification with its own thumbnail, so a keypress that used to
|
||||||
|
# vanish silently now shows what it took.
|
||||||
|
#
|
||||||
|
# shot.sh region copy pick an area, copy it
|
||||||
|
# shot.sh region save pick an area, save it to ~/Pictures/Screenshots
|
||||||
|
# shot.sh window copy the focused window, copy it
|
||||||
|
# shot.sh window save the focused window, save it
|
||||||
|
#
|
||||||
|
# A copy is kept in $XDG_RUNTIME_DIR only so the notification has a picture
|
||||||
|
# to show; its Save action moves it into ~/Pictures/Screenshots. Edit opens
|
||||||
|
# satty when it is installed. Cancelling the region picker does nothing.
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
target=${1:-region}
|
||||||
|
mode=${2:-copy}
|
||||||
|
|
||||||
|
dir="$HOME/Pictures/Screenshots"
|
||||||
|
stamp=$(date +'%Y-%m-%d_%H-%M-%S')
|
||||||
|
|
||||||
|
case "$target" in
|
||||||
|
region)
|
||||||
|
geometry=$(slurp) || exit 0
|
||||||
|
name="$stamp.png"
|
||||||
|
;;
|
||||||
|
window)
|
||||||
|
info=$(hyprctl activewindow -j)
|
||||||
|
geometry=$(printf '%s' "$info" | jq -r 'if .at then "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])" else empty end')
|
||||||
|
if [ -z "$geometry" ]; then
|
||||||
|
notify-send -a Screenshot "Screenshot" "No window is focused."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
app=$(printf '%s' "$info" | jq -r '.class // "unknown"' | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9_-]/_/g')
|
||||||
|
name="${app}_$stamp.png"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "usage: shot.sh region|window copy|save" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$mode" = save ]; then
|
||||||
|
mkdir -p "$dir"
|
||||||
|
file="$dir/$name"
|
||||||
|
else
|
||||||
|
file="${XDG_RUNTIME_DIR:-/tmp}/shot-$name"
|
||||||
|
fi
|
||||||
|
|
||||||
|
grim -g "$geometry" "$file"
|
||||||
|
wl-copy --type image/png < "$file"
|
||||||
|
|
||||||
|
title=$([ "$mode" = save ] && echo "Screenshot saved" || echo "Screenshot copied")
|
||||||
|
body=$([ "$mode" = save ] && echo "${file#"$HOME"/}" || echo "On the clipboard")
|
||||||
|
|
||||||
|
set -- --action=open=Open
|
||||||
|
command -v satty >/dev/null 2>&1 && set -- "$@" --action=edit=Edit
|
||||||
|
[ "$mode" = copy ] && set -- "$@" --action=save=Save
|
||||||
|
|
||||||
|
# notify-send waits for the notification to close and prints the action
|
||||||
|
# that was chosen, so run it in the background and act on the answer.
|
||||||
|
(
|
||||||
|
choice=$(notify-send -a Screenshot -i "$file" -h "string:image-path:$file" \
|
||||||
|
"$@" "$title" "$body") || exit 0
|
||||||
|
case "$choice" in
|
||||||
|
open) xdg-open "$file" ;;
|
||||||
|
edit) satty --filename "$file" --output-filename "$dir/edited_$name" --copy-command wl-copy ;;
|
||||||
|
save) mkdir -p "$dir" && mv "$file" "$dir/$name" \
|
||||||
|
&& notify-send -a Screenshot -i "$dir/$name" -h "string:image-path:$dir/$name" \
|
||||||
|
"Screenshot saved" "${dir#"$HOME"/}/$name" ;;
|
||||||
|
esac
|
||||||
|
) >/dev/null 2>&1 &
|
||||||
@@ -185,7 +185,14 @@ Item {
|
|||||||
id: inline
|
id: inline
|
||||||
x: 1
|
x: 1
|
||||||
y: 1
|
y: 1
|
||||||
source: root.notif?.image || ""
|
// A path given as an image hint (notify-send -h image-path:…)
|
||||||
|
// comes back routed through the icon provider, which treats
|
||||||
|
// it as an icon name and returns a placeholder. Load the file.
|
||||||
|
source: {
|
||||||
|
const img = root.notif?.image || "";
|
||||||
|
if (img.startsWith("image://icon//")) return "file://" + img.slice("image://icon/".length);
|
||||||
|
return img.startsWith("/") ? "file://" + img : img;
|
||||||
|
}
|
||||||
sourceSize.height: 90
|
sourceSize.height: 90
|
||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
asynchronous: true
|
asynchronous: true
|
||||||
|
|||||||
Reference in new issue
Block a user