Skip to content

Commit

Permalink
protocols: add hyprland_lock_notify_v1 implementation (#9092)
Browse files Browse the repository at this point in the history
  • Loading branch information
PaideiaDilemma authored Jan 19, 2025
1 parent 8dd2cd4 commit 4074531
Show file tree
Hide file tree
Showing 8 changed files with 154 additions and 7 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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}")
Expand Down Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion protocols/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ wayland_protos = dependency(

hyprland_protos = dependency(
'hyprland-protocols',
version: '>=0.4',
version: '>=0.6',
fallback: 'hyprland-protocols',
)

Expand Down Expand Up @@ -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',
Expand Down
5 changes: 4 additions & 1 deletion src/managers/ProtocolManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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,
Expand Down
88 changes: 88 additions & 0 deletions src/protocols/LockNotify.cpp
Original file line number Diff line number Diff line change
@@ -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;
}
50 changes: 50 additions & 0 deletions src/protocols/LockNotify.hpp
Original file line number Diff line number Diff line change
@@ -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;
};
4 changes: 4 additions & 0 deletions src/protocols/SessionLock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -115,6 +116,8 @@ CSessionLock::CSessionLock(SP<CExtSessionLockV1> resource_) : resource(resource_

PROTO::sessionLock->locked = false;

PROTO::lockNotify->onUnlocked();

events.unlockAndDestroy.emit();

inert = true;
Expand All @@ -128,6 +131,7 @@ CSessionLock::~CSessionLock() {

void CSessionLock::sendLocked() {
resource->sendLocked();
PROTO::lockNotify->onLocked();
}

bool CSessionLock::good() {
Expand Down
2 changes: 1 addition & 1 deletion subprojects/hyprland-protocols

0 comments on commit 4074531

Please sign in to comment.