Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package hyprpaper for openSUSE:Factory 
checked in at 2026-08-03 17:17:15
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/hyprpaper (Old)
 and      /work/SRC/openSUSE:Factory/.hyprpaper.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "hyprpaper"

Mon Aug  3 17:17:15 2026 rev:10 rq:1369175 version:0.8.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/hyprpaper/hyprpaper.changes      2026-02-17 
18:45:53.220315229 +0100
+++ /work/SRC/openSUSE:Factory/.hyprpaper.new.16738/hyprpaper.changes   
2026-08-03 17:17:29.955140500 +0200
@@ -1,0 +2,10 @@
+Fri Jul 31 16:31:49 UTC 2026 - Nassim Lhadj <[email protected]>
+
+- Update to version 0.8.4:
+  * Fix: set id and overwrite wildcard on explicit
+  * protocol: add a status object
+  * feature: add ability to randomize sort order
+  * feature: add opt-in recursive wallpaper directory scanning
+  * config/ui: add random-shuffle slideshow order
+
+-------------------------------------------------------------------

Old:
----
  hyprpaper-0.8.3.tar.gz

New:
----
  hyprpaper-0.8.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ hyprpaper.spec ++++++
--- /var/tmp/diff_new_pack.VLEuHO/_old  2026-08-03 17:17:30.855171820 +0200
+++ /var/tmp/diff_new_pack.VLEuHO/_new  2026-08-03 17:17:30.859171960 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           hyprpaper
-Version:        0.8.3
+Version:        0.8.4
 Release:        0
 Summary:        Wayland wallpaper utility with IPC controls
 License:        BSD-3-Clause

++++++ hyprpaper-0.8.3.tar.gz -> hyprpaper-0.8.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/.github/workflows/nix-build.yaml 
new/hyprpaper-0.8.4/.github/workflows/nix-build.yaml
--- old/hyprpaper-0.8.3/.github/workflows/nix-build.yaml        2026-01-29 
16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/.github/workflows/nix-build.yaml        2026-04-29 
22:21:53.000000000 +0200
@@ -1,50 +1,12 @@
-name: Build Hyprpaper (Nix)
+name: Build
 
 on: [push, pull_request, workflow_dispatch]
+
 jobs:
   nix:
-    name: "Build"
-    runs-on: ubuntu-latest
-    steps:
-    - name: Clone repository
-      uses: actions/checkout@v3
-      with:
-        submodules: recursive
-
-    - name: Install Nix
-      uses: nixbuild/nix-quick-install-action@v31
-      with:
-        nix_conf: |
-          keep-env-derivations = true
-          keep-outputs = true
-
-    - name: Restore and save Nix store
-      uses: nix-community/cache-nix-action@v6
-      with:
-        # restore and save a cache using this key
-        primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', 
'**/flake.lock') }}
-        # if there's no cache hit, restore a cache by this prefix
-        restore-prefixes-first-match: nix-${{ runner.os }}-
-        # collect garbage until the Nix store size (in bytes) is at most this 
number
-        # before trying to save a new cache
-        # 1G = 1073741824
-        gc-max-store-size-linux: 1G
-        # do purge caches
-        purge: true
-        # purge all versions of the cache
-        purge-prefixes: nix-${{ runner.os }}-
-        # created more than this number of seconds ago
-        purge-created: 0
-        # or, last accessed more than this number of seconds ago
-        # relative to the start of the `Post Restore and save Nix store` phase
-        purge-last-accessed: 0
-        # except any version with the key that is the same as the `primary-key`
-        purge-primary-key: never
-
-    - uses: cachix/cachix-action@v12
-      with:
-        name: hyprland
-        authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
-
-    - name: Build Hyprpaper with default settings
-      run: nix build --print-build-logs --accept-flake-config
+    if: (github.event_name != 'pull_request' || 
github.event.pull_request.head.repo.fork)
+    uses: hyprwm/actions/.github/workflows/nix.yml@main
+    secrets: inherit
+    with:
+      submodules: recursive
+      command: nix build --print-build-logs --accept-flake-config
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/VERSION new/hyprpaper-0.8.4/VERSION
--- old/hyprpaper-0.8.3/VERSION 2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/VERSION 2026-04-29 22:21:53.000000000 +0200
@@ -1 +1 @@
-0.8.3
+0.8.4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/flake.lock 
new/hyprpaper-0.8.4/flake.lock
--- old/hyprpaper-0.8.3/flake.lock      2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/flake.lock      2026-04-29 22:21:53.000000000 +0200
@@ -16,11 +16,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1765900596,
-        "narHash": "sha256-+hn8v9jkkLP9m+o0Nm5SiEq10W0iWDSotH2XfjU45fA=",
+        "lastModified": 1772460678,
+        "narHash": "sha256-NYaWs8fYJ38IgFld0hGSdT2LEVhrgO8SiRReBjIH7YY=",
         "owner": "hyprwm",
         "repo": "aquamarine",
