commit 2d4450846a8349149e717cc033645f15560894fe
parent 8ad6ea9e81711c1523c7dbfd5bd911f24991eaf8
Author: Chris Bracken <chris@bracken.jp>
Date: Sat, 24 Jul 2021 19:18:57 -0700
Sway: use grimshot for screenshots
`grim` is a lightweight tool for capturing screenshots on Wayland.
`grimshot` is a Bourne shell wrapper that works well with Sway.
Diffstat:
2 files changed, 160 insertions(+), 1 deletion(-)
diff --git a/.config/sway/config b/.config/sway/config
@@ -115,7 +115,12 @@ bindsym $mod+d exec $menu
floating_modifier $mod normal
# Capture a screenshot.
-bindsym $mod+Shift+s exec flameshot gui
+set $grimshot ~/.config/sway/grimshot
+set $screenshots ~/Pictures/Screenshots
+bindsym $mod+Shift+s exec $grimshot --notify save screen \
+ $screenshots/Screenshot_$(date +"%Y-%m-%d_%H:%M:%S.png")
+bindsym $mod+Control+Shift+s exec $grimshot --notify save area \
+ $screenshots/Screenshot_$(date +"%Y-%m-%d_%H.%M.%S.png")
# Reload the configuration file.
bindsym $mod+Shift+c reload
diff --git a/.config/sway/grimshot b/.config/sway/grimshot
@@ -0,0 +1,154 @@
+#!/bin/sh
+
+## 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:-~/.config}/user-dirs.dirs && \
+ . ${XDG_CONFIG_HOME:-~/.config}/user-dirs.dirs
+
+ echo ${XDG_SCREENSHOTS_DIR:-${XDG_PICTURES_DIR:-$HOME}}
+}
+
+if [ "$1" = "--notify" ]; then
+ NOTIFY=yes
+ shift 1
+else
+ NOTIFY=no
+fi
+
+ACTION=${1:-usage}
+SUBJECT=${2:-screen}
+FILE=${3:-$(getTargetDirectory)/$(date -Ins).png}
+
+if [ "$ACTION" != "save" ] && [ "$ACTION" != "copy" ] && [ "$ACTION" != "check" ]; then
+ echo "Usage:"
+ echo " grimshot [--notify] (copy|save) [active|screen|output|area|window] [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 " 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."
+ exit
+fi
+
+notify() {
+ notify-send -t 3000 -a grimshot "$@"
+}
+notifyOk() {
+ [ "$NOTIFY" = "no" ] && return
+
+ TITLE=${2:-"Screenshot"}
+ MESSAGE=${1:-"OK"}
+ notify "$TITLE" "$MESSAGE"
+}
+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 [ ! -z "$OUTPUT" ]; then
+ grim -o "$OUTPUT" "$FILE" || die "Unable to invoke grim"
+ elif [ -z "$GEOM" ]; then
+ grim "$FILE" || die "Unable to invoke grim"
+ else
+ grim -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)
+ # Check if user exited slurp without selecting the area
+ if [ -z "$GEOM" ]; then
+ exit 1
+ fi
+ WHAT="Window"
+else
+ die "Unknown subject to take a screen shot from" "$SUBJECT"
+fi
+
+if [ "$ACTION" = "copy" ] ; then
+ takeScreenshot - "$GEOM" "$OUTPUT" | wl-copy --type image/png || die "Clipboard error"
+ notifyOk "$WHAT copied to buffer"
+else
+ if takeScreenshot "$FILE" "$GEOM" "$OUTPUT"; then
+ TITLE="Screenshot of $SUBJECT"
+ MESSAGE=$(basename "$FILE")
+ notifyOk "$MESSAGE" "$TITLE"
+ echo $FILE
+ else
+ notifyError "Error taking screenshot with grim"
+ fi
+fi