From cee074f533be9dc3e816ab4c6111d6aa5081806a Mon Sep 17 00:00:00 2001 From: Kleidi Bujari Date: Sun, 1 Sep 2024 20:57:06 -0400 Subject: . --- grimshot | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) create mode 100755 grimshot (limited to 'grimshot') diff --git a/grimshot b/grimshot new file mode 100755 index 0000000..8f8ca92 --- /dev/null +++ b/grimshot @@ -0,0 +1,202 @@ +#!/bin/sh + +## Copied from: https://github.com/OctopusET/sway-contrib/blob/2d6e5a9dfba137251547f99befc330ef93d70551/grimshot + +## Grimshot: a helper for screenshots within sway +## Requirements: +## - `grim`: screenshot utility for wayland +## - `slurp`: to select an area +## - `swaymsg`: to read properties of current window +## - `wl-copy`: clipboard utility +## - `jq`: json utility to parse swaymsg output +## - `notify-send`: to show notifications +## Those are needed to be installed, if unsure, run `grimshot check` +## +## See `man 1 grimshot` or `grimshot usage` for further details. + +getTargetDirectory() { + test -f "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" && \ + . "${XDG_CONFIG_HOME:-$HOME/.config}/user-dirs.dirs" + + echo "${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}}" +} + +NOTIFY=no +CURSOR= +WAIT=no + +while [ $# -gt 0 ]; do + key="$1" + + case $key in + -n|--notify) + NOTIFY=yes + shift # past argument + ;; + -c|--cursor) + CURSOR=yes + shift # past argument + ;; + -w|--wait) + shift + WAIT="$1" + if echo "$WAIT" | grep "[^0-9]" -q; then + echo "invalid value for wait '$WAIT'" >&2 + exit 3 + fi + shift + ;; + *) # unknown option + break # done with parsing --flags + ;; + esac +done + +ACTION=${1:-usage} +SUBJECT=${2:-screen} +FILE=${3:-$(getTargetDirectory)/$(date -Ins).png} + +if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "savecopy" ] && [ "$ACTION" != "check" ]; then + echo "Usage:" + echo " grimshot [--notify] [--cursor] [--wait N] (copy|save) [active|screen|output|area|window|anything] [FILE|-]" + echo " grimshot check" + echo " grimshot usage" + echo "" + echo "Commands:" + echo " copy: Copy the screenshot data into the clipboard." + echo " save: Save the screenshot to a regular file or '-' to pipe to STDOUT." + echo " savecopy: Save the screenshot to a regular file and copy the data into the clipboard." + echo " check: Verify if required tools are installed and exit." + echo " usage: Show this message and exit." + echo "" + echo "Targets:" + echo " active: Currently active window." + echo " screen: All visible outputs." + echo " output: Currently active output." + echo " area: Manually select a region." + echo " window: Manually select a window." + echo " anything: Manually select an area, window, or output." + exit +fi + +notify() { + notify-send -t 3000 -a grimshot "$@" +} +notifyOk() { + [ "$NOTIFY" = "no" ] && return + + TITLE=${2:-"Screenshot"} + MESSAGE=${1:-"OK"} + + if [ "$ACTION" = "save" ] || [ "$ACTION" = "savecopy" ]; then + notify "$TITLE" "$MESSAGE" -i "$FILE" + else + notify "$TITLE" "$MESSAGE" + fi +} +notifyError() { + if [ $NOTIFY = "yes" ]; then + TITLE=${2:-"Screenshot"} + MESSAGE=${1:-"Error taking screenshot with grim"} + notify -u critical "$TITLE" "$MESSAGE" + else + echo "$1" + fi +} + +die() { + MSG=${1:-Bye} + notifyError "Error: $MSG" + exit 2 +} + +check() { + COMMAND=$1 + if command -v "$COMMAND" > /dev/null 2>&1; then + RESULT="OK" + else + RESULT="NOT FOUND" + fi + echo " $COMMAND: $RESULT" +} + +takeScreenshot() { + FILE=$1 + GEOM=$2 + OUTPUT=$3 + if [ -n "$OUTPUT" ]; then + grim ${CURSOR:+-c} -o "$OUTPUT" "$FILE" || die "Unable to invoke grim" + elif [ -z "$GEOM" ]; then + grim ${CURSOR:+-c} "$FILE" || die "Unable to invoke grim" + else + grim ${CURSOR:+-c} -g "$GEOM" "$FILE" || die "Unable to invoke grim" + fi +} + +if [ "$ACTION" = "check" ] ; then + echo "Checking if required tools are installed. If something is missing, install it to your system and make it available in PATH..." + check grim + check slurp + check swaymsg + check wl-copy + check jq + check notify-send + exit +elif [ "$SUBJECT" = "area" ] ; then + GEOM=$(slurp -d) + # Check if user exited slurp without selecting the area + if [ -z "$GEOM" ]; then + exit 1 + fi + WHAT="Area" +elif [ "$SUBJECT" = "active" ] ; then + FOCUSED=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused)') + GEOM=$(echo "$FOCUSED" | jq -r '.rect | "\(.x),\(.y) \(.width)x\(.height)"') + APP_ID=$(echo "$FOCUSED" | jq -r '.app_id') + WHAT="$APP_ID window" +elif [ "$SUBJECT" = "screen" ] ; then + GEOM="" + WHAT="Screen" +elif [ "$SUBJECT" = "output" ] ; then + GEOM="" + OUTPUT=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused)' | jq -r '.name') + WHAT="$OUTPUT" +elif [ "$SUBJECT" = "window" ] ; then + GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp -r) + # Check if user exited slurp without selecting the area + if [ -z "$GEOM" ]; then + exit 1 + fi + WHAT="Window" +elif [ "$SUBJECT" = "anything" ] ; then + GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp -o) + # Check if user exited slurp without selecting the area + if [ -z "$GEOM" ]; then + exit + fi + WHAT="Selection" +else + die "Unknown subject to take a screen shot from" "$SUBJECT" +fi + +if [ "$WAIT" != "no" ]; then + sleep "$WAIT" +fi + +if [ "$ACTION" = "copy" ] ; then + takeScreenshot - "$GEOM" "$OUTPUT" | wl-copy --type image/png || die "Clipboard error" + notifyOk "$WHAT copied to clipboard" +else + if takeScreenshot "$FILE" "$GEOM" "$OUTPUT"; then + TITLE="Screenshot of $SUBJECT" + MESSAGE=$(basename "$FILE") + if [ "$ACTION" = "savecopy" ]; then + wl-copy --type image/png < "$FILE" || die "Clipboard error" + MESSAGE="$MESSAGE and clipboard" + fi + notifyOk "$MESSAGE" "$TITLE" + echo "$FILE" + else + notifyError "Error taking screenshot with grim" + fi +fi -- cgit 1.4.1