-        "rev": "d83c97f8f5c0aae553c1489c7d9eff3eadcadace",
+        "rev": "5d2cb726b16ee349df443f84b64cff53221b6983",
         "type": "github"
       },
       "original": {
@@ -42,11 +42,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1763733840,
-        "narHash": "sha256-JnET78yl5RvpGuDQy3rCycOCkiKoLr5DN1fPhRNNMco=",
+        "lastModified": 1772461523,
+        "narHash": "sha256-mI6A51do+hEUzeJKk9YSWfVHdI/SEEIBi2tp5Whq5mI=",
         "owner": "hyprwm",
         "repo": "hyprgraphics",
-        "rev": "8f1bec691b2d198c60cccabca7a94add2df4ed1a",
+        "rev": "7d63c04b4a2dd5e59ef943b4b143f46e713df804",
         "type": "github"
       },
       "original": {
@@ -68,11 +68,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1764612430,
-        "narHash": "sha256-54ltTSbI6W+qYGMchAgCR6QnC1kOdKXN6X6pJhOWxFg=",
+        "lastModified": 1772459629,
+        "narHash": "sha256-/iwvNUYShmmnwmz/czEUh6+0eF5vCMv0xtDW0STPIuM=",
         "owner": "hyprwm",
         "repo": "hyprlang",
-        "rev": "0d00dc118981531aa731150b6ea551ef037acddd",
+        "rev": "7615ee388de18239a4ab1400946f3d0e498a8186",
         "type": "github"
       },
       "original": {
@@ -106,11 +106,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1765999299,
-        "narHash": "sha256-C0tMHhVMEN2XlgMVeuJSbY64h9UhR2AKk5Hxxlxx6cA=",
+        "lastModified": 1772462885,
+        "narHash": "sha256-5pHXrQK9zasMnIo6yME6EOXmWGFMSnCITcfKshhKJ9I=",
         "owner": "hyprwm",
         "repo": "hyprtoolkit",
-        "rev": "0a5d2c25d018112434e802212a1ad57ca1e24819",
+        "rev": "9af245a69fa6b286b88ddfc340afd288e00a6998",
         "type": "github"
       },
       "original": {
@@ -129,11 +129,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1766002182,
-        "narHash": "sha256-Ji2ty5d6yuToq59SZfpG0T5B5SkF3UiHoDl8VMyQp14=",
+        "lastModified": 1772459870,
+        "narHash": "sha256-xxkK2Cvqxpf/4UGcJ/TyCwrvmiNWsKsJfFzHMp2bxis=",
         "owner": "hyprwm",
         "repo": "hyprutils",
-        "rev": "1c527b30feb7bed959ac07ae034a6105e6b65fd3",
+        "rev": "e63f3a79334dec49f8eb1691f66f18115df04085",
         "type": "github"
       },
       "original": {
@@ -152,11 +152,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1763640274,
-        "narHash": "sha256-Uan1Nl9i4TF/kyFoHnTq1bd/rsWh4GAK/9/jDqLbY5A=",
+        "lastModified": 1772459835,
+        "narHash": "sha256-978jRz/y/9TKmZb/qD4lEYHCQGHpEXGqy+8X2lFZsak=",
         "owner": "hyprwm",
         "repo": "hyprwayland-scanner",
-        "rev": "f6cf414ca0e16a4d30198fd670ec86df3c89f671",
+        "rev": "0a692d4a645165eebd65f109146b8861e3a925e7",
         "type": "github"
       },
       "original": {
@@ -178,11 +178,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1765741352,
-        "narHash": "sha256-jTJQy1m2XkcZJABajYVP249fCWPl3GbLe3Z8KiQmZqg=",
+        "lastModified": 1772463520,
+        "narHash": "sha256-GIjASzYnV4fK19HnyJKmHyqyxHxIpjusK9foEA4Yo+4=",
         "owner": "hyprwm",
         "repo": "hyprwire",
-        "rev": "b8ca85082fd5c3cdd3d11027492cd0332b517078",
+        "rev": "4e1933ae5602b350c5b6633f5c932549c9b8aca2",
         "type": "github"
       },
       "original": {
@@ -193,11 +193,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1765779637,
-        "narHash": "sha256-KJ2wa/BLSrTqDjbfyNx70ov/HdgNBCBBSQP3BIzKnv4=",
+        "lastModified": 1772433332,
+        "narHash": "sha256-izhTDFKsg6KeVBxJS9EblGeQ8y+O8eCa6RcW874vxEc=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "1306659b587dc277866c7b69eb97e5f07864d8c4",
+        "rev": "cf59864ef8aa2e178cccedbe2c178185b0365705",
         "type": "github"
       },
       "original": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/flake.nix 
