#!/bin/sh ## Grimshot: a helper for screenshots within sway ## Requirements: ## - `grim`: screenshot utility for wayland ## - `slurp`: to select an area ## - `wf-recorder`: screen-recording utility ## - `swaymsg`: to read properties of current window ## - `wl-copy`: clipboard utility ## - `jq`: json uliity to parse swaymsg output ## - `notify-send`: to show notifications ## - `mktemp`: to create a temporary file ## Those are needed to be installed, if unsure, run `grimshot check` ## ## Examples: ## `grimshot copy win` - to copy current window ## `grimshot save area` - to select area and save it to default file (Pictures/Grimshot-$datetime.png) ## `grimshot save screen ~/screenshot.png` - to save screenshot under ~/screenshot.png ## `grimshot | grimshot -h` - usage ## `grimshot check` - verify if tools are installed _slurp() { slurp -d -c '#4E437188' -w 3 } _silence_notifications() { once -k mako trap '{ once mako; }' EXIT } ACTION=${1:-usage} SUBJECT=${2:-screen} FILE=${3:-${HOME}/Pictures/screenshots/$(now).png} case "$ACTION" in usage | help | -h | --help) echo "Usage:" echo " grimshot copy|save|rec win|screen|area|output [FILE]" echo "Troubleshoot:" echo " grimshot check" exit ;; esac notify() { notify-send -i "${TMP:-${FILE}}" -t 3000 -a grimshot "$@" # notify-send -i "${TMP:-${FILE}}" -t 3000 "$@" } notifyOk() { TITLE=${2:-"Screenshot"} MESSAGE=${1:-"OK"} notify "$TITLE" "$MESSAGE" } notifyError() { TITLE=${2:-"Screenshot"} MESSAGE=${1:-"Error taking screenshot with grim"} TMP=/usr/share/icons/Adwaita/scalable/apps/applets-screenshooter-symbolic.svg notify -u critical "$TITLE" "$MESSAGE" } die() { MSG=${1:-Bye} notifyError "Error: $MSG" exit 2 } check() { COMMAND=$1 command -v "$COMMAND" >/dev/null 2>&1 if [ $? ]; then RESULT="OK" else RESULT="NOT FOUND" fi echo " $COMMAND: $RESULT" } takeScreenshot() { FILE=$1 GEOM=$2 OUTPUT=$3 if [ -n "$GEOM" ]; then grim -g "$GEOM" "$FILE" || die "Unable to invoke grim" elif [ -n "$OUTPUT" ]; then grim -o "$OUTPUT" "$FILE" || die "Unable to invoke grim" else grim "$FILE" || die "Unable to invoke grim" fi } recordScreen() { _silence_notifications FILE=$1 GEOM=$2 OUTPUT=$3 REC_OPTS="-d /dev/dri/renderD128" if [ -n "$GEOM" ]; then wf-recorder ${REC_OPTS} -g "${GEOM}" -f "$FILE" || die "Unable to invoke wf-recorder" elif [ -n "$OUTPUT" ]; then wf-recorder ${REC_OPTS} -o "${OUTPUT}" -f "$FILE" || die "Unable to invoke wf-recorder" else wf-recorder ${REC_OPTS} -f "$FILE" || die "Unable to invoke wf-recorder" 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 wf-recorder check swaymsg check swq check wl-copy check jq check notify-send check mktemp exit elif [ "$SUBJECT" = "area" ]; then GEOM=$(_slurp) [ -z "$GEOM" ] && die "Selection cancelled" WHAT="Area" elif [ "$SUBJECT" = "win" ]; 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="$(swq current output)" WHAT="output $OUTPUT" else die "Unknown subject to take a screen shot from" "$SUBJECT" fi if [ ! "$ACTION" = "copy" ]; then mkdir -p "$(dirname "${FILE}")" fi if [ "$ACTION" = "copy" ]; then TMP=$(mktemp) || die "Unable to create temp file: is mktemp installed?" takeScreenshot "$TMP" "$GEOM" "$OUTPUT" wl-copy --type image/png <"$TMP" || die "Clipboard error" notifyOk "$WHAT copied to clipboard" rm "$TMP" elif [ "$ACTION" = "save" ]; then takeScreenshot "$FILE" "$GEOM" "$OUTPUT" if [ $? ]; then TITLE="Screenshot of $SUBJECT" MESSAGE=$(basename "$FILE") wl-copy --type image/png <"$FILE" || die "Clipboard error" notifyOk "$MESSAGE" "$TITLE" else notifyError "Error taking screenshot with grim" fi elif [ "$ACTION" = "rec" ]; then echo "$FILE" | awk '/png$/{exit 0}' && FILE=$(xdg-user-dir VIDEOS)/grimshot/$(now).mp4 # create dir if not exists [ -d "$(dirname "$FILE")" ] || mkdir -p "$(dirname "$FILE")" recordScreen "$FILE" "$GEOM" "$OUTPUT" wl-copy "$FILE" || die "Clipboard error" if [ $? ]; then TITLE="Screen recording of $SUBJECT" MESSAGE=$(basename "$FILE") notifyOk "$MESSAGE" "$TITLE" else notifyError "Error recording screen with wf-recorder" fi else die "Unknown action" "$ACTION" fi