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
724 stars 53 forks source link

[DISCUSSION] Best way to change wallpaper with hyprpaper? #108

Open zft9xgy opened 8 months ago

zft9xgy commented 8 months ago

Hello everyone, I'm opening this topic to discuss what is the best way to change wallpaper in hyprpaper:

This is how I do it right now, basically reset the hyprpaper.conf file and then overwrite it with the new info. is this the best way to change the wallpaper?

echo '' > /.config/hypr/hyprpaper.conf
echo "preload = /new-wallpaper-path/" >>  /.config/hypr/hyprpaper.conf
echo "wallpaper =,/new-wallpaper-path/" >>  /.config/hypr/hyprpaper.conf

TL;DR

Basically i use this to change wallpaper with hyprper and i use it in 3 different scripts, which are:

With the set-wallpaper.sh script I have made a setting in Thunar, which allows me to set an image as wallpaper by right clicking.

vaxerski commented 8 months ago

hyprctl hyprpaper ... is better

zft9xgy commented 8 months ago

It seem easy, but, if you want to use hyprctl hyprpaper wallpaper "DP-1,~/Pictures/myepicpng.png" the wallpaper need to be preloaded, so i think i will stick to my scrips, which it works.

Buy thank you!!

vaxerski commented 8 months ago

you can make two calls, one for preload and one for wallpaper

zft9xgy commented 8 months ago

Hi again, sorry for the delay. Still didnt make it work with hyperctl.

So just as example: My wallpaper folder got around 100 differents wallpapers, and the names are "wallpapaer-1" with out .png or .jpg, with out forrmat sufix.

Trying you way will be:

hyprctl hyprpaper preload "~/wallpapers/wallpaper-1"
hyprctl hyprpaper monitor ",~/wallpapers/wallpaper-1"

For me this didnt work. Error: File not found, could be because of sufix ?

Thanks for the help

vaxerski commented 8 months ago

what if you specify the monitor explicitly in monitor?

zft9xgy commented 8 months ago

Sorry it was a mistake: writting the post:

hyprctl hyprpaper preload "~/wallpapers/wallpaper-1" 
hyprctl hyprpaper wallpaper ",~/wallpapers/wallpaper-1"

But, is not working for me. Thanks again.

keithbowes commented 7 months ago

hyprctl hyprpaper ... is better

Or for those of us using hyprpaper with another compositor: printf ... | socat UNIX-CONNECT:/tmp/hypr/.hyperpaper.sock -

Unfortunately, only one user is permitted at a time that way. It should go to /tmp/hypr-${USER} instead.

simonwiles commented 7 months ago

what if you specify the monitor explicitly in monitor?

(for me, at least) it does work when specifying the monitor explicitly, but it doesn't if I use hyprctl hyprpaper wallpaper ",~/wallpapers/wallpaper-1"; which is a shame, because that's what I actually want to do. Is this intended/expected behaviour, or does it constitute a bug?

askdkc commented 6 months ago

@simonwiles

Just created a bash script which randomly changes background image. It automatically gets monitor name by running hyprctl monitors | grep Monitor | awk '{print $2}'

#!/bin/bash

directory=~/YOUR_BACKGROUND/IMAGE/DIRECTORY
monitor=`hyprctl monitors | grep Monitor | awk '{print $2}'`

