core: add an option to ignore idle inhibition per-listener (#158)

* Add ability to ignore Wayland idle inhibitors

config: general:ignore_wayland_inhibit (bool)

If the config value general:ignore_wayland_inhibit is true, the
CCExtIdleNotifierV1 function used will be: sendGetInputIdleNotification.
This instructs the compositor (hyprland) to return all idle/resume
events, ignoring any Wayland inhibitors.

If the config value general:ignore_wayland_inhibit is false/unset,
it will use the default function sendGetIdleNotification, which obeys
Wayland inhibitors.

* Ignore idle inhibition per-listener

Add `ignore_inhibit` option (bool) to listener section of config file,
to allow ignoring idle inhibition per-listener. When set to true, all
types of inhibitors are ignored (systemd, dbus/ScreenSaver, Wayland).
Default value: false (the rule will obey inhibition)

Example:

    listener {
        timeout = 5
        on-timeout = logger 'should obey idle inhibition'
    }

    listener {
        timeout = 6
        on-timeout = logger 'should ignore idle inhibition'
        ignore_inhibit = true
    }

* Add ability to ignore Wayland idle inhibitors

config: general:ignore_wayland_inhibit (bool, default: false)

If the config value general:ignore_wayland_inhibit is true, use
sendGetInputIdleNotification to create the idle notification object.
(Wayland protocol: ext_idle_notifier_v1::get_input_idle_notification)
This instructs the compositor to return all idle/resume events,
ignoring any Wayland inhibitors.

If the config value general:ignore_wayland_inhibit is false (default),
it will use sendGetIdleNotification, which obeys Wayland inhibitors.
(Wayland protocol: ext_idle_notifier_v1::get_idle_notification)

* clang-format

* Update flake.lock

* Add newline at end of file: src/core/Hypridle.cpp
This commit is contained in:
Chris Hixon 2025-06-03 12:45:20 -06:00 committed by GitHub
parent 63d08e8e72
commit a282131ac7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 29 additions and 22 deletions

View file

@ -37,6 +37,7 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue("listener", "timeout", Hyprlang::INT{-1});
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.addConfigValue("general:lock_cmd", Hyprlang::STRING{""});
m_config.addConfigValue("general:unlock_cmd", Hyprlang::STRING{""});
@ -86,6 +87,8 @@ Hyprlang::CParseResult CConfigManager::postParse() {
rule.onTimeout = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("listener", "on-timeout", k.c_str()));
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()));
if (timeout == -1) {
result.setError("Category has a missing timeout setting");
continue;
@ -95,7 +98,8 @@ Hyprlang::CParseResult CConfigManager::postParse() {
}
for (auto& r : m_vRules) {
Debug::log(LOG, "Registered timeout rule for {}s:\n on-timeout: {}\n on-resume: {}", r.timeout, r.onTimeout, r.onResume);
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);
}
return result;

View file

@ -17,6 +17,7 @@ class CConfigManager {
uint64_t timeout = 0;
std::string onTimeout = "";
std::string onResume = "";
bool ignoreInhibit = false;
};
std::vector<STimeoutRule> getRules();

View file

@ -1,3 +1,4 @@
#include "Hypridle.hpp"
#include "../helpers/Log.hpp"
#include "../config/ConfigManager.hpp"
@ -66,13 +67,14 @@ void CHypridle::run() {
const auto& r = RULES[i];
l.onRestore = r.onResume;
l.onTimeout = r.onTimeout;
l.ignoreInhibit = r.ignoreInhibit;
if (!*IGNOREWAYLANDINHIBIT)
l.notification =
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
else
if (*IGNOREWAYLANDINHIBIT || r.ignoreInhibit)
l.notification =
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetInputIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
else
l.notification =
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
l.notification->setData(&m_sWaylandIdleState.listeners[i]);
@ -256,7 +258,7 @@ static void spawn(const std::string& args) {
void CHypridle::onIdled(SIdleListener* pListener) {
Debug::log(LOG, "Idled: rule {:x}", (uintptr_t)pListener);
isIdled = true;
if (g_pHypridle->m_iInhibitLocks > 0) {
if (g_pHypridle->m_iInhibitLocks > 0 && !pListener->ignoreInhibit) {
Debug::log(LOG, "Ignoring from onIdled(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
return;
}
@ -273,7 +275,7 @@ void CHypridle::onIdled(SIdleListener* pListener) {
void CHypridle::onResumed(SIdleListener* pListener) {
Debug::log(LOG, "Resumed: rule {:x}", (uintptr_t)pListener);
isIdled = false;
if (g_pHypridle->m_iInhibitLocks > 0) {
if (g_pHypridle->m_iInhibitLocks > 0 && !pListener->ignoreInhibit) {
Debug::log(LOG, "Ignoring from onResumed(), inhibit locks: {}", g_pHypridle->m_iInhibitLocks);
return;
}
@ -299,19 +301,18 @@ void CHypridle::onInhibit(bool lock) {
static const auto IGNOREWAYLANDINHIBIT = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_wayland_inhibit");
const auto RULES = g_pConfigManager->getRules();
for (size_t i = 0; i < RULES.size(); ++i) {
auto& l = m_sWaylandIdleState.listeners[i];
const auto& r = RULES[i];
l.notification->sendDestroy();
if (!*IGNOREWAYLANDINHIBIT)
l.notification =
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
else
if (*IGNOREWAYLANDINHIBIT || r.ignoreInhibit)
l.notification =
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetInputIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
else
l.notification =
makeShared<CCExtIdleNotificationV1>(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource()));
l.notification->setData(&m_sWaylandIdleState.listeners[i]);

View file

@ -20,6 +20,7 @@ class CHypridle {
SP<CCExtIdleNotificationV1> notification = nullptr;
std::string onTimeout = "";
std::string onRestore = "";
bool ignoreInhibit = false;
};
struct SDbusInhibitCookie {