183 lines
5.8 KiB
Bash
Executable File
183 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Description:
|
|
# Change the desktop wallpaper and generate a blurred version.
|
|
#
|
|
# Requirs:
|
|
# - zenity (for file selection dialog)
|
|
# - imagemagick (for image processing)
|
|
# - swww (wallpaper daemon)
|
|
# - notify-send (for notifications)
|
|
# - change-colortheme (from scripts/change-colortheme)
|
|
# - flock (usually part of util-linux)
|
|
|
|
# Lock
|
|
|
|
exec {LOCK_FD}>/tmp/"$(basename "$0")".lock || {
|
|
echo "Failed to open lock file"
|
|
exit 1
|
|
}
|
|
|
|
flock -n "$LOCK_FD" || {
|
|
echo "Another instance is running. Exiting."
|
|
notify-send -a "change-wallpaper" "Error" "Another instance is running. Exiting."
|
|
exit 1
|
|
}
|
|
|
|
# Open a file selection dialog if no argument is provided
|
|
|
|
if [ -z "$1" ]; then
|
|
image=$(zenity --file-selection --title="Open File" --file-filter="*.jpg *.jpeg *.png *.webp *.bmp *.jfif *.tiff *.avif *.heic *.heif")
|
|
else
|
|
image="$1"
|
|
fi
|
|
|
|
[ -z "$image" ] && exit 1
|
|
[ ! -f "$image" ] && exit 1
|
|
|
|
# Obtain screen resolution
|
|
|
|
screen_width=$2
|
|
screen_height=$3
|
|
|
|
[ -z "$screen_width" ] && {
|
|
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
|
|
screen_width=$(hyprctl -j monitors | jq '.[0].resolution.x')
|
|
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
|
|
screen_width=$(niri msg focused-output | grep 'Current mode' | awk '{print $3}' | cut -d'x' -f1)
|
|
fi
|
|
}
|
|
|
|
[ -z "$screen_height" ] && {
|
|
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
|
|
screen_height=$(hyprctl -j monitors | jq '.[0].resolution.y')
|
|
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
|
|
screen_height=$(niri msg focused-output | grep 'Current mode' | awk '{print $3}' | cut -d'x' -f2)
|
|
fi
|
|
}
|
|
|
|
[ -z "$screen_width" ] && screen_width=2560
|
|
[ -z "$screen_height" ] && screen_height=1440
|
|
|
|
# $HOME/.config/wallpaper-chooser/config.json:
|
|
# ```json
|
|
# "sort": {
|
|
# "type": "date",
|
|
# "reverse": true
|
|
# }
|
|
# ```
|
|
# So in order to let the most recently used wallpapers appear first:
|
|
touch "$image"
|
|
|
|
|
|
# Copy image to local wallpaper directory
|
|
|
|
ext=${image##*.}
|
|
random_name=$(tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 16)
|
|
current_dir="$HOME/.local/share/wallpaper/current"
|
|
image_copied="$current_dir/wallpaper-${random_name}.${ext}"
|
|
|
|
mkdir -p "$current_dir" || {
|
|
echo "Could not create directory $current_dir"
|
|
exit 1
|
|
}
|
|
|
|
temp_img=$(mktemp --suffix=."$ext") || exit 1
|
|
trap 'rm -f "$temp_img"' EXIT
|
|
magick convert "$image" -resize "${screen_width}x${screen_height}^" -gravity center -extent "${screen_width}x${screen_height}" "$temp_img" || {
|
|
echo "Could not resize and crop image"
|
|
exit 1
|
|
}
|
|
cp "$temp_img" "$image_copied" || exit 1
|
|
hash=$(md5sum "$image_copied" | awk '{print $1}')
|
|
|
|
# Clean up old wallpapers
|
|
|
|
find "$current_dir" -type f -name "wallpaper-*" ! -name "$(basename "$image_copied")" -delete
|
|
|
|
# Generate blurred wallpaper
|
|
|
|
blur_dir="$HOME/.local/share/wallpaper/blurred"
|
|
blur_cache_dir="$HOME/.local/share/wallpaper/blurred-cache"
|
|
mkdir -p "$blur_dir" "$blur_cache_dir" || {
|
|
echo "Could not create cache directory"
|
|
exit 1
|
|
}
|
|
blurred_image="$blur_dir/blurred-${random_name}.$ext"
|
|
blurred_cache_image="$blur_cache_dir/${hash}.$ext"
|
|
|
|
## Time consuming task (magick -blur) in background
|
|
(
|
|
# notify-send -a "change-wallpaper" "Generating Blurred Wallpaper" "This may take a few seconds..."
|
|
|
|
### Check if cached blurred image exists
|
|
if [ -f "$blurred_cache_image" ]; then
|
|
# sleep 1 # Some ugly workaround
|
|
if ! cp -f "$blurred_cache_image" "$blurred_image"; then
|
|
echo "Could not copy cached blurred image"
|
|
# exit 1 # Non-critical error
|
|
else
|
|
find "$blur_dir" -type f -name "blurred-*" ! -name "$(basename "$blurred_image")" -delete
|
|
if [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
|
|
swww img -n backdrop "$blurred_image" --transition-type fade --transition-duration 2 > /dev/null 2> /dev/null
|
|
fi
|
|
notify-send -a "change-wallpaper" "Blurred Wallpaper From Cache" "$blurred_image" -i "$blurred_image"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
sigma=$(magick identify -format "%w %h" "$image_copied" | awk -v f=0.01 '{
|
|
m=($1>$2)?$1:$2;
|
|
s=m*f;
|
|
if(s<2) s=2;
|
|
if(s>200) s=200;
|
|
printf "%.2f", s
|
|
}')
|
|
|
|
### use a temporary file to avoid incomplete file being used
|
|
temp_blurred=$(mktemp --suffix=."$ext") || exit 1
|
|
trap 'rm -f "${temp_blurred}"' EXIT
|
|
magick "$image_copied" -blur 0x"$sigma" "$temp_blurred" || {
|
|
echo "Could not create blurred image"
|
|
exit 1
|
|
}
|
|
|
|
mv -f "$temp_blurred" "$blurred_image" || {
|
|
echo "Could not move blurred image to cache directory"
|
|
exit 1
|
|
}
|
|
|
|
find "$blur_dir" -type f -name "blurred-*" ! -name "$(basename "$blurred_image")" -delete
|
|
|
|
cp -f "$blurred_image" "$blurred_cache_image" || {
|
|
echo "Could not cache blurred image"
|
|
# exit 1 # Non-critical error
|
|
}
|
|
|
|
if [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
|
|
swww img -n backdrop "$blurred_image" --transition-type fade --transition-duration 2 > /dev/null 2> /dev/null
|
|
fi
|
|
|
|
notify-send -a "change-wallpaper" "Blurred Wallpaper Generated" "$blurred_image" -i "$blurred_image"
|
|
) &
|
|
|
|
# Apply wallpaper
|
|
|
|
if [ "$XDG_CURRENT_DESKTOP" = "Hyprland" ]; then
|
|
swww img -n background "$image_copied" --transition-type fade --transition-duration 2 > /dev/null 2> /dev/null
|
|
|
|
notify-send -a "change-wallpaper" "Wallpaper Changed" "$image" -i "$image_copied"
|
|
|
|
change-colortheme -i "$image_copied" || exit 1
|
|
elif [ "$XDG_CURRENT_DESKTOP" = "niri" ]; then
|
|
### Handled in wallpaper-daemon
|
|
# swww img -n background "$image_copied" --transition-type fade --transition-duration 2 > /dev/null 2> /dev/null
|
|
|
|
notify-send -a "change-wallpaper" "Wallpaper Changed" "$image" -i "$image_copied"
|
|
|
|
change-colortheme -i "$image_copied" || exit 1
|
|
else
|
|
echo "Unsupported desktop environment: $XDG_CURRENT_DESKTOP"
|
|
exit 1
|
|
fi
|