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 {