if [ -d "$directory" ]; then
    random_background=$(ls $directory/*.jpg | shuf -n 1)

    hyprctl hyprpaper unload all
    hyprctl hyprpaper preload $random_background
    hyprctl hyprpaper wallpaper "$monitor, $random_background"

fi
grapeofwrath commented 5 months ago

@simonwiles

Just created a bash script which randomly changes background image. It automatically gets monitor name by running hyprctl monitors | grep Monitor | awk '{print $2}'

#!/bin/bash

directory=~/YOUR_BACKGROUND/IMAGE/DIRECTORY
monitor=`hyprctl monitors | grep Monitor | awk '{print $2}'`

if [ -d "$directory" ]; then
    random_background=$(ls $directory/*.jpg | shuf -n 1)

    hyprctl hyprpaper unload all
    hyprctl hyprpaper preload $random_background
    hyprctl hyprpaper wallpaper "$monitor, $random_background"

fi

Took your idea with a lil inspiration from ZaneyOS and made a script that changes the wallpaper for all monitors every 15m. It's for a Nix config but one can easily make it a normal script if necessary.

{ pkgs, username, wallpaperDir, wallpaperGit }:

pkgs.writeShellScriptBin "wallpaper" ''
  monitor=(`hyprctl monitors | grep Monitor | awk '{print $2}'`)
  wal=$(find ${wallpaperDir} -name '*' | awk '!/.git/' | tail -n +2 | shuf -n 1)
  cache=""

  if [ -d ${wallpaperDir} ]; then
    cd ${wallpaperDir}
    git pull
  else
    ${pkgs.git}/bin/git clone ${wallpaperGit} ${wallpaperDir}
    chown -R ${username}:users ${wallpaperDir}
  fi

  while true; do
    if [[ $cache == $wal ]]; then
      wal=$(find ${wallpaperDir} -name '*' | awk '!/.git/' | tail -n +2 | shuf -n 1)
    else
      cache=$wal
      hyprctl hyprpaper unload all
      hyprctl hyprpaper preload $wal
      for m in ''${monitor[@]}; do
        hyprctl hyprpaper wallpaper "$m,$wal"
      done
    fi
    sleep 900
  done
''
askdkc commented 5 months ago

@grapeofwrath

Nice work!! Love seeing OSS synergy.

izmyname commented 3 months ago

In my case, here's my hyprpaper.conf

preload = ~/.wallpaper
wallpaper = eDP-1,~/.wallpaper
splash = false
ipc = off

And a keybind to reload hyprpaper. $bgreload = killall -e hyprpaper & sleep 1; hyprpaper & bind = $extraMod, R, exec, $bgreload

So, whenever I wanna change my wallpaper, i do ln -sf ~/Pictures/mynewbg.png ~/.wallpaper and reload hyprpaper with meta+shift+r.

ertugrulgacal commented 2 months ago

Here is the bash script I use to change the wallpaper on all my monitors.

#!/bin/bash

# Check if a file argument was provided
if [ -z "$1" ]; then
    echo "Error: Please provide a wallpaper file as an argument."
    exit 1
fi

# Check if the file exists
if [ ! -f "$1" ]; then
    echo "Error: File not found: $1"
    exit 1
fi

# Path to your hyprpaper configuration file
hyprpaper_config_file="$HOME/.config/hypr/hyprpaper.conf"

# Update the config file with the new wallpaper path 
sed -i -e "s|^preload = .*$|preload = $1|" \
       -e "s|^wallpaper = .*$|wallpaper = ,$1|" \
       "$hyprpaper_config_file"

# Reload hyprpaper
killall -e hyprpaper & 
sleep 1; 
hyprpaper &

# Let the user know it's done
echo "Wallpaper settings in hyprpaper.conf updated successfully."

usage: ./change_wallpaper.sh /path/to/your/wallpaper

ecarlson94 commented 2 months ago

I created a home-manager module that sets up hyprpaper and a systemd user service to randomize the wallpaper on an interval. Additionally, it uses lutgen to theme all images within a directory local to the nix configuration. So, no matter the image, it will always be on brand!

{
  pkgs,
  lib,
  ...
}:
with lib;
with builtins; let
  theme = {
    name = "catppuccin-mocha"; # Run `nix-shell -p lutgen --command 'lutgen apply -p ""` to see supported color palettes
    wallpapers = ./some/local/directory/of/images;
  };

  themedWallpaper = wallpaper:
    pkgs.stdenv.mkDerivation rec {
      name = "${theme.name}-${baseNameOf wallpaper}";
      nativeBuildInputs = [pkgs.lutgen];

      phases = ["buildPhase" "installPhase"];

      buildPhase = ''
        cp ${wallpaper} ./${name}
        lutgen apply -p ${theme.name} ${name} -o themed
      '';

      installPhase = ''
        cp themed/${name} $out
      '';
    };

  wallpapers = filesystem.listFilesRecursive theme.wallpapers;
  themedWallpapers = listToAttrs (map (wallpaper: {
      name = "${baseNameOf wallpaper}";
      value = themedWallpaper wallpaper;
    })
    wallpapers);

  wallpaperBashArray = "(\"${strings.concatStrings (strings.intersperse "\" \"" (map (wallpaper: "${wallpaper}") (attrValues themedWallpapers)))}\")";
  wallpaperRandomizer = pkgs.writeShellScriptBin "wallpaperRandomizer" ''
    wallpapers=${wallpaperBashArray}
    rand=$[$RANDOM % ''${#wallpapers[@]}]
    wallpaper=''${wallpapers[$rand]}

    monitor=(`hyprctl monitors | grep Monitor | awk '{print $2}'`)
    hyprctl hyprpaper unload all
    hyprctl hyprpaper preload $wallpaper
    for m in ''${monitor[@]}; do
      hyprctl hyprpaper wallpaper "$m,$wallpaper"
    done
  '';
in {
  home.packages = [wallpaperRandomizer];

  services.hyprpaper = {
    enable = true;

    settings = {
      ipc = "on";
      splash = false;
      splash_offset = 2.0;
    };
  };

  systemd.user = {
    services.wallpaperRandomizer = {
      Install = {WantedBy = ["graphical-session.target"];};

      Unit = {
        Description = "Set random desktop background using hyprpaper";
        After = ["graphical-session-pre.target"];
        PartOf = ["graphical-session.target"];
      };

      Service = {
        Type = "oneshot";
        ExecStart = "${wallpaperRandomizer}/bin/wallpaperRandomizer";
        IOSchedulingClass = "idle";
      };
    };

    timers.wallpaperRandomizer = {
      Unit = {Description = "Set random desktop background using hyprpaper on an interval";};

      Timer = {OnUnitActiveSec = "1h";};

      Install = {WantedBy = ["timers.target"];};
    };
  };
}

You can also manually trigger it by running wallpaperRandomizer in a shell. I know this is very nix specific, but if that is your use case, you're in luck.

ecarlson94 commented 2 months ago

Here is a version without lutgen for those who just want something simple:

{
  pkgs,
  lib,
  ...
}:
with lib; let
  theme = {
    name = "catppuccin-mocha"; # Run `nix-shell -p lutgen --command 'lutgen apply -p ""` to see supported color palettes
    wallpapers = ./some/local/directory/of/images;
  };

  wallpapers = filesystem.listFilesRecursive theme.wallpapers;

  wallpaperBashArray = "(\"${strings.concatStrings (strings.intersperse "\" \"" (map (wallpaper: "${wallpaper}") wallpapers))}\")";
  wallpaperRandomizer = pkgs.writeShellScriptBin "wallpaperRandomizer" ''
    wallpapers=${wallpaperBashArray}
    rand=$[$RANDOM % ''${#wallpapers[@]}]
    wallpaper=''${wallpapers[$rand]}

    monitor=(`hyprctl monitors | grep Monitor | awk '{print $2}'`)
    hyprctl hyprpaper unload all
    hyprctl hyprpaper preload $wallpaper
    for m in ''${monitor[@]}; do
      hyprctl hyprpaper wallpaper "$m,$wallpaper"
    done
  '';
in {
  home.packages = [wallpaperRandomizer];

  services.hyprpaper = {
    enable = true;

    settings = {
      ipc = "on";
      splash = false;
      splash_offset = 2.0;
    };
  };

  systemd.user = {
    services.wallpaperRandomizer = {
      Install = {WantedBy = ["graphical-session.target"];};

      Unit = {
        Description = "Set random desktop background using hyprpaper";
        After = ["graphical-session-pre.target"];
        PartOf = ["graphical-session.target"];
      };

      Service = {
        Type = "oneshot";
        ExecStart = "${wallpaperRandomizer}/bin/wallpaperRandomizer";
        IOSchedulingClass = "idle";
      };
    };

    timers.wallpaperRandomizer = {
      Unit = {Description = "Set random desktop background using hyprpaper on an interval";};

      Timer = {OnUnitActiveSec = "1h";};

      Install = {WantedBy = ["timers.target"];};
    };
  };
}
ebiscaia commented 1 month ago

Hi all,

Came up a similar version of the script with some modifications to make sure that my wallpaper orientation would match the orientation of the screen

!/bin/bash

while true; do
    killall hyprpaper
    FOLDER=~/.config/hypr

    # Overwrite config file with a blank version of it
    cp $FOLDER/hyprpaper.conf.bak $FOLDER/hyprpaper.conf

    # Start with blank values for preload and load variables
    PRELOAD=""
    LOAD=""

    # Loop accross all monitors
    for MONITOR in $(hyprctl monitors | awk '/^Monitor/ {print $2}'); do

        PATHPIC="$HOME/Pictures/Wallpapers/" # Determine the screen orientation

        # Get the value of orientation from hyprctl monitor
        ORIENTATION=$(hyprctl monitors | awk '/'"$MONITOR"'/{c=15} c&&c--' | awk '/transform/{print$2}')

        if ((ORIENTATION % 2 == 0)); then
            ORIENTATION="Landscape"
        else
            ORIENTATION="Portrait"
        fi

        # Append the screen orientation to the path
        PATHPIC+="$ORIENTATION/"

        # Now get a random file name and append to the path
        IMAGE=$(find "$PATHPIC" -name "*" -type f | shuf -n 1)

        PRELOAD+="preload = $IMAGE\n"
        LOAD+="wallpaper = $MONITOR,$IMAGE\n"

    done

    # Append the file name with the preload and load commands
    sed -i "/\# Preloads/a $PRELOAD" $FOLDER/hyprpaper.conf
    sed -i "/\# Wallpaper/a $LOAD" $FOLDER/hyprpaper.conf
    sed -i "s/^[{}]//" $FOLDER/hyprpaper.conf

    # Execute hyprpaper
    hyprpaper --config ~/.config/hypr/hyprpaper.conf &

    sleep 3600
done

That's all and good. However, if I try to use my user crontab (instead of looping and sleeping), I have got the following message:

[LOG] Welcome to hyprpaper!
built from commit  ()
[LOG] Using config location /home/eddie/.config/hypr/hyprpaper.conf.
[LOG] Cleaned old hyprpaper preloads (6), removing 75.6MB
[CRITICAL] No wayland compositor running!

Any idea why?

rofe33 commented 1 month ago

Hello all,

Thoughts on pyprpaper? It's a python script that randomly change wallpapers from a given directory or directories. I use the socket module, so there's no need to have hyprland installed.

For now the script randomly choose the wallpapers. If you have any other implementations to add, I would love to add them.

My current setup:

The hyprpaper.conf file is:

splash = off

I have a exec-once in the hyprland.conf:

exec-once = pyprpaper -m $(hyprctl -j monitors | jq -r '.[].name' | tr '\n' ' ') -- /path/to/directory

Note: You can create a cron job or a systemd timer to change periodically the wallpaper.

rofe33 commented 1 month ago

Note: You can create a cron job or a systemd timer to change periodically the wallpaper.

Hello,

I updated pyprpaper to include a --timer option, then we will be able to change the wallpaper each n seconds.

Now there is no need to use cron jobs or systemd timer.