diff --git a/src/core/Hypridle.cpp b/src/core/Hypridle.cpp index 9920f40..fc2f6c5 100644 --- a/src/core/Hypridle.cpp +++ b/src/core/Hypridle.cpp @@ -307,8 +307,8 @@ void CHypridle::onInhibit(bool lock) { 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]; + auto& l = m_sWaylandIdleState.listeners[i]; + const auto& r = RULES[i]; ext_idle_notification_v1_destroy(l.notification); @@ -334,14 +334,26 @@ void CHypridle::registerDbusInhibitCookie(CHypridle::SDbusInhibitCookie& cookie) m_sDBUSState.inhibitCookies.push_back(cookie); } -void CHypridle::unregisterDbusInhibitCookie(const CHypridle::SDbusInhibitCookie& cookie) { +bool CHypridle::unregisterDbusInhibitCookie(const CHypridle::SDbusInhibitCookie& cookie) { const auto IT = std::find_if(m_sDBUSState.inhibitCookies.begin(), m_sDBUSState.inhibitCookies.end(), [&cookie](const CHypridle::SDbusInhibitCookie& item) { return item.cookie == cookie.cookie; }); if (IT == m_sDBUSState.inhibitCookies.end()) - Debug::log(WARN, "BUG THIS: attempted to unregister unknown cookie"); - else - m_sDBUSState.inhibitCookies.erase(IT); + return false; + + m_sDBUSState.inhibitCookies.erase(IT); + 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; } void handleDbusLogin(sdbus::Message& msg) { @@ -410,7 +422,7 @@ void handleDbusBlockInhibits(const std::string& inhibits) { } void handleDbusBlockInhibitsPropertyChanged(sdbus::Message& msg) { - std::string interface; + std::string interface; std::map changedProperties; msg >> interface >> changedProperties; if (changedProperties.contains("BlockInhibited")) { @@ -420,6 +432,7 @@ void handleDbusBlockInhibitsPropertyChanged(sdbus::Message& msg) { void handleDbusScreensaver(sdbus::MethodCall call, bool inhibit) { std::string app = "?", reason = "?"; + std::string ownerID = call.getSender(); if (inhibit) { call >> app; @@ -432,13 +445,17 @@ void handleDbusScreensaver(sdbus::MethodCall call, bool inhibit) { if (COOKIE.cookie == 0) { Debug::log(WARN, "No cookie in uninhibit"); } else { - app = COOKIE.app; - reason = COOKIE.reason; - g_pHypridle->unregisterDbusInhibitCookie(COOKIE); + app = COOKIE.app; + reason = COOKIE.reason; + ownerID = COOKIE.ownerID; + + if (!g_pHypridle->unregisterDbusInhibitCookie(COOKIE)) { + Debug::log(WARN, "BUG THIS: attempted to unregister unknown cookie"); + }; } } - Debug::log(LOG, "ScreenSaver inhibit: {} dbus message from {} with content {}", inhibit, app, reason); + Debug::log(LOG, "ScreenSaver inhibit: {} dbus message from {} (owner: {}) with content {}", inhibit, app, ownerID, reason); if (inhibit) g_pHypridle->onInhibit(true); @@ -448,7 +465,7 @@ void handleDbusScreensaver(sdbus::MethodCall call, bool inhibit) { static int cookieID = 1337; if (inhibit) { - auto cookie = CHypridle::SDbusInhibitCookie{uint32_t{cookieID}, app, reason}; + auto cookie = CHypridle::SDbusInhibitCookie{uint32_t{cookieID}, app, reason, ownerID}; auto reply = call.createReply(); reply << uint32_t{cookieID++}; @@ -464,12 +481,25 @@ void handleDbusScreensaver(sdbus::MethodCall call, bool inhibit) { } } +void handleDbusNameOwnerChanged(sdbus::Message& msg) { + std::string name, oldOwner, newOwner; + msg >> name >> oldOwner >> newOwner; + + if (!newOwner.empty()) + return; + + if (g_pHypridle->unregisterDbusInhibitCookies(oldOwner)) { + Debug::log(LOG, "App with owner {} disconnected", oldOwner); + g_pHypridle->onInhibit(false); + } +} + void CHypridle::setupDBUS() { static auto const IGNORE_DBUS_INHIBIT = **(Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:ignore_dbus_inhibit"); static auto const IGNORE_SYSTEMD_INHIBIT = **(Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:ignore_systemd_inhibit"); - auto proxy = sdbus::createProxy("org.freedesktop.login1", "/org/freedesktop/login1"); - auto method = proxy->createMethodCall("org.freedesktop.login1.Manager", "GetSession"); + auto proxy = sdbus::createProxy("org.freedesktop.login1", "/org/freedesktop/login1"); + auto method = proxy->createMethodCall("org.freedesktop.login1.Manager", "GetSession"); method << "auto"; sdbus::ObjectPath path; @@ -479,14 +509,13 @@ void CHypridle::setupDBUS() { m_sDBUSState.connection->addMatch("type='signal',path='" + path + "',interface='org.freedesktop.login1.Session'", handleDbusLogin, sdbus::floating_slot_t{}); m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.login1.Manager'", handleDbusSleep, sdbus::floating_slot_t{}); - } catch (std::exception& e) { - Debug::log(WARN, "Couldn't connect to logind service ({})", e.what()); - } + } catch (std::exception& e) { Debug::log(WARN, "Couldn't connect to logind service ({})", e.what()); } Debug::log(LOG, "Using dbus path {}", path.c_str()); if (!IGNORE_SYSTEMD_INHIBIT) { - m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.DBus.Properties'", handleDbusBlockInhibitsPropertyChanged, sdbus::floating_slot_t{}); + m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.DBus.Properties'", handleDbusBlockInhibitsPropertyChanged, + sdbus::floating_slot_t{}); try { std::string value = proxy->getProperty("BlockInhibited").onInterface("org.freedesktop.login1.Manager"); @@ -504,7 +533,7 @@ void CHypridle::setupDBUS() { try { m_sDBUSState.screenSaverServiceConnection = sdbus::createSessionBusConnection("org.freedesktop.ScreenSaver"); - for (const std::string& path: paths) { + for (const std::string& path : paths) { try { auto obj = sdbus::createObject(*m_sDBUSState.screenSaverServiceConnection, path); obj->registerMethod("org.freedesktop.ScreenSaver", "Inhibit", "ss", "u", [&](sdbus::MethodCall c) { handleDbusScreensaver(c, true); }); @@ -514,6 +543,9 @@ void CHypridle::setupDBUS() { m_sDBUSState.screenSaverObjects.push_back(std::move(obj)); } catch (std::exception& e) { Debug::log(ERR, "Failed registering for {}, perhaps taken?\nerr: {}", path, e.what()); } } + + m_sDBUSState.screenSaverServiceConnection->addMatch("type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameOwnerChanged'", + handleDbusNameOwnerChanged, sdbus::floating_slot_t{}); } catch (std::exception& e) { Debug::log(ERR, "Couldn't connect to session dbus\nerr: {}", e.what()); } } } diff --git a/src/core/Hypridle.hpp b/src/core/Hypridle.hpp index 6f6a403..e5a131a 100644 --- a/src/core/Hypridle.hpp +++ b/src/core/Hypridle.hpp @@ -20,7 +20,7 @@ class CHypridle { struct SDbusInhibitCookie { uint32_t cookie = 0; - std::string app, reason; + std::string app, reason, ownerID; }; void run(); @@ -35,7 +35,8 @@ class CHypridle { SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie); void registerDbusInhibitCookie(SDbusInhibitCookie& cookie); - void unregisterDbusInhibitCookie(const SDbusInhibitCookie& cookie); + bool unregisterDbusInhibitCookie(const SDbusInhibitCookie& cookie); + bool unregisterDbusInhibitCookies(const std::string& ownerID); private: void setupDBUS();