Dotfiles/desktopenvs/hyprland/scripts/wallpaper-picker

138 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
VERBOSE=0
DIR=""
while [[ $# -gt 0 ]]; do
case "$1" in
-v|--verbose) VERBOSE=1 ;;
*) DIR="$1" ;;
esac
shift
done
DIR="${DIR:-$HOME/Pictures}"
LOG=""
(( VERBOSE )) && LOG="/tmp/wallpaper-picker-$$.log"
IMAGES=()
while IFS= read -r -d '' f; do
IMAGES+=("$f")
done < <(find "$DIR" -maxdepth 1 -type f \
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' \
-o -iname '*.webp' -o -iname '*.bmp' -o -iname '*.gif' \
-o -iname '*.avif' -o -iname '*.tiff' \) \
-print0 | sort -z)
[[ ${#IMAGES[@]} -eq 0 ]] && { echo "No images found in $DIR"; exit 1; }
INDEX=0
CURRENT_WALLPAPER=""
vlog() { (( VERBOSE )) && printf '%s\n' "$*" >> "$LOG"; }
icat() { kitty +kitten icat --stdin=no --silent --transfer-mode=memory "$@" 2>/dev/null; }
clear_images() { icat --clear; }
draw() {
local cols rows
cols=$(tput cols); rows=$(tput lines)
local gap=2
local side_w=$(( cols * 18 / 100 ))
local center_w=$(( cols - 2 * (side_w + gap) ))
local center_x=$(( side_w + gap ))
local next_x=$(( center_x + center_w + gap ))
local img_h=$(( rows - 3 ))
local n=${#IMAGES[@]}
local prev=$(( (INDEX - 1 + n) % n ))
local next=$(( (INDEX + 1) % n ))
printf '\033[2J\033[H'
clear_images
icat --place "${side_w}x${img_h}@0x0" "${IMAGES[$prev]}"
icat --place "${center_w}x${img_h}@${center_x}x0" "${IMAGES[$INDEX]}"
icat --place "${side_w}x${img_h}@${next_x}x0" "${IMAGES[$next]}"
tput cup $(( rows - 2 )) 0
printf ' [%d/%d] %s\n' $(( INDEX + 1 )) "$n" "$(basename "${IMAGES[$INDEX]}")"
local hints=' h/←: prev l/→: next Enter: set wallpaper q: quit'
(( VERBOSE )) && hints+=" [log: $LOG]"
printf '%s' "$hints"
}
set_wallpaper() {
local path="$1" prev="$CURRENT_WALLPAPER"
local out rc
vlog "=== set_wallpaper: $path ==="
out=$(hyprctl hyprpaper preload "$path" 2>&1); rc=$?
vlog "preload exit=$rc out=$out"
# Don't bail on preload failure — image may already be preloaded
local monitors_out ok=0
monitors_out=$(hyprctl monitors 2>&1)
vlog "monitors: $monitors_out"
while IFS= read -r mon; do
out=$(hyprctl hyprpaper wallpaper "$mon,$path" 2>&1); rc=$?
vlog "wallpaper $mon exit=$rc out=$out"
(( rc == 0 )) && ok=1
done < <(printf '%s\n' "$monitors_out" | awk '/^Monitor /{print $2}')
if (( ok == 0 )); then
vlog "FAILED: no monitor set"
return 1
fi
CURRENT_WALLPAPER="$path"
if [[ -n "$prev" && "$prev" != "$path" ]]; then
out=$(hyprctl hyprpaper unload "$prev" 2>&1); rc=$?
vlog "unload prev exit=$rc out=$out"
fi
return 0
}
read_key() {
local key
IFS= read -rsn1 key
if [[ $key == $'\x1b' ]]; then
local rest
IFS= read -rsn2 -t 0.1 rest
key+="$rest"
fi
printf '%s' "$key"
}
old_stty=$(stty -g)
trap 'stty "$old_stty"; clear_images; tput cnorm; printf "\033[2J\033[H"' EXIT
stty -echo -icanon -icrnl min 1 time 0
tput civis
draw
while true; do
key=$(read_key)
case "$key" in
h|$'\x1b[D')
INDEX=$(( (INDEX - 1 + ${#IMAGES[@]}) % ${#IMAGES[@]} ))
draw ;;
l|$'\x1b[C')
INDEX=$(( (INDEX + 1) % ${#IMAGES[@]} ))
draw ;;
$'\r'|$'\n')
if set_wallpaper "${IMAGES[$INDEX]}"; then
tput cup $(( $(tput lines) - 1 )) 0
printf ' Wallpaper set: %s' "$(basename "${IMAGES[$INDEX]}")"
else
tput cup $(( $(tput lines) - 1 )) 0
printf ' Failed — is hyprpaper running?'
(( VERBOSE )) && printf ' [see %s]' "$LOG"
fi ;;
q|Q) break ;;
esac
done