diff --git a/home/.config/hypr/hyprland.conf b/home/.config/hypr/hyprland.conf index f756b19..135eec2 100644 --- a/home/.config/hypr/hyprland.conf +++ b/home/.config/hypr/hyprland.conf @@ -135,6 +135,9 @@ windowrulev2 = float, class:^(firefox)$,title:^(Extension: \(uBlock Origin\)) ### KEY BINDINGS ### #################### +$SCREENSHOT_FORMAT = "${XDG_SCREENSHOTS_DIR:-$HOME/Pictures/Screenshots}/Screenshot_$(date +%Y-%m-%d_%H-%M-%S).png" +$SCREENSHOT_DELAY = 2000 + $MOUSE_LMB = mouse:272 $MOUSE_RMB = mouse:273 $MOUSE_MMB = mouse:274 @@ -178,13 +181,16 @@ binde = SUPER, Left, exec, brightness -d 5% -n binde = , XF86MonBrightnessUp, exec, brightness -i 5% -n binde = , XF86MonBrightnessDown, exec, brightness -d 5% -n -# Screenshots -bind = ,Print, exec, grim -g "$(slurp)" - | wl-copy --type image/png && notify-send "Screenshot" "Screenshot saved to clipboard" -bind = SUPER, Print, exec, grim -g "$(slurp)" - | swappy -f - -o - | wl-copy --type image/png -bind = CTRL, Print, exec, echo "" | wofi --prompt "Set delay (ms)" --show dmenu | xargs -I _ sleep _e-3 && grim -g "$(slurp)" - | wl-copy --type image/png -bind = SUPER_CTRL, Print, exec, echo "" | wofi --prompt "Set delay (ms)" --show dmenu | xargs -I _ sleep _e-3 && grim -g "$(slurp)" - | swappy -f - -o - | wl-copy --type image/png -bind = SHIFT, Print, exec, wl-copy --type image/png "$(hyprpicker)" && notify-send 'Picked color' "$(wl-paste) (saved to clipboard)" -bind = SUPER_SHIFT_CTRL, Print, exec, grim +# Screenshots (with custom screenshot script) +bind = ALT, Print, exec, wl-copy --type image/png "$(hyprpicker)" && notify-send 'Picked color' "$(wl-paste) (saved to clipboard)" +bind = , Print, exec, screenshot --notify --copy --target area +bind = SUPER, Print, exec, screenshot --notify --copy --target area --edit +bind = SHIFT, Print, exec, screenshot --notify --save $SCREENSHOT_FORMAT --target area +bind = CTRL, Print, exec, screenshot --notify --copy --target area --delay $SCREENSHOT_DELAY +bind = SUPER_SHIFT, Print, exec, screenshot --notify --save $SCREENSHOT_FORMAT --target area --edit +bind = SUPER_CTRL, Print, exec, screenshot --notify --copy --target area --delay $SCREENSHOT_DELAY --edit +bind = SUPER_SHIFT_CTRL, Print, exec, screenshot --notify --save $SCREENSHOT_FORMAT --target area --delay $SCREENSHOT_DELAY --edit + # Active window bind = SUPER, W, killactive, diff --git a/home/.local/bin/scripts/gui/hyprland/screenshot b/home/.local/bin/scripts/gui/hyprland/screenshot new file mode 100755 index 0000000..54b357e --- /dev/null +++ b/home/.local/bin/scripts/gui/hyprland/screenshot @@ -0,0 +1,226 @@ +#!/bin/bash + +# Inspired by grimblast (https://github.com/hyprwm/contrib/blob/main/grimblast/grimblast) + +# Requirements: +# - `grim`: screenshot utility for wayland +# - `slurp`: to select an area +# - `hyprctl`: to read properties of current window +# - `wl-copy`: clipboard utility +# - `jq`: json utility to parse hyprctl output +# - `notify-send`: to show notifications +# - `swappy`: for editing the screenshots (only required for --edit) + +# Helper functions + +die() { + MSG="${1}" + ERR_CODE="${2:-1}" + URGENCY="${3:-critical}" + + >&2 echo "$MSG" + if [ "$NOTIFY" = "yes" ]; then + notify-send -a screenshot -u "$URGENCY" "Error ($ERR_CODE)" "$MSG" + fi + exit "$ERR_CODE" +} + +# Argument parsing + +SAVE_METHOD= +SAVE_FILE= +TARGET= +NOTIFY=no +CURSOR=no +EDIT=no +DELAY=0 + +while [ "$1" ]; do + case "$1" in + -h | --help) + >&2 cat << EOF +screenshot taking utility script, allowing for easy all-in-one solution for +controlling how a screenshot should be taken. + +Methods (one is required): + --copy: Copy the screenshot data into the clipboard + --save [FILE]: Save the screenshot data into a file + --copysave [FILE]: Both save to clipboard and to file +General options: + --notify: Send a notification that the screenshot was saved + --cursor: Capture cursor in the screenshot + --edit: Once the screenshot is taken, edit it first with swappy + --delay [MILISECONDS]: Wait for given time until the screenshot is taken + --target [TARGET]: (REQUIRED) What should be captured +Variables: + FILE: A path to a .png image file for output, or '-' to pipe to STDOUT + MILISECONDS: Number of miliseconds; Must be a whole, non-negative number! + TARGET: Area on screen; can be one of: + - activewin: Currently active window + - window: Manually select a window + - activemon: Currently active monitor (output) + - monitor: Manually select a monitor + - all: Everything (all visible monitors/outputs) + - area: Manually select a region +EOF + exit 0 + ;; + --notify) + NOTIFY=yes + shift + ;; + --cursor) + CURSOR=yes + shift + ;; + --edit) + EDIT=yes + shift + ;; + --target) + if [ -z "$TARGET" ]; then + case "$2" in + activewin|window|activemon|monitor|all|area) + TARGET="$2" + shift 2 + ;; + *) + die "Invalid target (see TARGET variable in --help)" + ;; + esac + else + die "Only one target can be passed." + fi + ;; + --delay) + case "$2" in + ''|*[!0-9]*) + die "Argument after --delay must be an amount of MILISECONDS" + ;; + *) + DELAY="$2" + shift 2 + ;; + esac + ;; + + --copy) + if [ -z "$SAVE_METHOD" ]; then + SAVE_METHOD="copy" + shift + else + die "Only one method can be passed." + fi + ;; + --save) + if [ -z "$SAVE_METHOD" ]; then + SAVE_METHOD="save" + SAVE_FILE="$2" + shift 2 + else + die "Only one method can be passed." + fi + ;; + --copysave) + if [ -z "$SAVE_METHOD" ]; then + SAVE_METHOD="copysave" + SAVE_FILE="$2" + shift 2 + else + die "Only one method can be passed." + fi + ;; + *) + die "Unrecognized argument: $1" + ;; + esac +done + +# Screenshot functions + +takeScreenshot() { + FILE="$1" + GEOM="$2" + + ARGS=() + [ "$CURSOR" = "yes" ] && ARGS+=("-c") + [ -n "$GEOM" ] && ARGS+=("-g" "$GEOM") + ARGS+=("$FILE") + + sleep "$DELAY"e-3 + grim "${ARGS[@]}" || die "Unable to invoke grim" +} + +takeEditedScreenshot() { + FILE="$1" + GEOM="$2" + + if [ "$EDIT" = "yes" ]; then + takeScreenshot - "$GEOM" | swappy -f - -o "$FILE" || die "Unable to invoke swappy" + else + takeScreenshot "$FILE" "$GEOM" + fi +} + + +# Obtain the geometry for screenshot to be taken at + +if [ "$TARGET" = "area" ]; then + GEOM="$(slurp -d)" + if [ -z "$GEOM" ]; then + die "No area selected" 2 normal + fi + WHAT="Area" +elif [ "$TARGET" = "all" ]; then + GEOM="" + WHAT="Screen" +elif [ "$TARGET" = "activewin" ]; then + FOCUSED="$(hyprctl activewindow -j)" + GEOM="$(echo "$FOCUSED" | jq -r '"\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"')" + APP_ID="$(echo "$FOCUSED" | jq -r '.class')" + WHAT="$APP_ID window" +elif [ "$TARGET" = "window" ]; then + WORKSPACES="$(hyprctl monitors -j | jq -r 'map(.activeWorkspace.id)')" + WINDOWS="$(hyprctl clients -j | jq -r --argjson workspaces "$WORKSPACES" 'map(select([.workspace.id] | inside($workspaces)))' )" + GEOM=$(echo "$WINDOWS" | jq -r '.[] | "\(.at[0]),\(.at[1]) \(.size[0])x\(.size[1])"' | slurp -r) + if [ -z "$GEOM" ]; then + die "No window selected" 2 normal + fi + WHAT="Window" +elif [ "$TARGET" = "activemon" ]; then + ACTIVEMON="$(hyprctl monitors -j | jq -r '.[] | select(.focused == true)')" + GEOM="$(echo "$ACTIVEMON" | jq -r '"\(.x),\(.y) \(.width)x\(.height)"')" + WHAT="$(echo "$ACTIVEMON" | jq -r '.name')" +elif [ "$TARGET" = "monitor" ]; then + GEOM="$(slurp -o)" + if [ -z "$GEOM" ]; then + die "No monitor selected" 2 normal + fi + WHAT="Monitor" +else + if [ -z "$TARGET" ]; then + die "No target specified!" + else + die "Unknown target: $SAVE_METHOD" + fi +fi + +# Invoke grim and capture the screenshot + +if [ "$SAVE_METHOD" = "save" ]; then + takeEditedScreenshot "$SAVE_FILE" "$GEOM" + notify-send -a screenshot "Success" "$WHAT screenshot saved" -i "$(realpath "$SAVE_FILE")" +elif [ "$SAVE_METHOD" = "copy" ]; then + TEMP_FILE="$(mktemp --suffix=.png)" + takeEditedScreenshot "-" "$GEOM" | tee "$TEMP_FILE" | wl-copy --type image/png || die "Clipboard error" + notify-send -a screenshot "Success" "$WHAT screenshot copied" -i "$(realpath "$TEMP_FILE")" && rm "$TEMP_FILE" +elif [ "$SAVE_METHOD" = "copysave" ]; then + takeEditedScreenshot "-" "$GEOM" | tee "$SAVE_FILE" | wl-copy --type image/png || die "Clipboard error" + notify-send -a screenshot "Success" "$WHAT screenshot copied and saved" -i "$(realpath "$SAVE_FILE")" +else + if [ -z "$SAVE_METHOD" ]; then + die "No save method specified!" + else + die "Unknown save method: $SAVE_METHOD" + fi +fi