grimshot (4240B)
1 #!/bin/sh 2 3 ## Grimshot: a helper for screenshots within sway 4 ## Requirements: 5 ## - `grim`: screenshot utility for wayland 6 ## - `slurp`: to select an area 7 ## - `swaymsg`: to read properties of current window 8 ## - `wl-copy`: clipboard utility 9 ## - `jq`: json utility to parse swaymsg output 10 ## - `notify-send`: to show notifications 11 ## Those are needed to be installed, if unsure, run `grimshot check` 12 ## 13 ## See `man 1 grimshot` or `grimshot usage` for further details. 14 15 getTargetDirectory() { 16 test -f ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs && \ 17 . ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs 18 19 echo ${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}} 20 } 21 22 if [ "$1" = "--notify" ]; then 23 NOTIFY=yes 24 shift 1 25 else 26 NOTIFY=no 27 fi 28 29 ACTION=${1:-usage} 30 SUBJECT=${2:-screen} 31 FILE=${3:-$(getTargetDirectory)/$(date -Ins).png} 32 33 if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then 34 echo "Usage:" 35 echo " grimshot [--notify] (copy|save) [active|screen|output|area|window] [FILE|-]" 36 echo " grimshot check" 37 echo " grimshot usage" 38 echo "" 39 echo "Commands:" 40 echo " copy: Copy the screenshot data into the clipboard." 41 echo " save: Save the screenshot to a regular file or '-' to pipe to STDOUT." 42 echo " check: Verify if required tools are installed and exit." 43 echo " usage: Show this message and exit." 44 echo "" 45 echo "Targets:" 46 echo " active: Currently active window." 47 echo " screen: All visible outputs." 48 echo " output: Currently active output." 49 echo " area: Manually select a region." 50 echo " window: Manually select a window." 51 exit 52 fi 53 54 notify() { 55 notify-send -t 3000 -a grimshot "$@" 56 } 57 notifyOk() { 58 [ "$NOTIFY" = "no" ] && return 59 60 TITLE=${2:-"Screenshot"} 61 MESSAGE=${1:-"OK"} 62 notify "$TITLE" "$MESSAGE" 63 } 64 notifyError() { 65 if [ $NOTIFY = "yes" ]; then 66 TITLE=${2:-"Screenshot"} 67 MESSAGE=${1:-"Error taking screenshot with grim"} 68 notify -u critical "$TITLE" "$MESSAGE" 69 else 70 echo $1 71 fi 72 } 73 74 die() { 75 MSG=${1:-Bye} 76 notifyError "Error: $MSG" 77 exit 2 78 } 79 80 check() { 81 COMMAND=$1 82 if command -v "$COMMAND" > /dev/null 2>&1; then 83 RESULT="OK" 84 else 85 RESULT="NOT FOUND" 86 fi 87 echo " $COMMAND: $RESULT" 88 } 89 90 takeScreenshot() { 91 FILE=$1 92 GEOM=$2 93 OUTPUT=$3 94 95 DIR="$(dirname "$FILE")" 96 mkdir -p "$DIR" 97 if [ ! -z "$OUTPUT" ]; then 98 grim -o "$OUTPUT" "$FILE" || die "Unable to invoke grim" 99 elif [ -z "$GEOM" ]; then 100 grim "$FILE" || die "Unable to invoke grim" 101 else 102 grim -g "$GEOM" "$FILE" || die "Unable to invoke grim" 103 fi 104 } 105 106 if [ "$ACTION" = "check" ] ; then 107 echo "Checking if required tools are installed. If something is missing, install it to your system and make it available in PATH..." 108 check grim 109 check slurp 110 check swaymsg 111 check wl-copy 112 check jq 113 check notify-send 114 exit 115 elif [ "$SUBJECT" = "area" ] ; then 116 GEOM=$(slurp -d) 117 # Check if user exited slurp without selecting the area 118 if [ -z "$GEOM" ]; then 119 exit 1 120 fi 121 WHAT="Area" 122 elif [ "$SUBJECT" = "active" ] ; then 123 FOCUSED=$(swaymsg -t get_tree | jq -r 'recurse(.nodes[]?, .floating_nodes[]?) | select(.focused)') 124 GEOM=$(echo "$FOCUSED" | jq -r '.rect | "\(.x),\(.y) \(.width)x\(.height)"') 125 APP_ID=$(echo "$FOCUSED" | jq -r '.app_id') 126 WHAT="$APP_ID window" 127 elif [ "$SUBJECT" = "screen" ] ; then 128 GEOM="" 129 WHAT="Screen" 130 elif [ "$SUBJECT" = "output" ] ; then 131 GEOM="" 132 OUTPUT=$(swaymsg -t get_outputs | jq -r '.[] | select(.focused)' | jq -r '.name') 133 WHAT="$OUTPUT" 134 elif [ "$SUBJECT" = "window" ] ; then 135 GEOM=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"' | slurp) 136 # Check if user exited slurp without selecting the area 137 if [ -z "$GEOM" ]; then 138 exit 1 139 fi 140 WHAT="Window" 141 else 142 die "Unknown subject to take a screen shot from" "$SUBJECT" 143 fi 144 145 if [ "$ACTION" = "copy" ] ; then 146 takeScreenshot - "$GEOM" "$OUTPUT" | wl-copy --type image/png || die "Clipboard error" 147 notifyOk "$WHAT copied to buffer" 148 else 149 if takeScreenshot "$FILE" "$GEOM" "$OUTPUT"; then 150 TITLE="Screenshot of $SUBJECT" 151 MESSAGE=$(basename "$FILE") 152 notifyOk "$MESSAGE" "$TITLE" 153 echo $FILE 154 else 155 notifyError "Error taking screenshot with grim" 156 fi 157 fi