feat(scripts): add screenshot.sh
This commit is contained in:
parent
f5d6149d03
commit
e158449bf3
1 changed files with 178 additions and 0 deletions
178
scripts/screenshot.sh
Executable file
178
scripts/screenshot.sh
Executable file
|
|
@ -0,0 +1,178 @@
|
|||
#!/usr/bin/env bash
|
||||
# Take screenshots of areas, windows, or screens, interactively or immediately.
|
||||
# Usage: screenshot [-t area|window|screen|all] [-a copy|save] [-i]
|
||||
|
||||
set -u
|
||||
|
||||
TARGET='area'
|
||||
ACTION='copy'
|
||||
INTERACTIVE='false'
|
||||
|
||||
DATE_STR="$( date '+%F-%H-%M-%S' )"
|
||||
SAVE_DIR="${HOME}/Nextcloud/Afbeeldingen/Screenshots"
|
||||
|
||||
panic () {
|
||||
>&2 echo 'Usage: screenshot [-t area|window|screen|all] [-a copy|save] [-i]'
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get options
|
||||
while getopts ':t:a:i' option; do
|
||||
case "${option}" in
|
||||
t)
|
||||
if [[ "${OPTARG}" =~ ^(area|window|screen|all)$ ]]; then
|
||||
TARGET="${OPTARG}"
|
||||
else
|
||||
>&2 printf "Error: Invalid target '%s'.\n" "${OPTARG}"
|
||||
panic
|
||||
fi
|
||||
;;
|
||||
a)
|
||||
if [[ "${OPTARG}" =~ ^(copy|save)$ ]]; then
|
||||
ACTION="${OPTARG}"
|
||||
else
|
||||
>&2 printf "Error: Invalid action '%s'.\n" "${OPTARG}"
|
||||
fi
|
||||
;;
|
||||
i)
|
||||
INTERACTIVE='true'
|
||||
;;
|
||||
*)
|
||||
panic
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ "${ACTION}" == 'save' ]]; then
|
||||
SAVE_PATH="${SAVE_DIR}/${DATE_STR}.png"
|
||||
else
|
||||
SAVE_PATH="/tmp/screenshot_${DATE_STR}.png"
|
||||
fi
|
||||
|
||||
mkdir -p "${SAVE_DIR}"
|
||||
|
||||
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]] && command -v hyprctl >/dev/null 2>&1 ; then
|
||||
WM='hyprland'
|
||||
else
|
||||
>&2 echo 'Error: Unsupported or undetected Window Manager.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for tool in grim slurp wl-copy jq; do
|
||||
if ! command -v "${tool}" >/dev/null 2>&1; then
|
||||
>&2 echo "Error: Required dependency '${tool}' is missing."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
# Helper functions
|
||||
|
||||
target_area () {
|
||||
slurp || true
|
||||
}
|
||||
|
||||
hyprland_target_window () {
|
||||
hyprctl activewindow -j \
|
||||
| jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"'
|
||||
}
|
||||
|
||||
hyprland_target_window_interactive () {
|
||||
local ws_id
|
||||
ws_id="$( hyprctl activeworkspace -j | jq -r '.id' )"
|
||||
hyprctl clients -j \
|
||||
| jq -r --arg ws "${ws_id}" '.[] | select(.workspace.id == ($ws | tonumber)) | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' \
|
||||
| slurp -d \
|
||||
|| true
|
||||
}
|
||||
|
||||
hyprland_target_screen () {
|
||||
local ws_id
|
||||
ws_id="$(hyprctl activeworkspace -j | jq -r '.id')"
|
||||
hyprctl monitors -j \
|
||||
| jq -r --arg ws "${ws_id}" '.[] | select(.activeWorkspace.id == ($ws | tonumber)) | .name'
|
||||
}
|
||||
|
||||
hyprland_target_screen_interactive () {
|
||||
hyprctl monitors -j \
|
||||
| jq -r '.[] | "\(.x),\(.y) \(.width)x\(.height)"' \
|
||||
| slurp -d \
|
||||
|| true
|
||||
}
|
||||
|
||||
# Capturing the screenshot
|
||||
|
||||
GEOMETRY=''
|
||||
OUTPUT=''
|
||||
|
||||
fetch_target_data () {
|
||||
if [[ "${TARGET}" == 'area' ]]; then
|
||||
GEOMETRY="$( target_area )"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local route_key="${WM}_${TARGET}_${INTERACTIVE}"
|
||||
|
||||
case "${route_key}" in
|
||||
'hyprland_window_false')
|
||||
GEOMETRY="$( hyprland_target_window )"
|
||||
;;
|
||||
'hyprland_window_true')
|
||||
GEOMETRY="$( hyprland_target_window_interactive )"
|
||||
;;
|
||||
'hyprland_screen_false')
|
||||
OUTPUT="$( hyprland_target_screen )"
|
||||
;;
|
||||
'hyprland_screen_true')
|
||||
GEOMETRY="$( hyprland_target_screen_interactive )"
|
||||
;;
|
||||
|
||||
*)
|
||||
>&2 echo 'Error: Unmapped execution route.'
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
if [[ "${TARGET}" != 'all' ]]; then
|
||||
fetch_target_data
|
||||
fi
|
||||
|
||||
# Detect cancellation, Escape pressed during slurp results in empty string.
|
||||
if [[ "${INTERACTIVE}" == 'true' || "${TARGET}" == 'area' ]]; then
|
||||
if [[ -z "${GEOMETRY}" && -z "${OUTPUT}" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Take the screenshot
|
||||
if [[ -n "${GEOMETRY}" ]]; then
|
||||
grim -g "${GEOMETRY}" "${SAVE_PATH}"
|
||||
elif [[ -n "${OUTPUT}" ]]; then
|
||||
grim -o "${OUTPUT}" "${SAVE_PATH}"
|
||||
else
|
||||
grim "${SAVE_PATH}"
|
||||
fi
|
||||
|
||||
# Route to clipboard
|
||||
if [[ "${ACTION}" == 'copy' ]]; then
|
||||
wl-copy < "${SAVE_PATH}"
|
||||
fi
|
||||
|
||||
# Notifications
|
||||
if [[ "${TARGET}" != 'area' || "${INTERACTIVE}" == 'true' ]]; then
|
||||
NOTIF_ICON="${SAVE_PATH}"
|
||||
|
||||
if command -v magick >/dev/null 2>&1; then
|
||||
THUMB_PATH="/tmp/thumb_${DATE_STR}.png"
|
||||
if magick "${SAVE_PATH}" -thumbnail '320x320^' -gravity center -extent 320x320 "${THUMB_PATH}" >/dev/null 2>&1; then
|
||||
NOTIF_ICON="${THUMB_PATH}"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ "${ACTION}" == 'copy' ]]; then
|
||||
notify-send -a 'Grim' -i "${NOTIF_ICON}" 'Screenshot Captured' 'Copied to clipboard'
|
||||
else
|
||||
notify-send -a 'Grim' -i "${NOTIF_ICON}" 'Screenshot Captured' "Saved to ${SAVE_PATH}"
|
||||
fi
|
||||
fi
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue