hyprwm / hyprpaper

Hyprpaper is a blazing fast wayland wallpaper utility with IPC controls.
https://wiki.hyprland.org/Hypr-Ecosystem/hyprpaper/
BSD 3-Clause "New" or "Revised" License
773 stars 54 forks source link

Switch wallpaper every N amount of time #88

Closed ignamartinoli closed 1 year ago

ignamartinoli commented 1 year ago

Hi,

I would like to create a script where I can declare some wallpapers (or a directory with wallpapers), and every N amount of time Hyprpaper should switch between one of them randomly (KDE has a feature like that).

I have this for now but it feels weird/suboptimal/messy

#!/bin/sh

while true; do
    wallpaper="$(find -L "$XDG_DATA_HOME/hypr/wallpapers" -type f | shuf -n 1)"
    echo "ipc = off

    preload = $wallpaper

    wallpaper = eDP-1,$wallpaper
    wallpaper = HDMI-A-1,$wallpaper" > "$XDG_CONFIG_HOME/hypr/hyprpaper.conf"
    hyprpaper &

    sleep 5

    killall -9 hyprpaper
done

Does somebody knows a better way?

Vinetos commented 1 year ago

Hi,

What is your compositor ?

With Hyperland, You can use a CRON job or a systemd timer to change the wallpaper dynamically with

hyprctl hyprpaper wallpaper $(find -L $(xdg-user-dir PICTURES)/Wallpapers -type f | shuf -n 1)

The CRON job or systemd will repeat this

:warning: Make sure they are preloaded.

ignamartinoli commented 1 year ago

@Vinetos that's a very clever idea.

I use Hyprland.

I came up with this in a single script (and it works):

#!/bin/sh

while true; do
    wallpaper="$(find -L "$XDG_DATA_HOME/hypr/wallpapers" -type f | shuf -n 1)"
    echo "ipc = off

    preload = $wallpaper

    wallpaper = eDP-1,$wallpaper
    wallpaper = HDMI-A-1,$wallpaper" > "$XDG_CONFIG_HOME/hypr/hyprpaper.conf"
    hyprpaper &

    sleep 5

    killall -9 hyprpaper
done

but I'm not sure if it would be better to follow this script route or go for a CRON job like you suggested.

Vinetos commented 1 year ago

but I'm not sure if it would be better to follow this script route or go for a CRON job like you suggested.

I think its according to your preferences. Both could be good.

The script seems fine if you disabled IPC.

But I personally would go for IPC : If you want to stay with the script, you need to clean it a little bit. It unnecessary restarts the hyprpaper every 5s. As it is a daemon, you can dynamically execute theses actions by using hyprctl hyprpaper. I would go with something like that :

hyprpaper.conf:

ipc = on

# If your memory can handle it (and not too much wallpaper)
# preload=path/to/wallpaper/1.jpg
# preload=path/to/wallpaper/2.jpg
# preload=path/to/wallpaper/3.jpg

hyprland.conf:

exec-once=hyprpaper

Then update the shell to use the socket created by the daemon.

#!/bin/sh

while true; do
    wallpaper="$(find -L "$XDG_DATA_HOME/hypr/wallpapers" -type f | shuf -n 1)"
    hyprctl hyprpaper preload "$wallpaper" # Not necessary if you preloaded all the wallpapers in hyprpaper.conf
    hyprctl hyprpaper wallpaper "eDP-1,$wallpaper"
    hyprctl hyprpaper wallpaper "HDMI-A-1,$wallpaper"

    sleep 5
    hyprctl hyprpaper unload "$wallpaper" # Not necessary if you preloaded all the wallpapers in hyprpaper.conf

done

And you should be fine !

Side note: You can use a wildcard to apply the new wallpaper to all monitors : hyprctl hyprpaper wallpaper ",$wallpaper" / wallpaper = ",$wallpaper"

ignamartinoli commented 1 year ago

Thanks @Vinetos. I understand the concept, however I'm not sure about is where should I launch hyprpaper.sh.

I tried writing into hyprland.conf

exec-once = hyprpaper & /home/sicro/.config/hypr/hyprpaper.sh

and I would get no result.


I also tried writing into hyprland.conf

exec-once = $XDG_CONFIG_HOME/hypr/hyprpaper.sh

and launching hyperpaper from hyprpaper.sh

#!/bin/sh

config="$XDG_CONFIG_HOME/hypr/hyprpaper.conf"
wallpapers="$HOME/Pictures/Wallpapers"

echo 'ipc = on' > "$config"
for picture in "$wallpapers"/*; do
    echo "preload = $picture" >> "$config"
done

hyprpaper

while true; do
    wallpaper="$(find -L "$wallpapers" -type f | shuf -n 1)"

    hyprctl hyprpaper wallpaper "eDP-1,$wallpaper"

    sleep 60
done

but it wouldn't work.


Do you happen to know what I'm doing wrong?

Vinetos commented 1 year ago

I tried writing into hyprland.conf

exec-once = hyprpaper & /home/sicro/.config/hypr/hyprpaper.sh

and I would get no result.

Have you tried splitting the execution ?

exec-once = hyprpaper
exec-once = /home/sicro/.config/hypr/hyprpaper.sh

I also tried writing into hyprland.conf

exec-once = $XDG_CONFIG_HOME/hypr/hyprpaper.sh

and launching hyperpaper from hyprpaper.sh

#!/bin/sh

config="$XDG_CONFIG_HOME/hypr/hyprpaper.conf"
wallpapers="$HOME/Pictures/Wallpapers"

echo 'ipc = on' > "$config"
for picture in "$wallpapers"/*; do
  echo "preload = $picture" >> "$config"
done

hyprpaper

while true; do
  wallpaper="$(find -L "$wallpapers" -type f | shuf -n 1)"

  hyprctl hyprpaper wallpaper "eDP-1,$wallpaper"

  sleep 60
done

but it wouldn't work.

Do you have any errors or logs ?

ignamartinoli commented 1 year ago

I think I get what the problem is.

When hyprpaper runs it doesn't stop execution of other programs, so it goes straight to hyprctl hyprpaper wallpaper "eDP-1,$wallpaper" and since it's still pre-loading images it fails

Vinetos commented 1 year ago

That is totally possible. I was not sure when IPC is off but hyperland does stop its execution only when failing or receiving signal.

ignamartinoli commented 1 year ago

Hey @Vinetos, I was able to make the script work like this:

while true; do
    wallpaper="$(find -L "$directory" -type f | shuf -n 1)"

    hyprctl hyprpaper preload "$wallpaper"

    hyprctl hyprpaper wallpaper "eDP-1,$wallpaper"
    hyprctl hyprpaper wallpaper "HDMI-A-1,$wallpaper"

    sleep $time

    hyprctl hyprpaper unload "$wallpaper"
done

This only works if I have ipc = on. I wanted to make it work with IPC disabled, but I don't get what exactly disables this approach or how to circumvent this . Do you have any idea?

h0m3 commented 3 months ago

Hello,

I wrote this one that sets a random wallpaper per active display, just added on cron to run every 15 minutes. Also unload old wallpapers.

#!/bin/sh

WALLPAPER_DIR="${HOME}/Pictures/wallpapers"

OLDIFS=$IFS
IFS=$'\n'
for wallpaper in $(hyprctl hyprpaper listloaded); do
    hyprctl hyprpaper unload "$wallpaper"
done
IFS=$OLDIFS

for display in $(hyprctl monitors | grep "Monitor" | cut -d " " -f 2); do
    wallpaper="$(find "$WALLPAPER_DIR" -type f | shuf -n 1)"
    hyprctl hyprpaper preload "$wallpaper"
    hyprctl hyprpaper wallpaper "$display,$wallpaper"
done

I think it would be awesome if it was a native option of hyprpaper, instead of scripting. Maybe load a list of wallpapers and shuffle between then randomly using IPC.