From 0b702aa32ff297815d94b10cf31e1369c05fd0da Mon Sep 17 00:00:00 2001 From: Maximilian Seidler Date: Fri, 17 Jan 2025 07:57:58 +0100 Subject: [PATCH 1/5] core: add hyprland-lock-notify-v1 protocol implementation --- .gitignore | 6 +++++- CMakeLists.txt | 7 +++++++ flake.lock | 23 +++++++++++++++++++++++ flake.nix | 6 ++++++ nix/default.nix | 4 +++- nix/overlays.nix | 1 + src/core/Hypridle.cpp | 34 ++++++++++++++++++++++++++++++++++ src/core/Hypridle.hpp | 13 ++++++++++--- 8 files changed, 89 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 33419bc..c109696 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ .vscode/ build/ -protocols/ \ No newline at end of file +protocols/ +.clangd/ +.direnv/ +.cache/ +compile_commands.json diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dfb8a9..99206e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,10 +85,17 @@ function(protocol protoPath protoName external) endif() endfunction() +pkg_check_modules(hyprland_protocols_dep REQUIRED IMPORTED_TARGET hyprland-protocols>=0.4.0) +pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) +message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") + make_directory(${CMAKE_SOURCE_DIR}/protocols) # we don't ship any custom ones so # the dir won't be there + protocol("staging/ext-idle-notify/ext-idle-notify-v1.xml" "ext-idle-notify-v1" false) +protocol("${HYPRLAND_PROTOCOLS}/protocols/hyprland-lock-notify-v1.xml" "hyprland-lock-notify-v1" + true) # Installation install(TARGETS hypridle) diff --git a/flake.lock b/flake.lock index 74ad2f0..6f56a40 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,27 @@ { "nodes": { + "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1737053288, + "narHash": "sha256-RV6n5M5kewrOfpDMdVzj5oVRhVHiZpjDcaOHGYMcnRo=", + "rev": "5b17e27fde2155eeb96ff487b7721e5df0a72296", + "revCount": 30, + "type": "git", + "url": "file:///home/max/desk/hyprland-protocols" + }, + "original": { + "type": "git", + "url": "file:///home/max/desk/hyprland-protocols" + } + }, "hyprlang": { "inputs": { "hyprutils": [ @@ -67,6 +89,7 @@ }, "root": { "inputs": { + "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", "hyprutils": "hyprutils", "nixpkgs": "nixpkgs", diff --git a/flake.nix b/flake.nix index 24364c7..9dc4a54 100644 --- a/flake.nix +++ b/flake.nix @@ -17,6 +17,12 @@ inputs.nixpkgs.follows = "nixpkgs"; inputs.systems.follows = "systems"; }; + + hyprland-protocols = { + url = "github:hyprwm/hyprland-protocols"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + }; }; outputs = { diff --git a/nix/default.nix b/nix/default.nix index 5238809..f3b5a93 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -2,9 +2,10 @@ lib, stdenv, cmake, - pkg-config, + hyprland-protocols, hyprlang, hyprutils, + pkg-config, sdbus-cpp, systemd, wayland, @@ -24,6 +25,7 @@ stdenv.mkDerivation { ]; buildInputs = [ + hyprland-protocols hyprlang hyprutils sdbus-cpp diff --git a/nix/overlays.nix b/nix/overlays.nix index c3d5651..bde1308 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -13,6 +13,7 @@ in { default = inputs.self.overlays.hypridle; hypridle = lib.composeManyExtensions [ + inputs.hyprland-protocols.overlays.default inputs.hyprlang.overlays.default inputs.hyprutils.overlays.default inputs.self.overlays.sdbuscpp diff --git a/src/core/Hypridle.cpp b/src/core/Hypridle.cpp index 8c85e9d..038669f 100644 --- a/src/core/Hypridle.cpp +++ b/src/core/Hypridle.cpp @@ -1,6 +1,8 @@ #include "Hypridle.hpp" #include "../helpers/Log.hpp" #include "../config/ConfigManager.hpp" +#include "ext-idle-notify-v1-protocol.h" +#include "hyprland-lock-notify-v1-protocol.h" #include "signal.h" #include #include @@ -44,6 +46,19 @@ inline const ext_idle_notification_v1_listener idleListener = { .resumed = handleResumed, }; +void handleLocked(void* data, hyprland_lock_notification_v1* hyprland_lock_notification_v1) { + Debug::log(LOG, "Locked"); +} + +void handleUnlocked(void* data, hyprland_lock_notification_v1* hyprland_lock_notification_v1) { + Debug::log(LOG, "Unlocked"); +} + +inline const hyprland_lock_notification_v1_listener lockListener = { + .locked = handleLocked, + .unlocked = handleUnlocked, +}; + void CHypridle::run() { m_sWaylandState.registry = wl_display_get_registry(m_sWaylandState.display); @@ -73,6 +88,12 @@ void CHypridle::run() { wl_display_roundtrip(m_sWaylandState.display); + if (m_sWaylandState.lockNotifier) { + m_sWaylandState.lockNotification = hyprland_lock_notifier_v1_get_lock_notification(m_sWaylandState.lockNotifier); + + hyprland_lock_notification_v1_add_listener(m_sWaylandState.lockNotification, &lockListener, nullptr); + } + Debug::log(LOG, "wayland done, registering dbus"); try { @@ -194,6 +215,9 @@ void CHypridle::onGlobal(void* data, struct wl_registry* registry, uint32_t name if (IFACE == ext_idle_notifier_v1_interface.name) { m_sWaylandIdleState.notifier = (ext_idle_notifier_v1*)wl_registry_bind(registry, name, &ext_idle_notifier_v1_interface, version); Debug::log(LOG, " > Bound to {} v{}", IFACE, version); + } else if (IFACE == hyprland_lock_notifier_v1_interface.name) { + m_sWaylandState.lockNotifier = (hyprland_lock_notifier_v1*)wl_registry_bind(registry, name, &hyprland_lock_notifier_v1_interface, version); + Debug::log(LOG, " > Bound to {} v{}", IFACE, version); } else if (IFACE == wl_seat_interface.name) { if (m_sWaylandState.seat) { Debug::log(WARN, "Hypridle does not support multi-seat configurations. Only binding to the first seat."); @@ -295,6 +319,16 @@ void CHypridle::onResumed(SIdleListener* pListener) { spawn(pListener->onRestore); } +void CHypridle::onLocked() { + Debug::log(LOG, "Locked"); + m_isLocked = true; + + if (const auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_lock_cmd"); !PLOCKCMD->empty()) { + Debug::log(LOG, "Running {}", *PLOCKCMD); + spawn(*PLOCKCMD); + } +} + void CHypridle::onInhibit(bool lock) { m_iInhibitLocks += lock ? 1 : -1; diff --git a/src/core/Hypridle.hpp b/src/core/Hypridle.hpp index e5a131a..2b8d59f 100644 --- a/src/core/Hypridle.hpp +++ b/src/core/Hypridle.hpp @@ -7,6 +7,7 @@ #include #include "ext-idle-notify-v1-protocol.h" +#include "hyprland-lock-notify-v1-protocol.h" class CHypridle { public: @@ -31,6 +32,9 @@ class CHypridle { void onIdled(SIdleListener*); void onResumed(SIdleListener*); + void onLocked(); + void onUnlocked(); + void onInhibit(bool lock); SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie); @@ -44,12 +48,15 @@ class CHypridle { bool m_bTerminate = false; bool isIdled = false; + bool m_isLocked = false; int64_t m_iInhibitLocks = 0; struct { - wl_display* display = nullptr; - wl_registry* registry = nullptr; - wl_seat* seat = nullptr; + wl_display* display = nullptr; + wl_registry* registry = nullptr; + wl_seat* seat = nullptr; + hyprland_lock_notifier_v1* lockNotifier = nullptr; + hyprland_lock_notification_v1* lockNotification = nullptr; } m_sWaylandState; struct { From 1824a558629f695e0aa0d7a27f68dfef6e03cf91 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler Date: Fri, 17 Jan 2025 08:00:51 +0100 Subject: [PATCH 2/5] config: add on_lock_cmd and on_unlock_cmd --- src/config/ConfigManager.cpp | 2 ++ src/core/Hypridle.cpp | 34 ++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 95d6854..de5bbf2 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -23,6 +23,8 @@ void CConfigManager::init() { m_config.addConfigValue("general:lock_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:unlock_cmd", Hyprlang::STRING{""}); + m_config.addConfigValue("general:on_lock_cmd", Hyprlang::STRING{""}); + m_config.addConfigValue("general:on_unlock_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:before_sleep_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:after_sleep_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:ignore_dbus_inhibit", Hyprlang::INT{0}); diff --git a/src/core/Hypridle.cpp b/src/core/Hypridle.cpp index 038669f..9723dc1 100644 --- a/src/core/Hypridle.cpp +++ b/src/core/Hypridle.cpp @@ -47,11 +47,11 @@ inline const ext_idle_notification_v1_listener idleListener = { }; void handleLocked(void* data, hyprland_lock_notification_v1* hyprland_lock_notification_v1) { - Debug::log(LOG, "Locked"); + g_pHypridle->onLocked(); } void handleUnlocked(void* data, hyprland_lock_notification_v1* hyprland_lock_notification_v1) { - Debug::log(LOG, "Unlocked"); + g_pHypridle->onUnlocked(); } inline const hyprland_lock_notification_v1_listener lockListener = { @@ -319,16 +319,6 @@ void CHypridle::onResumed(SIdleListener* pListener) { spawn(pListener->onRestore); } -void CHypridle::onLocked() { - Debug::log(LOG, "Locked"); - m_isLocked = true; - - if (const auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_lock_cmd"); !PLOCKCMD->empty()) { - Debug::log(LOG, "Running {}", *PLOCKCMD); - spawn(*PLOCKCMD); - } -} - void CHypridle::onInhibit(bool lock) { m_iInhibitLocks += lock ? 1 : -1; @@ -355,6 +345,26 @@ void CHypridle::onInhibit(bool lock) { Debug::log(LOG, "Inhibit locks: {}", m_iInhibitLocks); } +void CHypridle::onLocked() { + Debug::log(LOG, "Locked"); + m_isLocked = true; + + if (const auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_lock_cmd"); !PLOCKCMD->empty()) { + Debug::log(LOG, "Running {}", *PLOCKCMD); + spawn(*PLOCKCMD); + } +} + +void CHypridle::onUnlocked() { + Debug::log(LOG, "Unlocked"); + m_isLocked = false; + + if (const auto* const PUNLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_unlock_cmd"); !PUNLOCKCMD->empty()) { + Debug::log(LOG, "Running {}", *PUNLOCKCMD); + spawn(*PUNLOCKCMD); + } +} + CHypridle::SDbusInhibitCookie CHypridle::getDbusInhibitCookie(uint32_t cookie) { for (auto& c : m_sDBUSState.inhibitCookies) { if (c.cookie == cookie) From 37baf4f25b5404d4160e5312ea694d6750fb99d3 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler Date: Fri, 17 Jan 2025 08:03:14 +0100 Subject: [PATCH 3/5] core: add an option to inhibit sleep until the locked event --- src/config/ConfigManager.cpp | 1 + src/core/Hypridle.cpp | 107 +++++++++++++++++++++++++++++++---- src/core/Hypridle.hpp | 16 +++++- 3 files changed, 110 insertions(+), 14 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index de5bbf2..349971a 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -29,6 +29,7 @@ void CConfigManager::init() { m_config.addConfigValue("general:after_sleep_cmd", Hyprlang::STRING{""}); m_config.addConfigValue("general:ignore_dbus_inhibit", Hyprlang::INT{0}); m_config.addConfigValue("general:ignore_systemd_inhibit", Hyprlang::INT{0}); + m_config.addConfigValue("general:inhibit_sleep", Hyprlang::INT{2}); m_config.commence(); diff --git a/src/core/Hypridle.cpp b/src/core/Hypridle.cpp index 9723dc1..b53c216 100644 --- a/src/core/Hypridle.cpp +++ b/src/core/Hypridle.cpp @@ -103,7 +103,39 @@ void CHypridle::run() { exit(1); } + static auto* const PINHIBIT = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:inhibit_sleep"); + static auto* const PSLEEPCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:before_sleep_cmd"); + static auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:lock_cmd"); + + switch (**PINHIBIT) { + case 0: // disabled + m_inhibitSleepBehavior = SLEEP_INHIBIT_NONE; + break; + case 1: // enabled + m_inhibitSleepBehavior = SLEEP_INHIBIT_NORMAL; + break; + case 2: { // auto (enable, but wait until locked if before_sleep_cmd contains hyprlock, or loginctl lock-session and lock_cmd contains hyprlock.) + if (std::string{*PSLEEPCMD}.contains("hyprlock")) + m_inhibitSleepBehavior = SLEEP_INHIBIT_WAIT_FOR_LOCKED; + else if (std::string{*PLOCKCMD}.contains("hyprlock") && std::string{*PSLEEPCMD}.contains("lock-session")) + m_inhibitSleepBehavior = SLEEP_INHIBIT_WAIT_FOR_LOCKED; + else + m_inhibitSleepBehavior = SLEEP_INHIBIT_NORMAL; + } break; + case 3: // wait until locked + m_inhibitSleepBehavior = SLEEP_INHIBIT_WAIT_FOR_LOCKED; + break; + default: Debug::log(ERR, "Invalid inhibit_sleep value: {}", **PINHIBIT); break; + } + + switch (m_inhibitSleepBehavior) { + case SLEEP_INHIBIT_NONE: Debug::log(LOG, "Sleep inhibition disabled"); break; + case SLEEP_INHIBIT_NORMAL: Debug::log(LOG, "Sleep inhibition enabled"); break; + case SLEEP_INHIBIT_WAIT_FOR_LOCKED: Debug::log(LOG, "Sleep inhibition enabled - inhibiting until the wayland session gets locked"); break; + } + setupDBUS(); + handleInhibitSleep(false); enterEventLoop(); } @@ -268,6 +300,7 @@ static void spawn(const std::string& args) { close(socket[0]); write(socket[1], &grandchild, sizeof(grandchild)); close(socket[1]); + waitpid(grandchild, NULL, 0); // exit child _exit(0); } @@ -346,23 +379,22 @@ void CHypridle::onInhibit(bool lock) { } void CHypridle::onLocked() { - Debug::log(LOG, "Locked"); + Debug::log(LOG, "Wayland session got locked"); m_isLocked = true; - if (const auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_lock_cmd"); !PLOCKCMD->empty()) { - Debug::log(LOG, "Running {}", *PLOCKCMD); + if (m_inhibitSleepBehavior == SLEEP_INHIBIT_WAIT_FOR_LOCKED) + uninhibitSleep(); + + if (const auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_lock_cmd"); PLOCKCMD && strlen(*PLOCKCMD) > 0) spawn(*PLOCKCMD); - } } void CHypridle::onUnlocked() { - Debug::log(LOG, "Unlocked"); + Debug::log(LOG, "Wayland session got unlocked"); m_isLocked = false; - if (const auto* const PUNLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_unlock_cmd"); !PUNLOCKCMD->empty()) { - Debug::log(LOG, "Running {}", *PUNLOCKCMD); + if (const auto* const PUNLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_unlock_cmd"); PUNLOCKCMD && strlen(*PUNLOCKCMD) > 0) spawn(*PUNLOCKCMD); - } } CHypridle::SDbusInhibitCookie CHypridle::getDbusInhibitCookie(uint32_t cookie) { @@ -441,11 +473,14 @@ static void handleDbusSleep(sdbus::Message msg) { std::string cmd = toSleep ? *PSLEEPCMD : *PAFTERSLEEPCMD; - if (cmd.empty()) - return; + if (!toSleep) + g_pHypridle->handleInhibitSleep(toSleep); - Debug::log(LOG, "Running: {}", cmd); - spawn(cmd); + if (!cmd.empty()) + spawn(cmd); + + if (toSleep) + g_pHypridle->handleInhibitSleep(toSleep); } void handleDbusBlockInhibits(const std::string& inhibits) { @@ -540,6 +575,7 @@ void CHypridle::setupDBUS() { m_sDBUSState.connection->addMatch("type='signal',path='" + path + "',interface='org.freedesktop.login1.Session'", ::handleDbusLogin); m_sDBUSState.connection->addMatch("type='signal',path='/org/freedesktop/login1',interface='org.freedesktop.login1.Manager'", ::handleDbusSleep); + m_sDBUSState.login = sdbus::createProxy(*m_sDBUSState.connection, sdbus::ServiceName{"org.freedesktop.login1"}, sdbus::ObjectPath{"/org/freedesktop/login1"}); } catch (std::exception& e) { Debug::log(WARN, "Couldn't connect to logind service ({})", e.what()); } Debug::log(LOG, "Using dbus path {}", path.c_str()); @@ -586,3 +622,50 @@ void CHypridle::setupDBUS() { systemConnection.reset(); } + +void CHypridle::handleInhibitSleep(bool toSleep) { + if (m_inhibitSleepBehavior == SLEEP_INHIBIT_NONE) + return; + + if (!toSleep) + inhibitSleep(); + else if (m_inhibitSleepBehavior != SLEEP_INHIBIT_WAIT_FOR_LOCKED) + uninhibitSleep(); +} + +void CHypridle::inhibitSleep() { + auto method = m_sDBUSState.login->createMethodCall(sdbus::InterfaceName{"org.freedesktop.login1.Manager"}, sdbus::MethodName{"Inhibit"}); + method << "sleep"; + method << "hypridle"; + method << "Hypridle wants to delay sleep until it's before_sleep handling is done."; + method << "delay"; + + try { + auto reply = m_sDBUSState.login->callMethod(method); + + if (!reply || !reply.isValid()) { + Debug::log(ERR, "Failed to inhibit sleep"); + return; + } + + if (reply.isEmpty()) { + Debug::log(ERR, "Failed to inhibit sleep, empty reply"); + return; + } + + reply >> m_sDBUSState.sleepInhibitFd; + Debug::log(TRACE, "Inhibited sleep with fd {}", m_sDBUSState.sleepInhibitFd.get()); + } catch (const std::exception& e) { Debug::log(ERR, "Failed to inhibit sleep ({})", e.what()); } + + Debug::log(LOG, "Inhibited sleep!"); +} + +void CHypridle::uninhibitSleep() { + if (!m_sDBUSState.sleepInhibitFd.isValid()) { + Debug::log(ERR, "No sleep inhibitor fd to release"); + return; + } + + Debug::log(LOG, "Releasing the sleep inhibitor!"); + close(m_sDBUSState.sleepInhibitFd.release()); +} diff --git a/src/core/Hypridle.hpp b/src/core/Hypridle.hpp index 2b8d59f..26aa9ef 100644 --- a/src/core/Hypridle.hpp +++ b/src/core/Hypridle.hpp @@ -32,16 +32,20 @@ class CHypridle { void onIdled(SIdleListener*); void onResumed(SIdleListener*); + void onInhibit(bool lock); + void onLocked(); void onUnlocked(); - void onInhibit(bool lock); - SDbusInhibitCookie getDbusInhibitCookie(uint32_t cookie); void registerDbusInhibitCookie(SDbusInhibitCookie& cookie); bool unregisterDbusInhibitCookie(const SDbusInhibitCookie& cookie); bool unregisterDbusInhibitCookies(const std::string& ownerID); + void handleInhibitSleep(bool toSleep); + void inhibitSleep(); + void uninhibitSleep(); + private: void setupDBUS(); void enterEventLoop(); @@ -51,6 +55,12 @@ class CHypridle { bool m_isLocked = false; int64_t m_iInhibitLocks = 0; + enum { + SLEEP_INHIBIT_NONE, + SLEEP_INHIBIT_NORMAL, + SLEEP_INHIBIT_WAIT_FOR_LOCKED, + } m_inhibitSleepBehavior; + struct { wl_display* display = nullptr; wl_registry* registry = nullptr; @@ -68,8 +78,10 @@ class CHypridle { struct { std::unique_ptr connection; std::unique_ptr screenSaverServiceConnection; + std::unique_ptr login; std::vector> screenSaverObjects; std::vector inhibitCookies; + sdbus::UnixFd sleepInhibitFd; } m_sDBUSState; struct { From 8acef589dce889af70eca0eb144f02793597d872 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler Date: Sat, 18 Jan 2025 09:49:19 +0100 Subject: [PATCH 4/5] bump hyprland-protocols --- CMakeLists.txt | 2 +- flake.lock | 17 +++++++++-------- src/core/Hypridle.cpp | 42 +++++++++++++++++++++++++++--------------- src/core/Hypridle.hpp | 4 ++-- 4 files changed, 39 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99206e8..7d1db61 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,7 +85,7 @@ function(protocol protoPath protoName external) endif() endfunction() -pkg_check_modules(hyprland_protocols_dep REQUIRED IMPORTED_TARGET hyprland-protocols>=0.4.0) +pkg_check_modules(hyprland_protocols_dep REQUIRED IMPORTED_TARGET hyprland-protocols>=0.6.0) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") diff --git a/flake.lock b/flake.lock index 6f56a40..0c30975 100644 --- a/flake.lock +++ b/flake.lock @@ -10,16 +10,17 @@ ] }, "locked": { - "lastModified": 1737053288, - "narHash": "sha256-RV6n5M5kewrOfpDMdVzj5oVRhVHiZpjDcaOHGYMcnRo=", - "rev": "5b17e27fde2155eeb96ff487b7721e5df0a72296", - "revCount": 30, - "type": "git", - "url": "file:///home/max/desk/hyprland-protocols" + "lastModified": 1737127640, + "narHash": "sha256-mIQ3/axCZ4g8ySwWRbW4fJcyC9v55uAii3cqlJRtW8g=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "455c055883d9639d4fcbfcedb4c6d12ce313791e", + "type": "github" }, "original": { - "type": "git", - "url": "file:///home/max/desk/hyprland-protocols" + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" } }, "hyprlang": { diff --git a/src/core/Hypridle.cpp b/src/core/Hypridle.cpp index b53c216..e65ab78 100644 --- a/src/core/Hypridle.cpp +++ b/src/core/Hypridle.cpp @@ -103,6 +103,11 @@ void CHypridle::run() { exit(1); } + if (!m_sWaylandState.lockNotifier) + Debug::log(WARN, + "Compositor is missing hyprland-lock-notify-v1!\n" + "general:inhibit_sleep=3, general:on_lock_cmd and general:on_unlock_cmd will not work."); + static auto* const PINHIBIT = (Hyprlang::INT* const*)g_pConfigManager->getValuePtr("general:inhibit_sleep"); static auto* const PSLEEPCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:before_sleep_cmd"); static auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:lock_cmd"); @@ -115,15 +120,16 @@ void CHypridle::run() { m_inhibitSleepBehavior = SLEEP_INHIBIT_NORMAL; break; case 2: { // auto (enable, but wait until locked if before_sleep_cmd contains hyprlock, or loginctl lock-session and lock_cmd contains hyprlock.) - if (std::string{*PSLEEPCMD}.contains("hyprlock")) - m_inhibitSleepBehavior = SLEEP_INHIBIT_WAIT_FOR_LOCKED; - else if (std::string{*PLOCKCMD}.contains("hyprlock") && std::string{*PSLEEPCMD}.contains("lock-session")) - m_inhibitSleepBehavior = SLEEP_INHIBIT_WAIT_FOR_LOCKED; + if (m_sWaylandState.lockNotifier && std::string{*PSLEEPCMD}.contains("hyprlock")) + m_inhibitSleepBehavior = SLEEP_INHIBIT_LOCK_NOTIFY; + else if (m_sWaylandState.lockNotifier && std::string{*PLOCKCMD}.contains("hyprlock") && std::string{*PSLEEPCMD}.contains("lock-session")) + m_inhibitSleepBehavior = SLEEP_INHIBIT_LOCK_NOTIFY; else m_inhibitSleepBehavior = SLEEP_INHIBIT_NORMAL; } break; case 3: // wait until locked - m_inhibitSleepBehavior = SLEEP_INHIBIT_WAIT_FOR_LOCKED; + if (m_sWaylandState.lockNotifier) + m_inhibitSleepBehavior = SLEEP_INHIBIT_LOCK_NOTIFY; break; default: Debug::log(ERR, "Invalid inhibit_sleep value: {}", **PINHIBIT); break; } @@ -131,11 +137,12 @@ void CHypridle::run() { switch (m_inhibitSleepBehavior) { case SLEEP_INHIBIT_NONE: Debug::log(LOG, "Sleep inhibition disabled"); break; case SLEEP_INHIBIT_NORMAL: Debug::log(LOG, "Sleep inhibition enabled"); break; - case SLEEP_INHIBIT_WAIT_FOR_LOCKED: Debug::log(LOG, "Sleep inhibition enabled - inhibiting until the wayland session gets locked"); break; + case SLEEP_INHIBIT_LOCK_NOTIFY: Debug::log(LOG, "Sleep inhibition enabled - inhibiting until the wayland session gets locked"); break; } setupDBUS(); - handleInhibitSleep(false); + if (m_inhibitSleepBehavior != SLEEP_INHIBIT_NONE) + inhibitSleep(); enterEventLoop(); } @@ -382,17 +389,20 @@ void CHypridle::onLocked() { Debug::log(LOG, "Wayland session got locked"); m_isLocked = true; - if (m_inhibitSleepBehavior == SLEEP_INHIBIT_WAIT_FOR_LOCKED) - uninhibitSleep(); - if (const auto* const PLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_lock_cmd"); PLOCKCMD && strlen(*PLOCKCMD) > 0) spawn(*PLOCKCMD); + + if (m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY) + uninhibitSleep(); } void CHypridle::onUnlocked() { Debug::log(LOG, "Wayland session got unlocked"); m_isLocked = false; + if (m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY) + inhibitSleep(); + if (const auto* const PUNLOCKCMD = (Hyprlang::STRING const*)g_pConfigManager->getValuePtr("general:on_unlock_cmd"); PUNLOCKCMD && strlen(*PUNLOCKCMD) > 0) spawn(*PUNLOCKCMD); } @@ -474,13 +484,13 @@ static void handleDbusSleep(sdbus::Message msg) { std::string cmd = toSleep ? *PSLEEPCMD : *PAFTERSLEEPCMD; if (!toSleep) - g_pHypridle->handleInhibitSleep(toSleep); + g_pHypridle->handleInhibitOnDbusSleep(toSleep); if (!cmd.empty()) spawn(cmd); if (toSleep) - g_pHypridle->handleInhibitSleep(toSleep); + g_pHypridle->handleInhibitOnDbusSleep(toSleep); } void handleDbusBlockInhibits(const std::string& inhibits) { @@ -623,13 +633,15 @@ void CHypridle::setupDBUS() { systemConnection.reset(); } -void CHypridle::handleInhibitSleep(bool toSleep) { - if (m_inhibitSleepBehavior == SLEEP_INHIBIT_NONE) +void CHypridle::handleInhibitOnDbusSleep(bool toSleep) { + if (m_inhibitSleepBehavior == SLEEP_INHIBIT_NONE || // + m_inhibitSleepBehavior == SLEEP_INHIBIT_LOCK_NOTIFY // Sleep inhibition handled via onLocked/onUnlocked + ) return; if (!toSleep) inhibitSleep(); - else if (m_inhibitSleepBehavior != SLEEP_INHIBIT_WAIT_FOR_LOCKED) + else uninhibitSleep(); } diff --git a/src/core/Hypridle.hpp b/src/core/Hypridle.hpp index 26aa9ef..67dc2d8 100644 --- a/src/core/Hypridle.hpp +++ b/src/core/Hypridle.hpp @@ -42,7 +42,7 @@ class CHypridle { bool unregisterDbusInhibitCookie(const SDbusInhibitCookie& cookie); bool unregisterDbusInhibitCookies(const std::string& ownerID); - void handleInhibitSleep(bool toSleep); + void handleInhibitOnDbusSleep(bool toSleep); void inhibitSleep(); void uninhibitSleep(); @@ -58,7 +58,7 @@ class CHypridle { enum { SLEEP_INHIBIT_NONE, SLEEP_INHIBIT_NORMAL, - SLEEP_INHIBIT_WAIT_FOR_LOCKED, + SLEEP_INHIBIT_LOCK_NOTIFY, } m_inhibitSleepBehavior; struct { From 1b579fe226b3079045fee358e4e0b8f72b483b72 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler Date: Thu, 23 Jan 2025 08:55:25 +0100 Subject: [PATCH 5/5] move to hyprwayland-scanner --- CMakeLists.txt | 74 ++++++++++++------------- README.md | 1 + flake.lock | 48 ++++++++++++----- flake.nix | 6 +++ nix/default.nix | 6 ++- nix/overlays.nix | 1 + src/core/Hypridle.cpp | 122 +++++++++++++++--------------------------- src/core/Hypridle.hpp | 26 ++++----- src/defines.hpp | 8 +++ 9 files changed, 147 insertions(+), 145 deletions(-) create mode 100644 src/defines.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d1db61..13545b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ message(STATUS "Checking deps...") find_package(Threads REQUIRED) find_package(PkgConfig REQUIRED) +find_package(hyprwayland-scanner 0.4.4 REQUIRED) pkg_check_modules( deps REQUIRED @@ -50,52 +51,47 @@ add_executable(hypridle ${SRCFILES}) target_link_libraries(hypridle PRIVATE rt Threads::Threads PkgConfig::deps) # protocols -find_program(WaylandScanner NAMES wayland-scanner) -message(STATUS "Found WaylandScanner at ${WaylandScanner}") -execute_process( - COMMAND pkg-config --variable=pkgdatadir wayland-protocols - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} - OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR - OUTPUT_STRIP_TRAILING_WHITESPACE) +pkg_get_variable(WAYLAND_PROTOCOLS_DIR wayland-protocols pkgdatadir) message(STATUS "Found wayland-protocols at ${WAYLAND_PROTOCOLS_DIR}") - -function(protocol protoPath protoName external) - if(external) - execute_process( - COMMAND ${WaylandScanner} client-header ${protoPath} - protocols/${protoName}-protocol.h - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process( - COMMAND ${WaylandScanner} private-code ${protoPath} - protocols/${protoName}-protocol.c - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - target_sources(hypridle PRIVATE protocols/${protoName}-protocol.c) - else() - execute_process( - COMMAND - ${WaylandScanner} client-header ${WAYLAND_PROTOCOLS_DIR}/${protoPath} - protocols/${protoName}-protocol.h - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - execute_process( - COMMAND - ${WaylandScanner} private-code ${WAYLAND_PROTOCOLS_DIR}/${protoPath} - protocols/${protoName}-protocol.c - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - target_sources(hypridle PRIVATE protocols/${protoName}-protocol.c) - endif() -endfunction() +pkg_get_variable(WAYLAND_SCANNER_PKGDATA_DIR wayland-scanner pkgdatadir) +message(STATUS "Found wayland-scanner pkgdatadir at ${WAYLAND_SCANNER_PKGDATA_DIR}") pkg_check_modules(hyprland_protocols_dep REQUIRED IMPORTED_TARGET hyprland-protocols>=0.6.0) pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir) -message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}") +message(STATUS "Found hyprland-protocols at ${HYPRLAND_PROTOCOLS}") + +function(protocolnew protoPath protoName external) + if(external) + set(path ${protoPath}) + else() + set(path ${WAYLAND_PROTOCOLS_DIR}/${protoPath}) + endif() + message(STATUS "Full proto path: ${path}") + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/${protoName}.cpp + ${CMAKE_SOURCE_DIR}/protocols/${protoName}.hpp + COMMAND hyprwayland-scanner --client ${path}/${protoName}.xml + ${CMAKE_SOURCE_DIR}/protocols/ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + target_sources(hypridle PRIVATE protocols/${protoName}.cpp + protocols/${protoName}.hpp) +endfunction() +function(protocolWayland) + add_custom_command( + OUTPUT ${CMAKE_SOURCE_DIR}/protocols/wayland.cpp + ${CMAKE_SOURCE_DIR}/protocols/wayland.hpp + COMMAND hyprwayland-scanner --wayland-enums --client + ${WAYLAND_SCANNER_PKGDATA_DIR}/wayland.xml ${CMAKE_SOURCE_DIR}/protocols/ + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) + target_sources(hypridle PRIVATE protocols/wayland.cpp protocols/wayland.hpp) +endfunction() make_directory(${CMAKE_SOURCE_DIR}/protocols) # we don't ship any custom ones so - # the dir won't be there -protocol("staging/ext-idle-notify/ext-idle-notify-v1.xml" "ext-idle-notify-v1" - false) -protocol("${HYPRLAND_PROTOCOLS}/protocols/hyprland-lock-notify-v1.xml" "hyprland-lock-notify-v1" - true) +protocolwayland() + +protocolnew("staging/ext-idle-notify" "ext-idle-notify-v1" false) +protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true) # Installation install(TARGETS hypridle) diff --git a/README.md b/README.md index e6584fc..3d07fd6 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ will make those events ignored. - wayland-protocols - hyprlang >= 0.4.0 - sdbus-c++ + - hyprwayland-scanner ## Building & Installation diff --git a/flake.lock b/flake.lock index 0c30975..fef031e 100644 --- a/flake.lock +++ b/flake.lock @@ -10,11 +10,11 @@ ] }, "locked": { - "lastModified": 1737127640, - "narHash": "sha256-mIQ3/axCZ4g8ySwWRbW4fJcyC9v55uAii3cqlJRtW8g=", + "lastModified": 1737556638, + "narHash": "sha256-laKgI3mr2qz6tas/q3tuGPxMdsGhBi/w+HO+hO2f1AY=", "owner": "hyprwm", "repo": "hyprland-protocols", - "rev": "455c055883d9639d4fcbfcedb4c6d12ce313791e", + "rev": "4c75dd5c015c8a0e5a34c6d02a018a650f57feb5", "type": "github" }, "original": { @@ -36,11 +36,11 @@ ] }, "locked": { - "lastModified": 1734364628, - "narHash": "sha256-ii8fzJfI953n/EmIxVvq64ZAwhvwuuPHWfGd61/mJG8=", + "lastModified": 1735393019, + "narHash": "sha256-NPpqA8rtmDLsEmZOmz+qR67zsB6Y503Jnv+nSFLKJZ8=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "16e59c1eb13d9fb6de066f54e7555eb5e8a4aba5", + "rev": "55608efdaa387af7bfdc0eddb404c409958efa43", "type": "github" }, "original": { @@ -59,11 +59,11 @@ ] }, "locked": { - "lastModified": 1733502241, - "narHash": "sha256-KAUNC4Dgq8WQjYov5auBw/usaHixhacvb7cRDd0AG/k=", + "lastModified": 1737534948, + "narHash": "sha256-tisC/LmBymvMqI+zNyY7kru85HdCe1eva9uo5ltGGc0=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "104117aed6dd68561be38b50f218190aa47f2cd8", + "rev": "59414c4cee9fd48821750ba0b649f8b3d657399f", "type": "github" }, "original": { @@ -72,13 +72,36 @@ "type": "github" } }, + "hyprwayland-scanner": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "systems": [ + "systems" + ] + }, + "locked": { + "lastModified": 1735493474, + "narHash": "sha256-fktzv4NaqKm94VAkAoVqO/nqQlw+X0/tJJNAeCSfzK4=", + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "rev": "de913476b59ee88685fdc018e77b8f6637a2ae0b", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1734119587, - "narHash": "sha256-AKU6qqskl0yf2+JdRdD0cfxX4b9x3KKV5RqA6wijmPM=", + "lastModified": 1737469691, + "narHash": "sha256-nmKOgAU48S41dTPIXAq0AHZSehWUn6ZPrUKijHAMmIk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "3566ab7246670a43abd2ffa913cc62dad9cdf7d5", + "rev": "9e4d5190a9482a1fb9d18adf0bdb83c6e506eaab", "type": "github" }, "original": { @@ -93,6 +116,7 @@ "hyprland-protocols": "hyprland-protocols", "hyprlang": "hyprlang", "hyprutils": "hyprutils", + "hyprwayland-scanner": "hyprwayland-scanner", "nixpkgs": "nixpkgs", "systems": "systems" } diff --git a/flake.nix b/flake.nix index 9dc4a54..40dbfe5 100644 --- a/flake.nix +++ b/flake.nix @@ -23,6 +23,12 @@ inputs.nixpkgs.follows = "nixpkgs"; inputs.systems.follows = "systems"; }; + + hyprwayland-scanner = { + url = "github:hyprwm/hyprwayland-scanner"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.systems.follows = "systems"; + }; }; outputs = { diff --git a/nix/default.nix b/nix/default.nix index f3b5a93..9e35005 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -1,12 +1,13 @@ { - lib, - stdenv, cmake, hyprland-protocols, hyprlang, hyprutils, + hyprwayland-scanner, + lib, pkg-config, sdbus-cpp, + stdenv, systemd, wayland, wayland-protocols, @@ -20,6 +21,7 @@ stdenv.mkDerivation { nativeBuildInputs = [ cmake + hyprwayland-scanner pkg-config wayland-scanner ]; diff --git a/nix/overlays.nix b/nix/overlays.nix index bde1308..4791768 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -16,6 +16,7 @@ in { 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 { diff --git a/src/core/Hypridle.cpp b/src/core/Hypridle.cpp index e65ab78..7d6ba38 100644 --- a/src/core/Hypridle.cpp +++ b/src/core/Hypridle.cpp @@ -1,8 +1,6 @@ #include "Hypridle.hpp" #include "../helpers/Log.hpp" #include "../config/ConfigManager.hpp" -#include "ext-idle-notify-v1-protocol.h" -#include "hyprland-lock-notify-v1-protocol.h" #include "signal.h" #include #include @@ -20,49 +18,32 @@ CHypridle::CHypridle() { } } -void handleGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { - g_pHypridle->onGlobal(data, registry, name, interface, version); -} - -void handleGlobalRemove(void* data, struct wl_registry* registry, uint32_t name) { - g_pHypridle->onGlobalRemoved(data, registry, name); -} - -inline const wl_registry_listener registryListener = { - .global = handleGlobal, - .global_remove = handleGlobalRemove, -}; - -void handleIdled(void* data, ext_idle_notification_v1* ext_idle_notification_v1) { - g_pHypridle->onIdled((CHypridle::SIdleListener*)data); -} - -void handleResumed(void* data, ext_idle_notification_v1* ext_idle_notification_v1) { - g_pHypridle->onResumed((CHypridle::SIdleListener*)data); -} - -inline const ext_idle_notification_v1_listener idleListener = { - .idled = handleIdled, - .resumed = handleResumed, -}; - -void handleLocked(void* data, hyprland_lock_notification_v1* hyprland_lock_notification_v1) { - g_pHypridle->onLocked(); -} - -void handleUnlocked(void* data, hyprland_lock_notification_v1* hyprland_lock_notification_v1) { - g_pHypridle->onUnlocked(); -} - -inline const hyprland_lock_notification_v1_listener lockListener = { - .locked = handleLocked, - .unlocked = handleUnlocked, -}; - void CHypridle::run() { - m_sWaylandState.registry = wl_display_get_registry(m_sWaylandState.display); + m_sWaylandState.registry = makeShared((wl_proxy*)wl_display_get_registry(m_sWaylandState.display)); + m_sWaylandState.registry->setGlobal([this](CCWlRegistry* r, uint32_t name, const char* interface, uint32_t version) { + const std::string IFACE = interface; + Debug::log(LOG, " | got iface: {} v{}", IFACE, version); - wl_registry_add_listener(m_sWaylandState.registry, ®istryListener, nullptr); + if (IFACE == ext_idle_notifier_v1_interface.name) { + m_sWaylandIdleState.notifier = + makeShared((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &ext_idle_notifier_v1_interface, version)); + Debug::log(LOG, " > Bound to {} v{}", IFACE, version); + } else if (IFACE == hyprland_lock_notifier_v1_interface.name) { + m_sWaylandState.lockNotifier = + makeShared((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &hyprland_lock_notifier_v1_interface, version)); + Debug::log(LOG, " > Bound to {} v{}", IFACE, version); + } else if (IFACE == wl_seat_interface.name) { + if (m_sWaylandState.seat) { + Debug::log(WARN, "Hypridle does not support multi-seat configurations. Only binding to the first seat."); + return; + } + + m_sWaylandState.seat = makeShared((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wl_seat_interface, version)); + Debug::log(LOG, " > Bound to {} v{}", IFACE, version); + } + }); + + m_sWaylandState.registry->setGlobalRemove([](CCWlRegistry* r, uint32_t name) { Debug::log(LOG, " | removed iface {}", name); }); wl_display_roundtrip(m_sWaylandState.display); @@ -77,21 +58,24 @@ void CHypridle::run() { Debug::log(LOG, "found {} rules", RULES.size()); for (size_t i = 0; i < RULES.size(); ++i) { - auto& l = m_sWaylandIdleState.listeners[i]; - const auto& r = RULES[i]; - l.notification = ext_idle_notifier_v1_get_idle_notification(m_sWaylandIdleState.notifier, r.timeout * 1000 /* ms */, m_sWaylandState.seat); - l.onRestore = r.onResume; - l.onTimeout = r.onTimeout; + auto& l = m_sWaylandIdleState.listeners[i]; + const auto& r = RULES[i]; + l.onRestore = r.onResume; + l.onTimeout = r.onTimeout; - ext_idle_notification_v1_add_listener(l.notification, &idleListener, &l); + l.notification = makeShared(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource())); + l.notification->setData(&m_sWaylandIdleState.listeners[i]); + + l.notification->setIdled([this](CCExtIdleNotificationV1* n) { onIdled((CHypridle::SIdleListener*)n->data()); }); + l.notification->setResumed([this](CCExtIdleNotificationV1* n) { onResumed((CHypridle::SIdleListener*)n->data()); }); } wl_display_roundtrip(m_sWaylandState.display); if (m_sWaylandState.lockNotifier) { - m_sWaylandState.lockNotification = hyprland_lock_notifier_v1_get_lock_notification(m_sWaylandState.lockNotifier); - - hyprland_lock_notification_v1_add_listener(m_sWaylandState.lockNotification, &lockListener, nullptr); + m_sWaylandState.lockNotification = makeShared(m_sWaylandState.lockNotifier->sendGetLockNotification()); + m_sWaylandState.lockNotification->setLocked([this](CCHyprlandLockNotificationV1* n) { onLocked(); }); + m_sWaylandState.lockNotification->setUnlocked([this](CCHyprlandLockNotificationV1* n) { onUnlocked(); }); } Debug::log(LOG, "wayland done, registering dbus"); @@ -247,31 +231,6 @@ void CHypridle::enterEventLoop() { Debug::log(ERR, "[core] Terminated"); } -void CHypridle::onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) { - const std::string IFACE = interface; - Debug::log(LOG, " | got iface: {} v{}", IFACE, version); - - if (IFACE == ext_idle_notifier_v1_interface.name) { - m_sWaylandIdleState.notifier = (ext_idle_notifier_v1*)wl_registry_bind(registry, name, &ext_idle_notifier_v1_interface, version); - Debug::log(LOG, " > Bound to {} v{}", IFACE, version); - } else if (IFACE == hyprland_lock_notifier_v1_interface.name) { - m_sWaylandState.lockNotifier = (hyprland_lock_notifier_v1*)wl_registry_bind(registry, name, &hyprland_lock_notifier_v1_interface, version); - Debug::log(LOG, " > Bound to {} v{}", IFACE, version); - } else if (IFACE == wl_seat_interface.name) { - if (m_sWaylandState.seat) { - Debug::log(WARN, "Hypridle does not support multi-seat configurations. Only binding to the first seat."); - return; - } - - m_sWaylandState.seat = (wl_seat*)wl_registry_bind(registry, name, &wl_seat_interface, version); - Debug::log(LOG, " > Bound to {} v{}", IFACE, version); - } -} - -void CHypridle::onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name) { - ; -} - static void spawn(const std::string& args) { Debug::log(LOG, "Executing {}", args); @@ -374,11 +333,14 @@ void CHypridle::onInhibit(bool lock) { auto& l = m_sWaylandIdleState.listeners[i]; const auto& r = RULES[i]; - ext_idle_notification_v1_destroy(l.notification); + l.notification->sendDestroy(); - l.notification = ext_idle_notifier_v1_get_idle_notification(m_sWaylandIdleState.notifier, r.timeout * 1000 /* ms */, m_sWaylandState.seat); + l.notification = + makeShared(m_sWaylandIdleState.notifier->sendGetIdleNotification(r.timeout * 1000 /* ms */, m_sWaylandState.seat->resource())); + l.notification->setData(&m_sWaylandIdleState.listeners[i]); - ext_idle_notification_v1_add_listener(l.notification, &idleListener, &l); + l.notification->setIdled([this](CCExtIdleNotificationV1* n) { onIdled((CHypridle::SIdleListener*)n->data()); }); + l.notification->setResumed([this](CCExtIdleNotificationV1* n) { onResumed((CHypridle::SIdleListener*)n->data()); }); } } diff --git a/src/core/Hypridle.hpp b/src/core/Hypridle.hpp index 67dc2d8..d7fc588 100644 --- a/src/core/Hypridle.hpp +++ b/src/core/Hypridle.hpp @@ -2,21 +2,23 @@ #include #include -#include #include #include -#include "ext-idle-notify-v1-protocol.h" -#include "hyprland-lock-notify-v1-protocol.h" +#include "wayland.hpp" +#include "ext-idle-notify-v1.hpp" +#include "hyprland-lock-notify-v1.hpp" + +#include "../defines.hpp" class CHypridle { public: CHypridle(); struct SIdleListener { - ext_idle_notification_v1* notification = nullptr; - std::string onTimeout = ""; - std::string onRestore = ""; + SP notification = nullptr; + std::string onTimeout = ""; + std::string onRestore = ""; }; struct SDbusInhibitCookie { @@ -62,15 +64,15 @@ class CHypridle { } m_inhibitSleepBehavior; struct { - wl_display* display = nullptr; - wl_registry* registry = nullptr; - wl_seat* seat = nullptr; - hyprland_lock_notifier_v1* lockNotifier = nullptr; - hyprland_lock_notification_v1* lockNotification = nullptr; + wl_display* display = nullptr; + SP registry = nullptr; + SP seat = nullptr; + SP lockNotifier = nullptr; + SP lockNotification = nullptr; } m_sWaylandState; struct { - ext_idle_notifier_v1* notifier = nullptr; + SP notifier = nullptr; std::vector listeners; } m_sWaylandIdleState; diff --git a/src/defines.hpp b/src/defines.hpp new file mode 100644 index 0000000..9b66def --- /dev/null +++ b/src/defines.hpp @@ -0,0 +1,8 @@ +#include "wayland.hpp" +#include "ext-idle-notify-v1.hpp" +#include "hyprland-lock-notify-v1.hpp" + +#include +using namespace Hyprutils::Memory; +#define SP CSharedPointer +#define WP CWeakPointer