Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package hypridle for openSUSE:Factory 
checked in at 2026-08-01 18:31:31
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/hypridle (Old)
 and      /work/SRC/openSUSE:Factory/.hypridle.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "hypridle"

Sat Aug  1 18:31:31 2026 rev:5 rq:1368701 version:0.1.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/hypridle/hypridle.changes        2025-09-22 
16:41:43.562570005 +0200
+++ /work/SRC/openSUSE:Factory/.hypridle.new.16738/hypridle.changes     
2026-08-01 18:34:30.190514853 +0200
@@ -1,0 +2,12 @@
+Thu Jul 30 19:01:58 UTC 2026 - Nassim Lhadj <[email protected]>
+
+- Update to version 0.1.8:
+  * core: fix dbus inhibit lock counting
+  * nix: remove sdbus-cpp overlay
+  * core: don't skip on-resume when on-timeout already fired
+  * Fix: allow hypridle -c to run without default conf
+  * config: update dpms commands to lua syntax
+  * core: implement GetActive and ActiveChanged on dbus service
+  * core: add per-listener condition_cmd with retry
+
+-------------------------------------------------------------------

Old:
----
  hypridle-0.1.7.obscpio

New:
----
  hypridle-0.1.8.obscpio

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

Other differences:
------------------
++++++ hypridle.spec ++++++
--- /var/tmp/diff_new_pack.gTh1vu/_old  2026-08-01 18:34:32.046578755 +0200
+++ /var/tmp/diff_new_pack.gTh1vu/_new  2026-08-01 18:34:32.050578892 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package hypridle
 #
-# Copyright (c) 2025 SUSE LLC and contributors
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           hypridle
-Version:        0.1.7
+Version:        0.1.8
 Release:        0
 Summary:        Hyprland's idle daemon
 License:        BSD-3-Clause

++++++ hypridle-0.1.7.obscpio -> hypridle-0.1.8.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/.github/workflows/nix.yml 
new/hypridle-0.1.8/.github/workflows/nix.yml
--- old/hypridle-0.1.7/.github/workflows/nix.yml        2025-08-27 
12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/.github/workflows/nix.yml        2026-07-26 
16:44:59.000000000 +0200
@@ -1,48 +1,11 @@
 name: Build
 
 on: [push, pull_request, workflow_dispatch]
+
 jobs:
   nix:
-    runs-on: ubuntu-latest
-    steps:
-    - uses: actions/checkout@v3
-
-    - 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
-
-    # not needed (yet)
-    # - uses: cachix/cachix-action@v12
-    #   with:
-    #     name: hyprland
-    #     authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
-
-    - name: Build
-      run: nix flake check --print-build-logs --keep-going
-
+    if: (github.event_name != 'pull_request' || 
github.event.pull_request.head.repo.fork)
+    uses: hyprwm/actions/.github/workflows/nix.yml@main
+    secrets: inherit
+    with:
+      command: nix build --print-build-logs --keep-going
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/README.md new/hypridle-0.1.8/README.md
--- old/hypridle-0.1.7/README.md        2025-08-27 12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/README.md        2026-07-26 16:44:59.000000000 +0200
@@ -25,6 +25,8 @@
     timeout = 500                            # in seconds
     on-timeout = notify-send "You are idle!" # command to run when timeout has 
passed
     on-resume = notify-send "Welcome back!"  # command to run when activity is 
