summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com>2025-01-19 18:21:36 +0000
committerGitHub <noreply@github.com>2025-01-19 18:21:36 +0000
commit407453166ce2a52433c7b0b4ee92a41e47ef8f6d (patch)
tree441ec15b12061dd89ebf3bffb53b28daf514f547
parent8dd2cd41fb4c5a5eb6886cc190419b36084cabfa (diff)
protocols: add hyprland_lock_notify_v1 implementation (#9092)
-rw-r--r--CMakeLists.txt3
-rw-r--r--flake.lock6
-rw-r--r--protocols/meson.build3
-rw-r--r--src/managers/ProtocolManager.cpp5
-rw-r--r--src/protocols/LockNotify.cpp88
-rw-r--r--src/protocols/LockNotify.hpp50
-rw-r--r--src/protocols/SessionLock.cpp4
m---------subprojects/hyprland-protocols0
8 files changed, 153 insertions, 6 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a36d70fe..c022f3ba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -298,7 +298,7 @@ endfunction()
target_link_libraries(Hyprland OpenGL::EGL OpenGL::GL Threads::Threads)
-pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.4.0)
+pkg_check_modules(hyprland_protocols_dep hyprland-protocols>=0.6.0)
if(hyprland_protocols_dep_FOUND)
pkg_get_variable(HYPRLAND_PROTOCOLS hyprland-protocols pkgdatadir)
message(STATUS "hyprland-protocols dependency set to ${HYPRLAND_PROTOCOLS}")
@@ -329,6 +329,7 @@ protocolnew("protocols" "frog-color-management-v1" true)
protocolnew("protocols" "wayland-drm" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-ctm-control-v1" true)
protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-surface-v1" true)
+protocolnew("${HYPRLAND_PROTOCOLS}/protocols" "hyprland-lock-notify-v1" true)
protocolnew("staging/tearing-control" "tearing-control-v1" false)
protocolnew("staging/fractional-scale" "fractional-scale-v1" false)
diff --git a/flake.lock b/flake.lock
index f16ecaa7..7b85bd17 100644
--- a/flake.lock
+++ b/flake.lock
@@ -128,11 +128,11 @@
]
},
"locked": {
- "lastModified": 1735774328,
- "narHash": "sha256-vIRwLS9w+N99EU1aJ+XNOU6mJTxrUBa31i1r82l0V7s=",
+ "lastModified": 1737127640,
+ "narHash": "sha256-mIQ3/axCZ4g8ySwWRbW4fJcyC9v55uAii3cqlJRtW8g=",
"owner": "hyprwm",
"repo": "hyprland-protocols",
- "rev": "e3b6af97ddcfaafbda8e2828c719a5af84f662cb",
+ "rev": "455c055883d9639d4fcbfcedb4c6d12ce313791e",
"type": "github"
},
"original": {
diff --git a/protocols/meson.build b/protocols/meson.build
index fdbbf181..aa20940d 100644
--- a/protocols/meson.build
+++ b/protocols/meson.build
@@ -7,7 +7,7 @@ wayland_protos = dependency(
hyprland_protos = dependency(
'hyprland-protocols',
- version: '>=0.4',
+ version: '>=0.6',
fallback: 'hyprland-protocols',
)
@@ -40,6 +40,7 @@ protocols = [
hyprland_protocol_dir / 'protocols/hyprland-focus-grab-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-ctm-control-v1.xml',
hyprland_protocol_dir / 'protocols/hyprland-surface-v1.xml',
+ hyprland_protocol_dir / 'protocols/hyprland-lock-notify-v1.xml',
wayland_protocol_dir / 'staging/tearing-control/tearing-control-v1.xml',
wayland_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml',
wayland_protocol_dir / 'unstable/xdg-output/xdg-output-unstable-v1.xml',
diff --git a/src/managers/ProtocolManager.cpp b/src/managers/ProtocolManager.cpp
index b7d61f67..8e32bdec 100644
--- a/src/managers/ProtocolManager.cpp
+++ b/src/managers/ProtocolManager.cpp
@@ -20,6 +20,7 @@
#include "../protocols/OutputPower.hpp"
#include "../protocols/XDGActivation.hpp"
#include "../protocols/IdleNotify.hpp"
+#include "../protocols/LockNotify.hpp"
#include "../protocols/SessionLock.hpp"
#include "../protocols/InputMethodV2.hpp"
#include "../protocols/VirtualKeyboard.hpp"
@@ -145,6 +146,7 @@ CProtocolManager::CProtocolManager() {
PROTO::outputPower = std::make_unique<COutputPowerProtocol>(&zwlr_output_power_manager_v1_interface, 1, "OutputPower");
PROTO::activation = std::make_unique<CXDGActivationProtocol>(&xdg_activation_v1_interface, 1, "XDGActivation");
PROTO::idle = std::make_unique<CIdleNotifyProtocol>(&ext_idle_notifier_v1_interface, 1, "IdleNotify");
+ PROTO::lockNotify = std::make_unique<CLockNotifyProtocol>(&hyprland_lock_notifier_v1_interface, 1, "IdleNotify");
PROTO::sessionLock = std::make_unique<CSessionLockProtocol>(&ext_session_lock_manager_v1_interface, 1, "SessionLock");
PROTO::ime = std::make_unique<CInputMethodV2Protocol>(&zwp_input_method_manager_v2_interface, 1, "IMEv2");
PROTO::virtualKeyboard = std::make_unique<CVirtualKeyboardProtocol>(&zwp_virtual_keyboard_manager_v1_interface, 1, "VirtualKeyboard");
@@ -224,6 +226,7 @@ CProtocolManager::~CProtocolManager() {
PROTO::outputPower.reset();
PROTO::activation.reset();
PROTO::idle.reset();
+ PROTO::lockNotify.reset();
PROTO::sessionLock.reset();
PROTO::ime.reset();
PROTO::virtualKeyboard.reset();
@@ -296,7 +299,7 @@ bool CProtocolManager::isGlobalPrivileged(const wl_global* global) {
PROTO::xdgDialog->getGlobal(),
PROTO::singlePixel->getGlobal(),
PROTO::primarySelection->getGlobal(),
- PROTO::hyprlandSurface->getGlobal(),
+ PROTO::hyprlandSurface->getGlobal(),
PROTO::sync ? PROTO::sync->getGlobal() : nullptr,
PROTO::mesaDRM ? PROTO::mesaDRM->getGlobal() : nullptr,
PROTO::linuxDma ? PROTO::linuxDma->getGlobal() : nullptr,
diff --git a/src/protocols/LockNotify.cpp b/src/protocols/LockNotify.cpp
new file mode 100644
index 00000000..adcd0b2d
--- /dev/null
+++ b/src/protocols/LockNotify.cpp
@@ -0,0 +1,88 @@
+#include "LockNotify.hpp"
+
+CHyprlandLockNotification::CHyprlandLockNotification(SP<CHyprlandLockNotificationV1> resource_) : m_resource(resource_) {
+ if UNLIKELY (!m_resource->resource())
+ return;
+
+ m_resource->setDestroy([this](CHyprlandLockNotificationV1* r) { PROTO::lockNotify->destroyNotification(this); });
+ m_resource->setOnDestroy([this](CHyprlandLockNotificationV1* r) { PROTO::lockNotify->destroyNotification(this); });
+}
+
+bool CHyprlandLockNotification::good() {
+ return m_resource->resource();
+}
+
+void CHyprlandLockNotification::onLocked() {
+ if LIKELY (!m_locked)
+ m_resource->sendLocked();
+
+ m_locked = true;
+}
+
+void CHyprlandLockNotification::onUnlocked() {
+ if LIKELY (m_locked)
+ m_resource->sendUnlocked();
+
+ m_locked = false;
+}
+
+CLockNotifyProtocol::CLockNotifyProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ ;
+}
+
+void CLockNotifyProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_managers.emplace_back(std::make_unique<CHyprlandLockNotifierV1>(client, ver, id)).get();
+ RESOURCE->setOnDestroy([this](CHyprlandLockNotifierV1* p) { this->onManagerResourceDestroy(p->resource()); });
+
+ RESOURCE->setDestroy([this](CHyprlandLockNotifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); });
+ RESOURCE->setGetLockNotification([this](CHyprlandLockNotifierV1* pMgr, uint32_t id) { this->onGetNotification(pMgr, id); });
+}
+
+void CLockNotifyProtocol::onManagerResourceDestroy(wl_resource* res) {
+ std::erase_if(m_managers, [&](const auto& other) { return other->resource() == res; });
+}
+
+void CLockNotifyProtocol::destroyNotification(CHyprlandLockNotification* notif) {
+ std::erase_if(m_notifications, [&](const auto& other) { return other.get() == notif; });
+}
+
+void CLockNotifyProtocol::onGetNotification(CHyprlandLockNotifierV1* pMgr, uint32_t id) {
+ const auto CLIENT = pMgr->client();
+ const auto RESOURCE = m_notifications.emplace_back(makeShared<CHyprlandLockNotification>(makeShared<CHyprlandLockNotificationV1>(CLIENT, pMgr->version(), id))).get();
+
+ if UNLIKELY (!RESOURCE->good()) {
+ pMgr->noMemory();
+ m_notifications.pop_back();
+ return;
+ }
+
+ // Already locked?? Send locked right away
+ if UNLIKELY (m_isLocked)
+ m_notifications.back()->onLocked();
+}
+
+void CLockNotifyProtocol::onLocked() {
+ if UNLIKELY (m_isLocked) {
+ LOGM(ERR, "Not sending lock notification. Already locked!");
+ return;
+ }
+
+ for (auto const& n : m_notifications) {
+ n->onLocked();
+ }
+
+ m_isLocked = true;
+}
+
+void CLockNotifyProtocol::onUnlocked() {
+ if UNLIKELY (!m_isLocked) {
+ LOGM(ERR, "Not sending unlock notification. Not locked!");
+ return;
+ }
+
+ for (auto const& n : m_notifications) {
+ n->onUnlocked();
+ }
+
+ m_isLocked = false;
+}
diff --git a/src/protocols/LockNotify.hpp b/src/protocols/LockNotify.hpp
new file mode 100644
index 00000000..ec71034b
--- /dev/null
+++ b/src/protocols/LockNotify.hpp
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <memory>
+#include <vector>
+#include <unordered_map>
+#include "WaylandProtocol.hpp"
+#include "hyprland-lock-notify-v1.hpp"
+
+class CEventLoopTimer;
+
+class CHyprlandLockNotification {
+ public:
+ CHyprlandLockNotification(SP<CHyprlandLockNotificationV1> resource_);
+ ~CHyprlandLockNotification() = default;
+
+ bool good();
+ void onLocked();
+ void onUnlocked();
+
+ private:
+ SP<CHyprlandLockNotificationV1> m_resource;
+ bool m_locked = false;
+};
+
+class CLockNotifyProtocol : public IWaylandProtocol {
+ public:
+ CLockNotifyProtocol(const wl_interface* iface, const int& ver, const std::string& name);
+
+ virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id);
+
+ void onLocked();
+ void onUnlocked();
+
+ private:
+ void onManagerResourceDestroy(wl_resource* res);
+ void destroyNotification(CHyprlandLockNotification* notif);
+ void onGetNotification(CHyprlandLockNotifierV1* pMgr, uint32_t id);
+
+ bool m_isLocked = false;
+
+ //
+ std::vector<UP<CHyprlandLockNotifierV1>> m_managers;
+ std::vector<SP<CHyprlandLockNotification>> m_notifications;
+
+ friend class CHyprlandLockNotification;
+};
+
+namespace PROTO {
+ inline UP<CLockNotifyProtocol> lockNotify;
+};
diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp
index db65ee5f..8e215ffa 100644
--- a/src/protocols/SessionLock.cpp
+++ b/src/protocols/SessionLock.cpp
@@ -2,6 +2,7 @@
#include "../Compositor.hpp"
#include "../managers/SeatManager.hpp"
#include "FractionalScale.hpp"
+#include "LockNotify.hpp"
#include "core/Compositor.hpp"
#include "core/Output.hpp"
#include "../helpers/Monitor.hpp"
@@ -115,6 +116,8 @@ CSessionLock::CSessionLock(SP<CExtSessionLockV1> resource_) : resource(resource_
PROTO::sessionLock->locked = false;
+ PROTO::lockNotify->onUnlocked();
+
events.unlockAndDestroy.emit();
inert = true;
@@ -128,6 +131,7 @@ CSessionLock::~CSessionLock() {
void CSessionLock::sendLocked() {
resource->sendLocked();
+ PROTO::lockNotify->onLocked();
}
bool CSessionLock::good() {
diff --git a/subprojects/hyprland-protocols b/subprojects/hyprland-protocols
-Subproject 271df559dd30e4bc5ec6af02d017ac0aaabd63a
+Subproject 455c055883d9639d4fcbfcedb4c6d12ce313791