new/hyprpaper-0.8.4/flake.nix
--- old/hyprpaper-0.8.3/flake.nix       2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/flake.nix       2026-04-29 22:21:53.000000000 +0200
@@ -58,58 +58,38 @@
     };
   };
 
-  outputs = {
-    self,
-    nixpkgs,
-    systems,
-    ...
-  } @ inputs: let
-    inherit (nixpkgs) lib;
-    eachSystem = lib.genAttrs (import systems);
+  outputs =
+    {
+      self,
+      nixpkgs,
+      systems,
+      ...
+    }@inputs:
+    let
+      inherit (nixpkgs) lib;
+      eachSystem = lib.genAttrs (import systems);
 
-    pkgsFor = eachSystem (system:
-      import nixpkgs {
-        localSystem.system = system;
-        overlays = with self.overlays; [hyprpaper];
+      pkgsFor = eachSystem (
+        system:
+        import nixpkgs {
+          localSystem.system = system;
+          overlays = with self.overlays; [ hyprpaper-with-deps ];
+        }
+      );
+    in
+    {
+      overlays = import ./nix/overlays.nix { inherit inputs lib self; };
+
+      packages = eachSystem (system: {
+        default = self.packages.${system}.hyprpaper;
+        inherit (pkgsFor.${system}) hyprpaper hyprpaper-debug;
       });
-    mkDate = longDate: (lib.concatStringsSep "-" [
-      (builtins.substring 0 4 longDate)
-      (builtins.substring 4 2 longDate)
-      (builtins.substring 6 2 longDate)
-    ]);
-    version = lib.removeSuffix "\n" (builtins.readFile ./VERSION);
-  in {
-    overlays = {
-      default = self.overlays.hyprpaper;
-      hyprpaper = lib.composeManyExtensions [
-        inputs.aquamarine.overlays.default
-        inputs.hyprgraphics.overlays.default
-        inputs.hyprlang.overlays.default
-        inputs.hyprutils.overlays.default
-        inputs.hyprwayland-scanner.overlays.default
-        inputs.hyprtoolkit.overlays.default
-        inputs.hyprwire.overlays.default
-        (final: prev: rec {
-          hyprpaper = final.callPackage ./nix/default.nix {
-            stdenv = final.gcc15Stdenv;
-            version = version + "+date=" + (mkDate (self.lastModifiedDate or 
"19700101")) + "_" + (self.shortRev or "dirty");
-            commit = self.rev or "";
-          };
-          hyprpaper-debug = hyprpaper.override {debug = true;};
-        })
-      ];
-    };
 
-    packages = eachSystem (system: {
-      default = self.packages.${system}.hyprpaper;
-      inherit (pkgsFor.${system}) hyprpaper hyprpaper-debug;
-    });
+      homeManagerModules = {
+        default = self.homeManagerModules.hyprpaper;
+        hyprpaper = builtins.throw "hyprpaper: the flake HM module has been 
removed. Use the module from Home Manager upstream.";
+      };
 
-    homeManagerModules = {
-      default = self.homeManagerModules.hyprpaper;
-      hyprpaper = builtins.throw "hyprpaper: the flake HM module has been 
removed. Use the module from Home Manager upstream.";
+      formatter = eachSystem (system: pkgsFor.${system}.nixfmt-tree);
     };
-
-    formatter = eachSystem (system: pkgsFor.${system}.alejandra);
-  };
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/hw-protocols/hyprpaper_core.xml 
new/hyprpaper-0.8.4/hw-protocols/hyprpaper_core.xml
--- old/hyprpaper-0.8.3/hw-protocols/hyprpaper_core.xml 2026-01-29 
16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/hw-protocols/hyprpaper_core.xml 2026-04-29 
22:21:53.000000000 +0200
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<protocol name="hyprpaper_core" version="1">
+<protocol name="hyprpaper_core" version="2">
   <copyright>
     BSD 3-Clause License
 
@@ -31,7 +31,7 @@
     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   </copyright>
 
-  <object name="hyprpaper_core_manager" version="1">
+  <object name="hyprpaper_core_manager" version="2">
     <description summary="manager object">
       This is the core manager object for hyprpaper operations
     </description>
@@ -62,6 +62,13 @@
         Destroys this object. Children remain alive until destroyed.
       </description>
     </c2s>
+
+    <c2s name="get_status_object" since="2">
+      <description summary="Get a status object">
+        Creates a status object
+      </description>
+      <returns iface="hyprpaper_status"/>
+    </c2s>
   </object>
 
   <enum name="wallpaper_fit_mode">
@@ -136,6 +143,27 @@
     </s2c>
 
     <c2s name="destroy" destructor="true">
+      <description summary="Destroy this object">
+        Destroys this object.
+      </description>
+    </c2s>
+  </object>
+
+  <object name="hyprpaper_status" version="2">
+    <description summary="status object">
+      This is an object which will emit various status updates.
+    </description>
+    
+    <s2c name="active_wallpaper">
+      <description summary="Active wallpaper state">
+        Sends the active wallpaper for a given monitor. This will be emitted
+        immediately after binding, and then every time the path changes.
+      </description>
+      <arg name="monitor" type="varchar" summary="monitor name"/>
+      <arg name="path" type="varchar" summary="wallpaper path"/>
+    </s2c>
+
+    <c2s name="destroy" destructor="true">
       <description summary="Destroy this object">
         Destroys this object.
       </description>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/nix/default.nix 
new/hyprpaper-0.8.4/nix/default.nix
--- old/hyprpaper-0.8.3/nix/default.nix 2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/nix/default.nix 2026-04-29 22:21:53.000000000 +0200
@@ -22,6 +22,7 @@
   libselinux,
   libsepol,
   libthai,
+  libXdmcp,
   libwebp,
   pango,
   pcre,
@@ -30,7 +31,6 @@
   wayland,
   wayland-protocols,
   wayland-scanner,
-  xorg,
   commit,
   debug ? false,
   version ? "git",
@@ -50,10 +50,7 @@
     pkg-config
   ];
 
-  cmakeBuildType =
-    if debug
-    then "Debug"
-    else "Release";
+  cmakeBuildType = if debug then "Debug" else "Release";
 
   nativeBuildInputs = [
     cmake
@@ -83,12 +80,12 @@
     libsepol
     libthai
     libwebp
+    libXdmcp
     pango
     pcre
     pcre2
     wayland
     wayland-protocols
-    xorg.libXdmcp
     util-linux
   ];
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/nix/overlays.nix 
new/hyprpaper-0.8.4/nix/overlays.nix
--- old/hyprpaper-0.8.3/nix/overlays.nix        1970-01-01 01:00:00.000000000 
+0100
+++ new/hyprpaper-0.8.4/nix/overlays.nix        2026-04-29 22:21:53.000000000 
+0200
@@ -0,0 +1,45 @@
+{
+  lib,
+  inputs,
+  self,
+  ...
+}:
+let
+  mkDate =
+    longDate:
+    (lib.concatStringsSep "-" [
+      (builtins.substring 0 4 longDate)
+      (builtins.substring 4 2 longDate)
+      (builtins.substring 6 2 longDate)
+    ]);
+  version = lib.removeSuffix "\n" (builtins.readFile ../VERSION);
+in
+
+{
+  default = self.overlays.hyprpaper;
+
+  hyprpaper-with-deps = lib.composeManyExtensions [
+    inputs.aquamarine.overlays.default
+    inputs.hyprgraphics.overlays.default
+    inputs.hyprlang.overlays.default
+    inputs.hyprutils.overlays.default
+    inputs.hyprwayland-scanner.overlays.default
+    inputs.hyprtoolkit.overlays.default
+    inputs.hyprwire.overlays.default
+    self.overlays.hyprpaper
+  ];
+
+  hyprpaper = final: prev: rec {
+    hyprpaper = final.callPackage ./default.nix {
+      stdenv = final.gcc15Stdenv;
+      version =
+        version
+        + "+date="
+        + (mkDate (self.lastModifiedDate or "19700101"))
+        + "_"
+        + (self.shortRev or "dirty");
+      commit = self.rev or "";
+    };
+    hyprpaper-debug = hyprpaper.override { debug = true; };
+  };
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/src/config/ConfigManager.cpp 
new/hyprpaper-0.8.4/src/config/ConfigManager.cpp
--- old/hyprpaper-0.8.3/src/config/ConfigManager.cpp    2026-01-29 
16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/src/config/ConfigManager.cpp    2026-04-29 
22:21:53.000000000 +0200
@@ -2,6 +2,7 @@
 #include <algorithm>
 #include <filesystem>
 #include <glob.h>
+#include <random>
 #include <hyprlang.hpp>
 #include <hyprutils/path/Path.hpp>
 #include <hyprutils/string/String.hpp>
@@ -63,6 +64,8 @@
     m_config.addSpecialConfigValue("wallpaper", "path", Hyprlang::STRING{""});
     m_config.addSpecialConfigValue("wallpaper", "fit_mode", 
Hyprlang::STRING{"cover"});
     m_config.addSpecialConfigValue("wallpaper", "timeout", Hyprlang::INT{0});
+    m_config.addSpecialConfigValue("wallpaper", "order", 
Hyprlang::STRING{"default"});
+    m_config.addSpecialConfigValue("wallpaper", "recursive", Hyprlang::INT{0});
 
     m_config.registerHandler(&handleSource, "source", 
Hyprlang::SHandlerOptions{});
 
@@ -118,7 +121,7 @@
     return resolvePath(path);
 }
 
-static std::expected<std::vector<std::string>, std::string> getFullPath(const 
std::string& sv) {
+static std::expected<std::vector<std::string>, std::string> getFullPath(const 
std::string& sv, const bool recursive) {
     if (sv.empty())
         return std::unexpected("empty path");
 
@@ -134,14 +137,27 @@
     if (!std::filesystem::exists(resolvedPath))
         return std::unexpected(std::format("File '{}' does not exist", 
resolvedPath));
 
-    if (std::filesystem::is_directory(resolvedPath))
-        for (const auto& entry : 
std::filesystem::directory_iterator(resolvedPath, 
std::filesystem::directory_options::skip_permission_denied)) {
+    if (std::filesystem::is_directory(resolvedPath)) {
+        auto processEntry = [&result](const auto& entry) {
             if (entry.is_regular_file() && isImage(entry.path()))
                 result.push_back(entry.path());
+        };
 
-            if (result.size() >= maxImagesCount)
-                break;
+        if (recursive) {
+            for (const auto& entry :
+                 std::filesystem::recursive_directory_iterator(resolvedPath, 
std::filesystem::directory_options::skip_permission_denied)) {
+                processEntry(entry);
+                if (result.size() >= maxImagesCount)
+                    break;
+            }
+        } else {
+            for (const auto& entry : 
std::filesystem::directory_iterator(resolvedPath, 
std::filesystem::directory_options::skip_permission_denied)) {
+                processEntry(entry);
+                if (result.size() >= maxImagesCount)
+                    break;
+            }
         }
+    }
     else if (isImage(resolvedPath))
         result.push_back(resolvedPath);
     else
@@ -157,20 +173,22 @@
     result.reserve(keys.size());
 
     for (auto& key : keys) {
-        std::string monitor, fitMode, path;
-        int         timeout;
+        std::string monitor, fitMode, path, order;
+        int         timeout, recursive;
 
         try {
             monitor = 
std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("wallpaper", 
"monitor", key.c_str()));
             fitMode = 
std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("wallpaper", 
"fit_mode", key.c_str()));
             path    = 
std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("wallpaper", 
"path", key.c_str()));
             timeout = 
std::any_cast<Hyprlang::INT>(m_config.getSpecialConfigValue("wallpaper", 
"timeout", key.c_str()));
+            order     = 
std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("wallpaper", 
"order", key.c_str()));
+            recursive = 
std::any_cast<Hyprlang::INT>(m_config.getSpecialConfigValue("wallpaper", 
"recursive", key.c_str()));
         } catch (...) {
             g_logger->log(LOG_ERR, "Failed parsing wallpaper for key {}", key);
             continue;
         }
 
-        const auto RESOLVE_PATH = getFullPath(path);
+        const auto RESOLVE_PATH = getFullPath(path, recursive != 0);
 
         if (!RESOLVE_PATH) {
             g_logger->log(LOG_ERR, "Failed to resolve path {}: {}", path, 
RESOLVE_PATH.error());
@@ -182,7 +200,22 @@
             continue;
         }
 
-        result.emplace_back(SSetting{.monitor = std::move(monitor), .fitMode = 
std::move(fitMode), .paths = RESOLVE_PATH.value(), .timeout = timeout});
+        auto resolvedPaths = RESOLVE_PATH.value();
+
+        if (resolvedPaths.size() > 1) {
+            if (order != "default" && order != "random" && order != 
"random-shuffle") {
+                g_logger->log(LOG_WARN, "Invalid order value '{}', falling 
back to default", order);
+                order = "default";
+            }
+
+            if (order == "random" || order == "random-shuffle") {
+                std::random_device rd;
+                std::mt19937       g(rd());
+                std::shuffle(resolvedPaths.begin(), resolvedPaths.end(), g);
+            }
+        }
+
+        result.emplace_back(SSetting{.monitor = std::move(monitor), .fitMode = 
std::move(fitMode), .paths = std::move(resolvedPaths), .order = 
std::move(order), .timeout = timeout});
     }
 
     return result;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/src/config/ConfigManager.hpp 
new/hyprpaper-0.8.4/src/config/ConfigManager.hpp
--- old/hyprpaper-0.8.3/src/config/ConfigManager.hpp    2026-01-29 
16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/src/config/ConfigManager.hpp    2026-04-29 
22:21:53.000000000 +0200
@@ -16,6 +16,7 @@
     struct SSetting {
         std::string              monitor, fitMode;
         std::vector<std::string> paths;
+        std::string              order   = "default";
         int                      timeout = 0;
         uint32_t                 id      = 0;
     };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/src/config/WallpaperMatcher.cpp 
new/hyprpaper-0.8.4/src/config/WallpaperMatcher.cpp
--- old/hyprpaper-0.8.3/src/config/WallpaperMatcher.cpp 2026-01-29 
16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/src/config/WallpaperMatcher.cpp 2026-04-29 
22:21:53.000000000 +0200
@@ -65,6 +65,8 @@
 std::optional<CWallpaperMatcher::rw<const CConfigManager::SSetting>> 
CWallpaperMatcher::matchSetting(const std::string_view& monName, const 
std::string_view& monDesc) {
     // match explicit
     for (const auto& s : m_settings) {
+        if (isWildcard(s.monitor))
+            continue;
         if (s.monitor != monName && !("desc:"s + 
std::string{monDesc}).starts_with(s.monitor))
             continue;
         return s;
@@ -96,7 +98,7 @@
         auto&      activeState = getState(name);
 
         if (!STATE)
-            activeState = {.name = name, .desc = desc};
+            activeState = {.name = name, .desc = desc, .currentID = 
CConfigManager::SETTING_INVALID};
         else {
             activeState.name = name;
             activeState.desc = desc;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/src/ipc/IPC.cpp 
new/hyprpaper-0.8.4/src/ipc/IPC.cpp
--- old/hyprpaper-0.8.3/src/ipc/IPC.cpp 2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/src/ipc/IPC.cpp 2026-04-29 22:21:53.000000000 +0200
@@ -8,7 +8,8 @@
 using namespace IPC;
 using namespace std::string_literals;
 
-constexpr const char*         SOCKET_NAME = ".hyprpaper.sock";
+constexpr const char*         SOCKET_NAME      = ".hyprpaper.sock";
+constexpr const size_t        HP_PROTO_VERSION = 2;
 
 static SP<CHyprpaperCoreImpl> g_coreImpl;
 
@@ -114,7 +115,7 @@
     if (!m_socket)
         return;
 
-    g_coreImpl = makeShared<CHyprpaperCoreImpl>(1, 
[this](SP<Hyprwire::IObject> obj) {
+    g_coreImpl = makeShared<CHyprpaperCoreImpl>(HP_PROTO_VERSION, 
[this](SP<Hyprwire::IObject> obj) {
         auto manager = 
m_managers.emplace_back(makeShared<CHyprpaperCoreManagerObject>(std::move(obj)));
 
         manager->setDestroy([this, weak = 
WP<CHyprpaperCoreManagerObject>{manager}] { std::erase(m_managers, weak); });
@@ -127,6 +128,18 @@
             m_wallpaperObjects.emplace_back(makeShared<CWallpaperObject>(
                 
makeShared<CHyprpaperWallpaperObject>(m_socket->createObject(weak->getObject()->client(),
 weak->getObject(), "hyprpaper_wallpaper", id))));
         });
+
+        manager->setGetStatusObject([this, weak = 
WP<CHyprpaperCoreManagerObject>{manager}](uint32_t id) {
+            if (!weak)
+                return;
+
+            auto x =
+                
m_statusObjects.emplace_back(makeShared<CHyprpaperStatusObject>(m_socket->createObject(weak->getObject()->client(),
 weak->getObject(), "hyprpaper_status", id)));
+
+            for (const auto& m : g_ui->targets()) {
+                x->sendActiveWallpaper(m->m_monitorName.c_str(), 
m->m_lastPath.c_str());
+            }
+        });
     });
 
     m_socket->addImplementation(g_coreImpl);
@@ -145,3 +158,9 @@
         m->sendRemoveMonitor(sv.c_str());
     }
 }
+
+void CSocket::onWallpaperChanged(const std::string& mon, const std::string& 
path) {
+    for (const auto& so : m_statusObjects) {
+        so->sendActiveWallpaper(mon.c_str(), path.c_str());
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/src/ipc/IPC.hpp 
new/hyprpaper-0.8.4/src/ipc/IPC.hpp
--- old/hyprpaper-0.8.3/src/ipc/IPC.hpp 2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/src/ipc/IPC.hpp 2026-04-29 22:21:53.000000000 +0200
@@ -30,6 +30,7 @@
 
         void onNewDisplay(const std::string& sv);
         void onRemovedDisplay(const std::string& sv);
+        void onWallpaperChanged(const std::string& mon, const std::string& 
path);
 
       private:
         SP<Hyprwire::IServerSocket>                  m_socket;
@@ -38,6 +39,7 @@
 
         std::vector<SP<CHyprpaperCoreManagerObject>> m_managers;
         std::vector<SP<CWallpaperObject>>            m_wallpaperObjects;
+        std::vector<SP<CHyprpaperStatusObject>>      m_statusObjects;
 
         friend class CWallpaperObject;
     };
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/src/ui/UI.cpp 
new/hyprpaper-0.8.4/src/ui/UI.cpp
--- old/hyprpaper-0.8.3/src/ui/UI.cpp   2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/src/ui/UI.cpp   2026-04-29 22:21:53.000000000 +0200
@@ -6,6 +6,8 @@
 #include "../ipc/IPC.hpp"
 #include "../config/WallpaperMatcher.hpp"
 
+#include <algorithm>
+#include <random>
 #include <hyprtoolkit/core/Output.hpp>
 
 #include <hyprutils/string/String.hpp>
@@ -24,14 +26,23 @@
 
 class CWallpaperTarget::CImagesData {
   public:
-    CImagesData(Hyprtoolkit::eImageFitMode fitMode, const 
std::vector<std::string>& images, const int timeout = 0) :
-        fitMode(fitMode), images(images), timeout(timeout > 0 ? timeout : 30) 
{}
+    CImagesData(Hyprtoolkit::eImageFitMode fitMode, std::vector<std::string> 
images, const int timeout = 0, std::string order = "default") :
+        fitMode(fitMode), images(std::move(images)), order(std::move(order)), 
timeout(timeout > 0 ? timeout : 30) {}
 
     const Hyprtoolkit::eImageFitMode fitMode;
-    const std::vector<std::string>   images;
+    std::vector<std::string>         images;
+    const std::string                order;
     const int                        timeout;
 
     std::string                      nextImage() {
+        if (order == "random-shuffle" && current + 1 >= images.size()) {
+            std::random_device rd;
+            std::mt19937       g(rd());
+            std::shuffle(images.begin(), images.end(), g);
+            current = 0;
+            return images[current];
+        }
+
         current = (current + 1) % images.size();
         return images[current];
     }
@@ -41,7 +52,7 @@
 };
 
 CWallpaperTarget::CWallpaperTarget(SP<Hyprtoolkit::IBackend> backend, 
SP<Hyprtoolkit::IOutput> output, const std::vector<std::string>& path, 
Hyprtoolkit::eImageFitMode fitMode,
-                                   const int timeout) : 
m_monitorName(output->port()), m_backend(backend) {
+                                   const int timeout, const std::string& 
order) : m_monitorName(output->port()), m_backend(backend) {
     static const auto SPLASH_REPLY = HyprlandSocket::getFromSocket("/splash");
 
     static const auto PENABLESPLASH = 
Hyprlang::CSimpleConfigValue<Hyprlang::INT>(g_config->hyprlang(), "splash");
@@ -73,11 +84,13 @@
                   ->fitMode(fitMode)
                   ->commence();
 
+    m_lastPath = path.front();
+
     m_image->setPositionMode(Hyprtoolkit::IElement::HT_POSITION_ABSOLUTE);
     m_image->setPositionFlag(Hyprtoolkit::IElement::HT_POSITION_FLAG_CENTER, 
true);
 
     if (path.size() > 1) {
-        m_imagesData = makeUnique<CImagesData>(fitMode, path, timeout);
+        m_imagesData = makeUnique<CImagesData>(fitMode, 
std::vector<std::string>(path), timeout, order);
         m_timer =
             
m_backend->addTimer(std::chrono::milliseconds(std::chrono::seconds(m_imagesData->timeout)),
 [this](ASP<Hyprtoolkit::CTimer> self, void*) { onRepeatTimer(); }, nullptr);
     }
@@ -115,8 +128,10 @@
 
     ASSERT(m_imagesData);
 
+    m_lastPath = m_imagesData->nextImage();
+
     m_image->rebuild()
-        ->path(m_imagesData->nextImage())
+        ->path(std::string{m_lastPath})
         ->size({Hyprtoolkit::CDynamicSize::HT_SIZE_PERCENT, 
Hyprtoolkit::CDynamicSize::HT_SIZE_PERCENT, {1.F, 1.F}})
         ->sync(true)
         ->fitMode(m_imagesData->fitMode)
@@ -124,6 +139,8 @@
 
     m_timer =
         
m_backend->addTimer(std::chrono::milliseconds(std::chrono::seconds(m_imagesData->timeout)),
 [this](ASP<Hyprtoolkit::CTimer> self, void*) { onRepeatTimer(); }, nullptr);
+
+    IPC::g_IPCSocket->onWallpaperChanged(m_monitorName, m_lastPath);
 }
 
 void CUI::registerOutput(const SP<Hyprtoolkit::IOutput>& mon) {
@@ -222,5 +239,9 @@
 
     std::erase_if(m_targets, [&mon](const auto& e) { return e->m_monitorName 
== mon->port(); });
 
-    m_targets.emplace_back(makeShared<CWallpaperTarget>(m_backend, mon, 
TARGET->get().paths, toFitMode(TARGET->get().fitMode), TARGET->get().timeout));
+    m_targets.emplace_back(makeShared<CWallpaperTarget>(m_backend, mon, 
TARGET->get().paths, toFitMode(TARGET->get().fitMode), TARGET->get().timeout, 
TARGET->get().order));
+}
+
+const std::vector<SP<CWallpaperTarget>>& CUI::targets() {
+    return m_targets;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hyprpaper-0.8.3/src/ui/UI.hpp 
new/hyprpaper-0.8.4/src/ui/UI.hpp
--- old/hyprpaper-0.8.3/src/ui/UI.hpp   2026-01-29 16:50:46.000000000 +0100
+++ new/hyprpaper-0.8.4/src/ui/UI.hpp   2026-04-29 22:21:53.000000000 +0200
@@ -17,14 +17,14 @@
 class CWallpaperTarget {
   public:
     CWallpaperTarget(SP<Hyprtoolkit::IBackend> backend, 
SP<Hyprtoolkit::IOutput> output, const std::vector<std::string>& path,
-                     Hyprtoolkit::eImageFitMode fitMode = 
Hyprtoolkit::IMAGE_FIT_MODE_COVER, const int timeout = 0);
+                     Hyprtoolkit::eImageFitMode fitMode = 
Hyprtoolkit::IMAGE_FIT_MODE_COVER, const int timeout = 0, const std::string& 
order = "default");
     ~CWallpaperTarget();
 
     CWallpaperTarget(const CWallpaperTarget&) = delete;
     CWallpaperTarget(CWallpaperTarget&)       = delete;
     CWallpaperTarget(CWallpaperTarget&&)      = delete;
 
-    std::string m_monitorName;
+    std::string m_monitorName, m_lastPath;
 
   private:
     void onRepeatTimer();
@@ -46,8 +46,9 @@
     CUI();
     ~CUI();
 
-    bool                      run();
-    SP<Hyprtoolkit::IBackend> backend();
+    bool                                     run();
+    SP<Hyprtoolkit::IBackend>                backend();
+    const std::vector<SP<CWallpaperTarget>>& targets();
 
   private:
     void                              targetChanged(const 
SP<Hyprtoolkit::IOutput>& mon);

Reply via email to