detected after timeout has fired.
+    condition_cmd =                          # if set, run this command before 
on-timeout. Exit 0 = proceed, non-zero = defer
+    condition_retry = 0                      # retry interval in seconds when 
condition_cmd defers (default: 0, no retry)
 }
 ```
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/VERSION new/hypridle-0.1.8/VERSION
--- old/hypridle-0.1.7/VERSION  2025-08-27 12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/VERSION  2026-07-26 16:44:59.000000000 +0200
@@ -1 +1 @@
-0.1.7
+0.1.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/assets/example.conf 
new/hypridle-0.1.8/assets/example.conf
--- old/hypridle-0.1.7/assets/example.conf      2025-08-27 12:40:01.000000000 
+0200
+++ new/hypridle-0.1.8/assets/example.conf      2026-07-26 16:44:59.000000000 
+0200
@@ -2,9 +2,9 @@
 # for more configuration options, refer 
https://wiki.hyprland.org/Hypr-Ecosystem/hypridle
 
 general {
-    lock_cmd = pidof hyprlock || hyprlock       # avoid starting multiple 
hyprlock instances.
-    before_sleep_cmd = loginctl lock-session    # lock before suspend.
-    after_sleep_cmd = hyprctl dispatch dpms on  # to avoid having to press a 
key twice to turn on the display.
+    lock_cmd = pidof hyprlock || hyprlock                             # avoid 
starting multiple hyprlock instances.
+    before_sleep_cmd = loginctl lock-session                          # lock 
before suspend.
+    after_sleep_cmd = hyprctl dispatch 'hl.dsp.dpms({action = "on"})' # turn 
on screen w/o key press after resume.
 }
 
 listener {
@@ -26,9 +26,9 @@
 }
 
 listener {
-    timeout = 330                                 # 5.5min.
-    on-timeout = hyprctl dispatch dpms off        # screen off when timeout 
has passed.
-    on-resume = hyprctl dispatch dpms on          # screen on when activity is 
detected after timeout has fired.
+    timeout = 330                                                 # 5.5min.
+    on-timeout = hyprctl dispatch 'hl.dsp.dpms({action = "off"})' # screen off 
when timeout has passed.
+    on-resume = hyprctl dispatch 'hl.dsp.dpms({action = "on"})'   # screen on 
when activity is detected.
 }
 
 listener {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/flake.lock 
new/hypridle-0.1.8/flake.lock
--- old/hypridle-0.1.7/flake.lock       2025-08-27 12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/flake.lock       2026-07-26 16:44:59.000000000 +0200
@@ -10,11 +10,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749046714,
-        "narHash": "sha256-kymV5FMnddYGI+UjwIw8ceDjdeg7ToDVjbHCvUlhn14=",
+        "lastModified": 1772460177,
+        "narHash": "sha256-/6G/MsPvtn7bc4Y32pserBT/Z4SUUdBd4XYJpOEKVR4=",
         "owner": "hyprwm",
         "repo": "hyprland-protocols",
-        "rev": "613878cb6f459c5e323aaafe1e6f388ac8a36330",
+        "rev": "1cb6db5fd6bb8aee419f4457402fa18293ace917",
         "type": "github"
       },
       "original": {
@@ -36,11 +36,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749145882,
-        "narHash": "sha256-qr0KXeczF8Sma3Ae7+dR2NHhvG7YeLBJv19W4oMu6ZE=",
+        "lastModified": 1772459629,
+        "narHash": "sha256-/iwvNUYShmmnwmz/czEUh6+0eF5vCMv0xtDW0STPIuM=",
         "owner": "hyprwm",
         "repo": "hyprlang",
-        "rev": "1bfb84f54d50c7ae6558c794d3cfd5f6a7e6e676",
+        "rev": "7615ee388de18239a4ab1400946f3d0e498a8186",
         "type": "github"
       },
       "original": {
@@ -59,11 +59,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749135356,
-        "narHash": "sha256-Q8mAKMDsFbCEuq7zoSlcTuxgbIBVhfIYpX0RjE32PS0=",
+        "lastModified": 1772459870,
+        "narHash": "sha256-xxkK2Cvqxpf/4UGcJ/TyCwrvmiNWsKsJfFzHMp2bxis=",
         "owner": "hyprwm",
         "repo": "hyprutils",
-        "rev": "e36db00dfb3a3d3fdcc4069cb292ff60d2699ccb",
+        "rev": "e63f3a79334dec49f8eb1691f66f18115df04085",
         "type": "github"
       },
       "original": {
@@ -82,11 +82,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1749145760,
-        "narHash": "sha256-IHaGWpGrv7seFWdw/1A+wHtTsPlOGIKMrk1TUIYJEFI=",
+        "lastModified": 1772459835,
+        "narHash": "sha256-978jRz/y/9TKmZb/qD4lEYHCQGHpEXGqy+8X2lFZsak=",
         "owner": "hyprwm",
         "repo": "hyprwayland-scanner",
-        "rev": "817918315ea016cc2d94004bfb3223b5fd9dfcc6",
+        "rev": "0a692d4a645165eebd65f109146b8861e3a925e7",
         "type": "github"
       },
       "original": {
@@ -97,11 +97,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1748929857,
-        "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=",
+        "lastModified": 1772198003,
+        "narHash": "sha256-I45esRSssFtJ8p/gLHUZ1OUaaTaVLluNkABkk6arQwE=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4",
+        "rev": "dd9b079222d43e1943b6ebd802f04fd959dc8e61",
         "type": "github"
       },
       "original": {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/flake.nix new/hypridle-0.1.8/flake.nix
--- old/hypridle-0.1.7/flake.nix        2025-08-27 12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/flake.nix        2026-07-26 16:44:59.000000000 +0200
@@ -31,35 +31,40 @@
     };
   };
 
-  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; [default];
+  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; [ hypridle-with-deps ];
+        }
+      );
+    in
+    {
+      overlays = import ./nix/overlays.nix { inherit inputs lib self; };
+
+      packages = eachSystem (system: {
+        default = self.packages.${system}.hypridle;
+        inherit (pkgsFor.${system}) hypridle;
       });
-  in {
-    overlays = import ./nix/overlays.nix {inherit inputs lib;};
 
-    packages = eachSystem (system: {
-      default = self.packages.${system}.hypridle;
-      inherit (pkgsFor.${system}) hypridle;
-    });
-
-    homeManagerModules = {
-      default = self.homeManagerModules.hypridle;
-      hypridle = builtins.throw "hypridle: the flake HM module has been 
removed. Use the module from Home Manager upstream.";
-    };
+      homeManagerModules = {
+        default = self.homeManagerModules.hypridle;
+        hypridle = builtins.throw "hypridle: the flake HM module has been 
removed. Use the module from Home Manager upstream.";
+      };
 
-    checks = eachSystem (system: self.packages.${system});
+      checks = eachSystem (system: self.packages.${system});
 
-    formatter = eachSystem (system: pkgsFor.${system}.alejandra);
-  };
+      formatter = eachSystem (system: pkgsFor.${system}.nixfmt-tree);
+    };
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/nix/default.nix 
new/hypridle-0.1.8/nix/default.nix
--- old/hypridle-0.1.7/nix/default.nix  2025-08-27 12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/nix/default.nix  2026-07-26 16:44:59.000000000 +0200
@@ -6,7 +6,7 @@
   hyprwayland-scanner,
   lib,
   pkg-config,
-  sdbus-cpp,
+  sdbus-cpp_2,
   stdenv,
   systemd,
   wayland,
@@ -30,7 +30,7 @@
     hyprland-protocols
     hyprlang
     hyprutils
-    sdbus-cpp
+    sdbus-cpp_2
     systemd
     wayland
     wayland-protocols
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/nix/overlays.nix 
new/hypridle-0.1.8/nix/overlays.nix
--- old/hypridle-0.1.7/nix/overlays.nix 2025-08-27 12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/nix/overlays.nix 2026-07-26 16:44:59.000000000 +0200
@@ -1,42 +1,41 @@
 {
   lib,
   inputs,
-}: let
-  mkDate = longDate: (lib.concatStringsSep "-" [
-    (builtins.substring 0 4 longDate)
-    (builtins.substring 4 2 longDate)
-    (builtins.substring 6 2 longDate)
-  ]);
+  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 {
+in
+{
   default = inputs.self.overlays.hypridle;
 
-  hypridle = lib.composeManyExtensions [
+  hypridle-with-deps = lib.composeManyExtensions [
     inputs.hyprland-protocols.overlays.default
     inputs.hyprlang.overlays.default
     inputs.hyprutils.overlays.default
     inputs.hyprwayland-scanner.overlays.default
-    inputs.self.overlays.sdbuscpp
-    (final: prev: {
-      hypridle = prev.callPackage ./default.nix {
-        stdenv = prev.gcc15Stdenv;
-        version = version + "+date=" + (mkDate (inputs.self.lastModifiedDate 
or "19700101")) + "_" + (inputs.self.shortRev or "dirty");
-        inherit (final) hyprlang;
-      };
-    })
+    self.overlays.hypridle
   ];
 
-  sdbuscpp = final: prev: {
-    sdbus-cpp = prev.sdbus-cpp.overrideAttrs (self: super: {
-      version = "2.0.0";
-
-      src = final.fetchFromGitHub {
-        owner = "Kistler-group";
-        repo = "sdbus-cpp";
-        rev = "refs/tags/v${self.version}";
-        hash = "sha256-W8V5FRhV3jtERMFrZ4gf30OpIQLYoj2yYGpnYOmH2+g=";
-      };
-    });
+  hypridle = final: prev: {
+    hypridle = prev.callPackage ./default.nix {
+      stdenv = prev.gcc15Stdenv;
+      version =
+        version
+        + "+date="
+        + (mkDate (inputs.self.lastModifiedDate or "19700101"))
+        + "_"
+        + (inputs.self.shortRev or "dirty");
+      inherit (final) hyprlang;
+    };
   };
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/src/config/ConfigManager.cpp 
new/hypridle-0.1.8/src/config/ConfigManager.cpp
--- old/hypridle-0.1.7/src/config/ConfigManager.cpp     2025-08-27 
12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/src/config/ConfigManager.cpp     2026-07-26 
16:44:59.000000000 +0200
@@ -5,19 +5,41 @@
 #include <filesystem>
 #include <glob.h>
 #include <cstring>
+#include <expected>
+
+static std::expected<std::string, std::error_code> getMainConfigPath(const 
std::string& overridePath = "") {
+    namespace fs = std::filesystem;
+
+    if (!overridePath.empty()) {
+        std::error_code ec;
+        if (!fs::exists(overridePath, ec))
+            return 
std::unexpected(std::make_error_code(std::errc::no_such_file_or_directory));
+        return overridePath;
+    }
 
-static std::string getMainConfigPath() {
     static const auto paths = Hyprutils::Path::findConfig("hypridle");
+
     if (paths.first.has_value())
         return paths.first.value();
-    else
-        throw std::runtime_error("Could not find config in HOME, 
XDG_CONFIG_HOME, XDG_CONFIG_DIRS or /etc/hypr.");
+
+    return 
std::unexpected(std::make_error_code(std::errc::no_such_file_or_directory));
 }
 
 CConfigManager::CConfigManager(std::string configPath) :
-    m_config(configPath.empty() ? getMainConfigPath().c_str() : 
configPath.c_str(), Hyprlang::SConfigOptions{.throwAllErrors = true, 
.allowMissingConfig = false}) {
-    ;
-    configCurrentPath = configPath.empty() ? getMainConfigPath() : configPath;
+    /* allowMissingConfig = 'true' to avoid library-level exceptions during 
initialization.
+    Existence is guaranteed by the path check below. */
+    m_config(getMainConfigPath(configPath).value_or("").c_str(),
+             Hyprlang::SConfigOptions{.throwAllErrors = false, 
.allowMissingConfig = true})
+{
+    auto pathResult = getMainConfigPath(configPath);
+
+    if (!pathResult)
+        return;
+
+    configCurrentPath = *pathResult;
+    configHeadPath    = configCurrentPath;
+
+    Debug::log(LOG, "Using config file: {}", configCurrentPath);
 }
 
 static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
@@ -38,6 +60,8 @@
     m_config.addSpecialConfigValue("listener", "on-timeout", 
Hyprlang::STRING{""});
     m_config.addSpecialConfigValue("listener", "on-resume", 
Hyprlang::STRING{""});
     m_config.addSpecialConfigValue("listener", "ignore_inhibit", 
Hyprlang::INT{0});
+    m_config.addSpecialConfigValue("listener", "condition_cmd", 
Hyprlang::STRING{""});
+    m_config.addSpecialConfigValue("listener", "condition_retry", 
Hyprlang::INT{0});
 
     m_config.addConfigValue("general:lock_cmd", Hyprlang::STRING{""});
     m_config.addConfigValue("general:unlock_cmd", Hyprlang::STRING{""});
@@ -51,8 +75,7 @@
     m_config.addConfigValue("general:inhibit_sleep", Hyprlang::INT{2});
 
     // track the file in the circular dependency chain
-    const auto mainConfigPath = getMainConfigPath();
-    
alreadyIncludedSourceFiles.insert(std::filesystem::canonical(mainConfigPath));
+    
alreadyIncludedSourceFiles.insert(std::filesystem::canonical(configHeadPath));
 
     m_config.registerHandler(&::handleSource, "source", {.allowFlags = false});
 
@@ -88,6 +111,8 @@
         rule.onResume  = 
std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", 
"on-resume", k.c_str()));
 
         rule.ignoreInhibit = 
std::any_cast<Hyprlang::INT>(m_config.getSpecialConfigValue("listener", 
"ignore_inhibit", k.c_str()));
+        rule.conditionCmd  = 
std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", 
"condition_cmd", k.c_str()));
+        rule.conditionRetry = 
std::any_cast<Hyprlang::INT>(m_config.getSpecialConfigValue("listener", 
"condition_retry", k.c_str()));
 
         if (timeout == -1) {
             result.setError("Category has a missing timeout setting");
@@ -98,8 +123,8 @@
     }
 
     for (auto& r : m_vRules) {
-        Debug::log(LOG, "Registered timeout rule for {}s:\n      on-timeout: 
{}\n      on-resume: {}\n      ignore_inhibit: {}", r.timeout, r.onTimeout, 
r.onResume,
-                   r.ignoreInhibit);
+        Debug::log(LOG, "Registered timeout rule for {}s:\n      on-timeout: 
{}\n      on-resume: {}\n      ignore_inhibit: {}\n      condition_cmd: {}\n    
  condition_retry: {}",
+                   r.timeout, r.onTimeout, r.onResume, r.ignoreInhibit, 
r.conditionCmd, r.conditionRetry);
     }
 
     return result;
@@ -110,9 +135,9 @@
 }
 
 std::optional<std::string> CConfigManager::handleSource(const std::string& 
command, const std::string& rawpath) {
-    if (rawpath.length() < 2) {
+    if (rawpath.length() < 2)
         return "source path " + rawpath + " bogus!";
-    }
+
     std::unique_ptr<glob_t, void (*)(glob_t*)> glob_buf{new glob_t, [](glob_t* 
g) { globfree(g); }};
     memset(glob_buf.get(), 0, sizeof(glob_t));
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/src/config/ConfigManager.hpp 
new/hypridle-0.1.8/src/config/ConfigManager.hpp
--- old/hypridle-0.1.7/src/config/ConfigManager.hpp     2025-08-27 
12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/src/config/ConfigManager.hpp     2026-07-26 
16:44:59.000000000 +0200
@@ -14,15 +14,17 @@
     void init();
 
     struct STimeoutRule {
-        uint64_t    timeout       = 0;
-        std::string onTimeout     = "";
-        std::string onResume      = "";
-        bool        ignoreInhibit = false;
+        uint64_t    timeout        = 0;
+        std::string onTimeout      = "";
+        std::string onResume       = "";
+        bool        ignoreInhibit  = false;
+        std::string conditionCmd   = "";
+        int64_t     conditionRetry = 0;
     };
 
     std::vector<STimeoutRule>  getRules();
     std::optional<std::string> handleSource(const std::string&, const 
std::string&);
-    std::string                configCurrentPath;
+    std::string                configCurrentPath, configHeadPath;
     std::set<std::string>      alreadyIncludedSourceFiles;
 
     template <typename T>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/src/core/Hypridle.cpp 
new/hypridle-0.1.8/src/core/Hypridle.cpp
--- old/hypridle-0.1.7/src/core/Hypridle.cpp    2025-08-27 12:40:01.000000000 
+0200
+++ new/hypridle-0.1.8/src/core/Hypridle.cpp    2026-07-26 16:44:59.000000000 
+0200
@@ -65,9 +65,11 @@
     for (size_t i = 0; i < RULES.size(); ++i) {
         auto&       l   = m_sWaylandIdleState.listeners[i];
         const auto& r   = RULES[i];
-        l.onRestore     = r.onResume;
-        l.onTimeout     = r.onTimeout;
-        l.ignoreInhibit = r.ignoreInhibit;
+        l.onRestore      = r.onResume;
+        l.onTimeout      = r.onTimeout;
+        l.ignoreInhibit  = r.ignoreInhibit;
+        l.conditionCmd   = r.conditionCmd;
+        l.conditionRetry = r.conditionRetry;
 
         if (*IGNOREWAYLANDINHIBIT || r.ignoreInhibit)
             l.notification =
@@ -142,6 +144,26 @@
     enterEventLoop();
 }
 
+static int64_t nowMonotonic() {
+    return 
std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
+}
+
+static bool runConditionCmd(const std::string& cmd) {
+    Debug::log(LOG, "Running condition_cmd: {}", cmd);
+
+    Hyprutils::OS::CProcess proc("/bin/sh", {"-c", cmd});
+    if (!proc.runSync()) {
+        Debug::log(ERR, "Failed to run condition_cmd: {}", cmd);
+        return false;
+    }
+
+    const int exitCode = proc.exitCode();
+    Debug::log(LOG, "condition_cmd exited with {}", exitCode);
+    return exitCode == 0;
+}
+
+static void spawn(const std::string& args);
+
 void CHypridle::enterEventLoop() {
 
     nfds_t pollfdsCount = m_sDBUSState.screenSaverServiceConnection ? 3 : 2;
@@ -196,7 +218,7 @@
 
         std::unique_lock lk(m_sEventLoopInternals.loopMutex);
         if (!m_sEventLoopInternals.shouldProcess) // avoid a lock if a thread 
managed to request something already since we .unlock()ed
-            m_sEventLoopInternals.loopSignal.wait(lk, [this] { return 
m_sEventLoopInternals.shouldProcess == true; }); // wait for events
+            m_sEventLoopInternals.loopSignal.wait_for(lk, 
std::chrono::seconds(5), [this] { return m_sEventLoopInternals.shouldProcess == 
true; }); // wait for events or timeout (for condition_cmd retries)
 
         m_sEventLoopInternals.loopRequestMutex.lock(); // lock incoming events
 
@@ -238,6 +260,24 @@
             ret = wl_display_dispatch_pending(m_sWaylandState.display);
             wl_display_flush(m_sWaylandState.display);
         } while (ret > 0);
+
+        // Check condition_cmd retries for pending listeners
+        const auto now = nowMonotonic();
+        for (auto& l : m_sWaylandIdleState.listeners) {
+            if (!l.conditionPending || now < l.conditionRetryAt)
+                continue;
+
+            Debug::log(LOG, "Retrying condition_cmd for rule {:x}", 
(uintptr_t)&l);
+            if (runConditionCmd(l.conditionCmd)) {
+                l.conditionPending = false;
+                l.onTimeoutFired = true;
+                Debug::log(LOG, "Condition met, running {}", l.onTimeout);
+                spawn(l.onTimeout);
+            } else {
+                l.conditionRetryAt = now + l.conditionRetry;
+                Debug::log(LOG, "Condition still not met, retrying in {}s", 
l.conditionRetry);
+            }
+        }
     }
 
     Debug::log(ERR, "[core] Terminated");
@@ -268,18 +308,49 @@
         return;
     }
 
+    // Check condition_cmd before firing on-timeout
+    if (!pListener->conditionCmd.empty()) {
+        if (!runConditionCmd(pListener->conditionCmd)) {
+            if (pListener->conditionRetry > 0) {
+                Debug::log(LOG, "condition_cmd blocked on-timeout, retrying in 
{}s", pListener->conditionRetry);
+                pListener->conditionPending = true;
+                pListener->conditionRetryAt = nowMonotonic() + 
pListener->conditionRetry;
+            } else {
+                Debug::log(LOG, "condition_cmd blocked on-timeout, no retry 
configured");
+            }
+            return;
+        }
+    }
+
     Debug::log(LOG, "Running {}", pListener->onTimeout);
+    pListener->onTimeoutFired = true;
     spawn(pListener->onTimeout);
 }
 
 void CHypridle::onResumed(SIdleListener* pListener) {
     Debug::log(LOG, "Resumed: rule {:x}", (uintptr_t)pListener);
     isIdled = false;
-    if (g_pHypridle->m_iInhibitLocks > 0 && !pListener->ignoreInhibit) {
-        Debug::log(LOG, "Ignoring from onResumed(), inhibit locks: {}", 
g_pHypridle->m_iInhibitLocks);
+
+    // Any input means the user is no longer idle for *any* rule, so cancel all
+    // pending condition retries, not just this listener's. Per-listener 
clearing
+    // is insufficient: onInhibit() destroys and recreates idle notifications 
when
+    // the inhibit count drops to 0 while idle (e.g. a media player toggling 
the
+    // screensaver inhibit). That orphans a long-timeout rule's pending retry 
--
+    // its old notification is gone, and the recreated one won't fire resume 
until
+    // a fresh full timeout elapses, which never happens if the user stays 
active.
+    // The retry then waits on conditionPending alone and fires when the 
condition
+    // finally clears, despite continuous input. Clearing all on any resume 
fixes it.
+    for (auto& l : m_sWaylandIdleState.listeners)
+        l.conditionPending = false;
+
+    // If on-timeout never actually executed (was inhibited), skip on-resume 
too
+    if (!pListener->onTimeoutFired) {
+        Debug::log(LOG, "Skipping onResumed: onTimeout was inhibited for rule 
{:x}", (uintptr_t)pListener);
         return;
     }
 
+    pListener->onTimeoutFired = false;
+
     if (pListener->onRestore.empty()) {
         Debug::log(LOG, "Ignoring, onRestore is empty.");
         return;
@@ -332,6 +403,14 @@
     if (!std::string{*LOCKCMD}.empty())
         spawn(*LOCKCMD);
 
+    if (m_sDBUSState.screenSaverObjects.size() > 0) {
+        auto obj = m_sDBUSState.screenSaverObjects[0].get();
+
+        obj->emitSignal("ActiveChanged")
+            .onInterface("org.freedesktop.ScreenSaver")
+            .withArguments(true);
+    }
+
     if (m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY)
         uninhibitSleep();
 }
@@ -340,6 +419,14 @@
     Debug::log(LOG, "Wayland session got unlocked");
     m_isLocked = false;
 
+    if (m_sDBUSState.screenSaverObjects.size() > 0) {
+        auto obj = m_sDBUSState.screenSaverObjects[0].get();
+
+        obj->emitSignal("ActiveChanged")
+            .onInterface("org.freedesktop.ScreenSaver")
+            .withArguments(false);
+    }
+
     if (m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY)
         inhibitSleep();
 
@@ -371,15 +458,8 @@
     return true;
 }
 
-bool CHypridle::unregisterDbusInhibitCookies(const std::string& ownerID) {
-    const auto IT = std::remove_if(m_sDBUSState.inhibitCookies.begin(), 
m_sDBUSState.inhibitCookies.end(),
-                                   [&ownerID](const 
CHypridle::SDbusInhibitCookie& item) { return item.ownerID == ownerID; });
-
-    if (IT == m_sDBUSState.inhibitCookies.end())
-        return false;
-
-    m_sDBUSState.inhibitCookies.erase(IT, m_sDBUSState.inhibitCookies.end());
-    return true;
+size_t CHypridle::unregisterDbusInhibitCookies(const std::string& ownerID) {
+    return std::erase_if(m_sDBUSState.inhibitCookies, [&ownerID](const 
CHypridle::SDbusInhibitCookie& item) { return item.ownerID == ownerID; });
 }
 
 static void handleDbusLogin(sdbus::Message msg) {
@@ -461,6 +541,7 @@
 
 static uint32_t handleDbusScreensaver(std::string app, std::string reason, 
uint32_t cookie, bool inhibit, const char* sender) {
     std::string ownerID = sender;
+    bool cookieFound = false;
 
     if (!inhibit) {
         Debug::log(TRACE, "Read uninhibit cookie: {}", cookie);
@@ -471,6 +552,7 @@
             app     = COOKIE.app;
             reason  = COOKIE.reason;
             ownerID = COOKIE.ownerID;
+            cookieFound = true;
 
             if (!g_pHypridle->unregisterDbusInhibitCookie(COOKIE))
                 Debug::log(WARN, "BUG THIS: attempted to unregister unknown 
cookie");
@@ -481,7 +563,7 @@
 
     if (inhibit)
         g_pHypridle->onInhibit(true);
-    else
+    else if (cookieFound)
         g_pHypridle->onInhibit(false);
 
     static uint32_t cookieID = 1337;
@@ -506,9 +588,11 @@
     if (!newOwner.empty())
         return;
 
-    if (g_pHypridle->unregisterDbusInhibitCookies(oldOwner)) {
+    size_t removed = g_pHypridle->unregisterDbusInhibitCookies(oldOwner);
+    if (removed > 0) {
         Debug::log(LOG, "App with owner {} disconnected", oldOwner);
-        g_pHypridle->onInhibit(false);
+        for (size_t i = 0; i < removed; i++)
+            g_pHypridle->onInhibit(false);
     }
 }
 
@@ -558,7 +642,12 @@
                        }),
                                    
sdbus::registerMethod("UnInhibit").implementedAs([object = obj.get()](uint32_t 
c) {
                                        handleDbusScreensaver("", "", c, false, 
object->getCurrentlyProcessedMessage().getSender());
-                                   }))
+                                   }),
+                                   
sdbus::registerMethod("GetActive").implementedAs([]() {
+                                       return g_pHypridle->m_isLocked;
+                                   }),
+                                   
sdbus::registerSignal("ActiveChanged").withParameters<bool>()
+                                )
                         
.forInterface(sdbus::InterfaceName{"org.freedesktop.ScreenSaver"});
 
                     m_sDBUSState.screenSaverObjects.push_back(std::move(obj));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/src/core/Hypridle.hpp 
new/hypridle-0.1.8/src/core/Hypridle.hpp
--- old/hypridle-0.1.7/src/core/Hypridle.hpp    2025-08-27 12:40:01.000000000 
+0200
+++ new/hypridle-0.1.8/src/core/Hypridle.hpp    2026-07-26 16:44:59.000000000 
+0200
@@ -17,10 +17,15 @@
     CHypridle();
 
     struct SIdleListener {
-        SP<CCExtIdleNotificationV1> notification  = nullptr;
-        std::string                 onTimeout     = "";
-        std::string                 onRestore     = "";
-        bool                        ignoreInhibit = false;
+        SP<CCExtIdleNotificationV1> notification      = nullptr;
+        std::string                 onTimeout         = "";
+        std::string                 onRestore         = "";
+        bool                        ignoreInhibit     = false;
+        bool                        onTimeoutFired    = false;
+        std::string                 conditionCmd      = "";
+        int64_t                     conditionRetry    = 0;
+        bool                        conditionPending  = false;
+        int64_t                     conditionRetryAt  = 0;
     };
 
     struct SDbusInhibitCookie {
@@ -44,7 +49,7 @@
     SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie);
     void               registerDbusInhibitCookie(SDbusInhibitCookie& cookie);
     bool               unregisterDbusInhibitCookie(const SDbusInhibitCookie& 
cookie);
-    bool               unregisterDbusInhibitCookies(const std::string& 
ownerID);
+    size_t             unregisterDbusInhibitCookies(const std::string& 
ownerID);
 
     void               handleInhibitOnDbusSleep(bool toSleep);
     void               inhibitSleep();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hypridle-0.1.7/src/main.cpp 
new/hypridle-0.1.8/src/main.cpp
--- old/hypridle-0.1.7/src/main.cpp     2025-08-27 12:40:01.000000000 +0200
+++ new/hypridle-0.1.8/src/main.cpp     2026-07-26 16:44:59.000000000 +0200
@@ -2,6 +2,7 @@
 #include "config/ConfigManager.hpp"
 #include "core/Hypridle.hpp"
 #include "helpers/Log.hpp"
+#include <memory>
 
 int main(int argc, char** argv, char** envp) {
     std::string configPath;
@@ -40,29 +41,33 @@
 
         else if (arg == "--help" || arg == "-h") {
             Debug::log(NONE,
-                "Usage: hypridle [options]\n"
-                "Options:\n"
-                "  -v, --verbose       Enable verbose logging\n"
-                "  -q, --quiet         Suppress all output except errors\n"
-                "  -V, --version       Show version information\n"
-                "  -c, --config <path> Specify a custom config file path\n"
-                "  -h, --help          Show this help message"
-            );
+                       "Usage: hypridle [options]\n"
+                       "Options:\n"
+                       "  -v, --verbose       Enable verbose logging\n"
+                       "  -q, --quiet         Suppress all output except 
errors\n"
+                       "  -V, --version       Show version information\n"
+                       "  -c, --config <path> Specify a custom config file 
path\n"
+                       "  -h, --help          Show this help message");
             return 0;
         }
     }
 
-    try {
-        g_pConfigManager = std::make_unique<CConfigManager>(configPath);
-        g_pConfigManager->init();
-    } catch (const char* err) {
-        Debug::log(CRIT, "ConfigManager threw: {}", err);
-        std::string strerr = err;
-        if (strerr.contains("File does not exist"))
-            Debug::log(NONE, "           Make sure you have a config.");
+    g_pConfigManager = std::make_unique<CConfigManager>(configPath);
+
+    if (g_pConfigManager->configCurrentPath.empty()) {
+        if (!configPath.empty()) {
+            Debug::log(CRIT, "ConfigManager: Specified file not found: {}\n", 
configPath);
+        } else {
+            Debug::log(CRIT, "ConfigManager: No hypridle.conf file found in:");
+            Debug::log(NONE, "    $XDG_CONFIG_HOME/hypr/, ~/.config/hypr/, 
[XDG_CONFIG_DIRS]/hypr/, /etc/xdg/hypr/\n");
+            Debug::log(NONE, "Create a config or specify one manually:");
+            Debug::log(NONE, "    hypridle -c /path/to/conf");
+        }
         return 1;
     }
 
+    g_pConfigManager->init();
+
     g_pHypridle = std::make_unique<CHypridle>();
     g_pHypridle->run();
 

++++++ hypridle.obsinfo ++++++
--- /var/tmp/diff_new_pack.gTh1vu/_old  2026-08-01 18:34:32.382590323 +0200
+++ /var/tmp/diff_new_pack.gTh1vu/_new  2026-08-01 18:34:32.386590461 +0200
@@ -1,5 +1,5 @@
 name: hypridle
-version: 0.1.7
-mtime: 1756291201
-commit: 5430b73ddf148651bcf35fa39ed4d757c7534028
+version: 0.1.8
+mtime: 1785077099
+commit: e5c01af0842bd66617f7004568df9406111d6e80
 

Reply via email to