nixos: unify wallpapers via syncthing
Start hyprpaper via a user service and set wallpaper via IPC on session start.\nPoint xmonad random-background at the same Syncthing wallpaper directory (X11 only).
This commit is contained in:
@@ -4,6 +4,120 @@
|
||||
./emacs.nix
|
||||
];
|
||||
|
||||
# Hyprland config starts this target on login (see `dotfiles/config/hypr/hyprland.conf`).
|
||||
systemd.user.targets.hyprland-session = {
|
||||
Unit = {
|
||||
Description = "Hyprland session (custom)";
|
||||
};
|
||||
};
|
||||
|
||||
systemd.user.services.hyprpaper = let
|
||||
wallpaperDir = "/var/lib/syncthing/sync/Wallpaper";
|
||||
waitForWayland = pkgs.writeShellScript "wait-for-wayland" ''
|
||||
# Hyprpaper needs a Wayland socket. systemd "Condition*" checks are
|
||||
# brittle here (they skip the unit entirely, with no retry) and also
|
||||
# don't support expanding $WAYLAND_DISPLAY in paths.
|
||||
for _ in {1..50}; do
|
||||
if [ -n "$WAYLAND_DISPLAY" ] && [ -n "$XDG_RUNTIME_DIR" ] && [ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; then
|
||||
exit 0
|
||||
fi
|
||||
${pkgs.coreutils}/bin/sleep 0.1
|
||||
done
|
||||
|
||||
echo "Wayland socket not ready: WAYLAND_DISPLAY=$WAYLAND_DISPLAY XDG_RUNTIME_DIR=$XDG_RUNTIME_DIR" >&2
|
||||
exit 1
|
||||
'';
|
||||
setWallpaper = pkgs.writeShellScript "set-hyprpaper-wallpaper" ''
|
||||
# hyprpaper 0.8.x doesn't seem to apply `wallpaper = ...` entries from
|
||||
# its config on startup reliably. Explicitly set the wallpaper via IPC
|
||||
# once the hyprpaper socket is ready.
|
||||
#
|
||||
# NOTE: hyprctl hyprpaper currently ignores `--instance` and uses
|
||||
# $HYPRLAND_INSTANCE_SIGNATURE to find hyprpaper's socket, so we rely on
|
||||
# the environment imported by Hyprland on login.
|
||||
set -u
|
||||
|
||||
runtimeDir="''${XDG_RUNTIME_DIR:-}"
|
||||
sig="''${HYPRLAND_INSTANCE_SIGNATURE:-}"
|
||||
sockPath=""
|
||||
if [ -n "$runtimeDir" ] && [ -n "$sig" ]; then
|
||||
sockPath="$runtimeDir/hypr/$sig/.hyprpaper.sock"
|
||||
fi
|
||||
|
||||
# Don't fail the service if env isn't available yet.
|
||||
if [ -z "$sockPath" ]; then
|
||||
echo "set-hyprpaper-wallpaper: missing XDG_RUNTIME_DIR/HYPRLAND_INSTANCE_SIGNATURE" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for _ in {1..50}; do
|
||||
if [ -S "$sockPath" ]; then
|
||||
break
|
||||
fi
|
||||
${pkgs.coreutils}/bin/sleep 0.1
|
||||
done
|
||||
|
||||
if [ ! -S "$sockPath" ]; then
|
||||
echo "set-hyprpaper-wallpaper: hyprpaper socket not ready at $sockPath" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ ! -d "${wallpaperDir}" ]; then
|
||||
echo "set-hyprpaper-wallpaper: wallpaper directory missing: ${wallpaperDir}" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
wallpaper="$(${pkgs.findutils}/bin/find "${wallpaperDir}" -type f -regextype posix-extended -iregex '.*\.(png|jpe?g|webp)$' -print0 | ${pkgs.coreutils}/bin/shuf -z -n 1 | ${pkgs.coreutils}/bin/tr -d '\0')"
|
||||
|
||||
if [ -z "$wallpaper" ]; then
|
||||
echo "set-hyprpaper-wallpaper: no wallpapers found in ${wallpaperDir}" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Apply to all current monitors.
|
||||
mons=$(/run/current-system/sw/bin/hyprctl -j monitors 2>/dev/null | ${pkgs.jq}/bin/jq -r '.[].name' 2>/dev/null || true)
|
||||
if [ -z "$mons" ]; then
|
||||
# Fallback to parsing non-JSON output.
|
||||
mons=$(/run/current-system/sw/bin/hyprctl monitors 2>/dev/null | ${pkgs.gnugrep}/bin/grep -oE '^Monitor [^ ]+' | ${pkgs.coreutils}/bin/cut -d' ' -f2 || true)
|
||||
fi
|
||||
|
||||
for mon in $mons; do
|
||||
# The socket file can exist before hyprpaper is actually ready to
|
||||
# accept connections, so retry briefly.
|
||||
for _ in {1..50}; do
|
||||
if /run/current-system/sw/bin/hyprctl hyprpaper wallpaper "$mon,$wallpaper" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
${pkgs.coreutils}/bin/sleep 0.1
|
||||
done
|
||||
done
|
||||
|
||||
exit 0
|
||||
'';
|
||||
hyprpaperConf = pkgs.writeText "hyprpaper.conf" ''
|
||||
ipc = true
|
||||
splash = false
|
||||
'';
|
||||
in {
|
||||
Unit = {
|
||||
Description = "Hyprpaper (managed by home-manager)";
|
||||
PartOf = [ "hyprland-session.target" ];
|
||||
After = [ "hyprland-session.target" ];
|
||||
};
|
||||
|
||||
Service = {
|
||||
ExecStartPre = waitForWayland;
|
||||
ExecStart = "${pkgs.hyprpaper}/bin/hyprpaper -c ${hyprpaperConf}";
|
||||
ExecStartPost = setWallpaper;
|
||||
Restart = "on-failure";
|
||||
RestartSec = 1;
|
||||
};
|
||||
|
||||
Install = {
|
||||
WantedBy = [ "hyprland-session.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
xdg.desktopEntries.google-chrome-devtools = {
|
||||
name = "Google Chrome (DevTools)";
|
||||
genericName = "Web Browser";
|
||||
|
||||
Reference in New Issue
Block a user