mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-22 20:49:49 +01:00
session-lock: move to new impl
This commit is contained in:
parent
d7a48cf478
commit
90e1411315
13 changed files with 424 additions and 148 deletions
|
@ -276,6 +276,7 @@ protocolNew("unstable/text-input/text-input-unstable-v3.xml" "text-input-unstabl
|
|||
protocolNew("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml" "pointer-constraints-unstable-v1" false)
|
||||
protocolNew("staging/xdg-activation/xdg-activation-v1.xml" "xdg-activation-v1" false)
|
||||
protocolNew("staging/ext-idle-notify/ext-idle-notify-v1.xml" "ext-idle-notify-v1" false)
|
||||
protocolNew("staging/ext-session-lock/ext-session-lock-v1.xml" "ext-session-lock-v1" false)
|
||||
|
||||
# tools
|
||||
add_subdirectory(hyprctl)
|
||||
|
|
|
@ -53,6 +53,7 @@ new_protocols = [
|
|||
[wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/xdg-activation/xdg-activation-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-idle-notify/ext-idle-notify-v1.xml'],
|
||||
[wl_protocol_dir, 'staging/ext-session-lock/ext-session-lock-v1.xml'],
|
||||
]
|
||||
|
||||
wl_protos_src = []
|
||||
|
|
|
@ -266,8 +266,6 @@ void CCompositor::initServer() {
|
|||
|
||||
m_sWLRHeadlessBackend = wlr_headless_backend_create(m_sWLEventLoop);
|
||||
|
||||
m_sWLRSessionLockMgr = wlr_session_lock_manager_v1_create(m_sWLDisplay);
|
||||
|
||||
if (!m_sWLRHeadlessBackend) {
|
||||
Debug::log(CRIT, "Couldn't create the headless backend");
|
||||
throwError("wlr_headless_backend_create() failed!");
|
||||
|
@ -315,7 +313,6 @@ void CCompositor::initAllSignals() {
|
|||
addWLSignal(&m_sWLRVKeyboardMgr->events.new_virtual_keyboard, &Events::listen_newVirtualKeyboard, m_sWLRVKeyboardMgr, "VKeyboardMgr");
|
||||
addWLSignal(&m_sWLRRenderer->events.destroy, &Events::listen_RendererDestroy, m_sWLRRenderer, "WLRRenderer");
|
||||
addWLSignal(&m_sWLRIMEMgr->events.input_method, &Events::listen_newIME, m_sWLRIMEMgr, "IMEMgr");
|
||||
addWLSignal(&m_sWLRSessionLockMgr->events.new_lock, &Events::listen_newSessionLock, m_sWLRSessionLockMgr, "SessionLockMgr");
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
addWLSignal(&m_sWRLDRMLeaseMgr->events.request, &Events::listen_leaseRequest, &m_sWRLDRMLeaseMgr, "DRM");
|
||||
|
@ -359,7 +356,6 @@ void CCompositor::removeAllSignals() {
|
|||
removeWLSignal(&Events::listen_newVirtualKeyboard);
|
||||
removeWLSignal(&Events::listen_RendererDestroy);
|
||||
removeWLSignal(&Events::listen_newIME);
|
||||
removeWLSignal(&Events::listen_newSessionLock);
|
||||
|
||||
if (m_sWRLDRMLeaseMgr)
|
||||
removeWLSignal(&Events::listen_leaseRequest);
|
||||
|
|
|
@ -67,7 +67,6 @@ class CCompositor {
|
|||
wlr_input_method_manager_v2* m_sWLRIMEMgr;
|
||||
wlr_linux_dmabuf_v1* m_sWLRLinuxDMABuf;
|
||||
wlr_backend* m_sWLRHeadlessBackend;
|
||||
wlr_session_lock_manager_v1* m_sWLRSessionLockMgr;
|
||||
// ------------------------------------------------- //
|
||||
|
||||
std::string m_szHyprTempDataRoot = "";
|
||||
|
|
|
@ -193,9 +193,3 @@ void Events::listener_newIME(wl_listener* listener, void* data) {
|
|||
|
||||
g_pInputManager->m_sIMERelay.onNewIME((wlr_input_method_v2*)data);
|
||||
}
|
||||
|
||||
void Events::listener_newSessionLock(wl_listener* listener, void* data) {
|
||||
Debug::log(LOG, "New session lock!");
|
||||
|
||||
g_pSessionLockManager->onNewSessionLock((wlr_session_lock_v1*)data);
|
||||
}
|
||||
|
|
|
@ -90,7 +90,6 @@ extern "C" {
|
|||
#include <wlr/backend/headless.h>
|
||||
#include <wlr/backend/multi.h>
|
||||
#include <wlr/backend/wayland.h>
|
||||
#include <wlr/types/wlr_session_lock_v1.h>
|
||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/transform.h>
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "../protocols/OutputPower.hpp"
|
||||
#include "../protocols/XDGActivation.hpp"
|
||||
#include "../protocols/IdleNotify.hpp"
|
||||
#include "../protocols/SessionLock.hpp"
|
||||
|
||||
#include "tearing-control-v1.hpp"
|
||||
#include "fractional-scale-v1.hpp"
|
||||
|
@ -37,6 +38,7 @@
|
|||
#include "wlr-output-power-management-unstable-v1.hpp"
|
||||
#include "xdg-activation-v1.hpp"
|
||||
#include "ext-idle-notify-v1.hpp"
|
||||
#include "ext-session-lock-v1.hpp"
|
||||
|
||||
CProtocolManager::CProtocolManager() {
|
||||
|
||||
|
@ -58,6 +60,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::sessionLock = std::make_unique<CSessionLockProtocol>(&ext_session_lock_manager_v1_interface, 1, "SessionLock");
|
||||
|
||||
// Old protocol implementations.
|
||||
// TODO: rewrite them to use hyprwayland-scanner.
|
||||
|
|
|
@ -2,141 +2,92 @@
|
|||
#include "../Compositor.hpp"
|
||||
#include "../config/ConfigValue.hpp"
|
||||
#include "../protocols/FractionalScale.hpp"
|
||||
#include "../protocols/SessionLock.hpp"
|
||||
|
||||
static void handleSurfaceMap(void* owner, void* data) {
|
||||
const auto PSURFACE = (SSessionLockSurface*)owner;
|
||||
SSessionLockSurface::SSessionLockSurface(SP<CSessionLockSurface> surface_) : surface(surface_) {
|
||||
pWlrSurface = surface.lock()->surface();
|
||||
|
||||
Debug::log(LOG, "SessionLockSurface {:x} mapped", (uintptr_t)PSURFACE);
|
||||
listeners.map = surface_->events.map.registerListener([this](std::any data) {
|
||||
mapped = true;
|
||||
|
||||
PSURFACE->mapped = true;
|
||||
g_pCompositor->focusSurface(surface.lock()->surface());
|
||||
|
||||
g_pCompositor->focusSurface(PSURFACE->pWlrLockSurface->surface);
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(iMonitorID);
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PSURFACE->iMonitorID);
|
||||
if (PMONITOR)
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
});
|
||||
|
||||
if (PMONITOR)
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
listeners.destroy = surface_->events.destroy.registerListener([this](std::any data) {
|
||||
if (pWlrSurface == g_pCompositor->m_pLastFocus)
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
|
||||
g_pSessionLockManager->removeSessionLockSurface(this);
|
||||
});
|
||||
|
||||
listeners.commit = surface_->events.commit.registerListener([this](std::any data) {
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(iMonitorID);
|
||||
|
||||
if (PMONITOR)
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
});
|
||||
}
|
||||
|
||||
static void handleSurfaceCommit(void* owner, void* data) {
|
||||
const auto PSURFACE = (SSessionLockSurface*)owner;
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromID(PSURFACE->iMonitorID);
|
||||
|
||||
if (PMONITOR)
|
||||
g_pHyprRenderer->damageMonitor(PMONITOR);
|
||||
CSessionLockManager::CSessionLockManager() {
|
||||
listeners.newLock = PROTO::sessionLock->events.newLock.registerListener([this](std::any data) { this->onNewSessionLock(std::any_cast<SP<CSessionLock>>(data)); });
|
||||
}
|
||||
|
||||
static void handleSurfaceDestroy(void* owner, void* data) {
|
||||
const auto PSURFACE = (SSessionLockSurface*)owner;
|
||||
|
||||
Debug::log(LOG, "SessionLockSurface {:x} destroyed", (uintptr_t)PSURFACE);
|
||||
|
||||
PSURFACE->hyprListener_commit.removeCallback();
|
||||
PSURFACE->hyprListener_destroy.removeCallback();
|
||||
PSURFACE->hyprListener_map.removeCallback();
|
||||
|
||||
if (PSURFACE->pWlrLockSurface->surface == g_pCompositor->m_pLastFocus)
|
||||
g_pCompositor->m_pLastFocus = nullptr;
|
||||
|
||||
g_pSessionLockManager->removeSessionLockSurface(PSURFACE);
|
||||
}
|
||||
|
||||
void CSessionLockManager::onNewSessionLock(wlr_session_lock_v1* pWlrLock) {
|
||||
void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) {
|
||||
|
||||
static auto PALLOWRELOCK = CConfigValue<Hyprlang::INT>("misc:allow_session_lock_restore");
|
||||
|
||||
if (m_sSessionLock.active && (!*PALLOWRELOCK || m_sSessionLock.pWlrLock)) {
|
||||
Debug::log(LOG, "Attempted to lock a locked session!");
|
||||
wlr_session_lock_v1_destroy(pWlrLock);
|
||||
if (PROTO::sessionLock->isLocked() && !*PALLOWRELOCK) {
|
||||
Debug::log(LOG, "Cannot re-lock, misc:allow_session_lock_restore is disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug::log(LOG, "Session got locked by {:x}", (uintptr_t)pWlrLock);
|
||||
Debug::log(LOG, "Session got locked by {:x}", (uintptr_t)pLock.get());
|
||||
|
||||
m_sSessionLock.pWlrLock = pWlrLock;
|
||||
m_pSessionLock = std::make_unique<SSessionLock>();
|
||||
m_pSessionLock->lock = pLock;
|
||||
|
||||
g_pCompositor->m_sSeat.exclusiveClient = wl_resource_get_client(pWlrLock->resource);
|
||||
m_pSessionLock->listeners.newSurface = pLock->events.newLockSurface.registerListener([this](std::any data) {
|
||||
auto SURFACE = std::any_cast<SP<CSessionLockSurface>>(data);
|
||||
|
||||
m_sSessionLock.hyprListener_newSurface.initCallback(
|
||||
&pWlrLock->events.new_surface,
|
||||
[&](void* owner, void* data) {
|
||||
const auto PSURFACE = &*m_sSessionLock.vSessionLockSurfaces.emplace_back(std::make_unique<SSessionLockSurface>());
|
||||
const auto PMONITOR = SURFACE->monitor();
|
||||
|
||||
const auto PWLRSURFACE = (wlr_session_lock_surface_v1*)data;
|
||||
const auto NEWSURFACE = m_pSessionLock->vSessionLockSurfaces.emplace_back(std::make_unique<SSessionLockSurface>(SURFACE)).get();
|
||||
NEWSURFACE->iMonitorID = PMONITOR->ID;
|
||||
PROTO::fractional->sendScale(SURFACE->surface(), PMONITOR->scale);
|
||||
});
|
||||
|
||||
const auto PMONITOR = g_pCompositor->getMonitorFromOutput(PWLRSURFACE->output);
|
||||
m_pSessionLock->listeners.unlock = pLock->events.unlockAndDestroy.registerListener([this](std::any data) {
|
||||
m_pSessionLock.reset();
|
||||
g_pInputManager->refocus();
|
||||
|
||||
if (!PMONITOR) {
|
||||
m_sSessionLock.vSessionLockSurfaces.pop_back();
|
||||
return;
|
||||
}
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
});
|
||||
|
||||
PSURFACE->pWlrLockSurface = PWLRSURFACE;
|
||||
PSURFACE->iMonitorID = PMONITOR->ID;
|
||||
m_pSessionLock->listeners.destroy = pLock->events.destroyed.registerListener([this](std::any data) {
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
|
||||
PROTO::fractional->sendScale(PSURFACE->pWlrLockSurface->surface, PMONITOR->scale);
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
});
|
||||
|
||||
wlr_session_lock_surface_v1_configure(PWLRSURFACE, PMONITOR->vecSize.x, PMONITOR->vecSize.y);
|
||||
|
||||
PSURFACE->hyprListener_map.initCallback(&PWLRSURFACE->surface->events.map, &handleSurfaceMap, PSURFACE, "SSessionLockSurface");
|
||||
PSURFACE->hyprListener_destroy.initCallback(&PWLRSURFACE->events.destroy, &handleSurfaceDestroy, PSURFACE, "SSessionLockSurface");
|
||||
PSURFACE->hyprListener_commit.initCallback(&PWLRSURFACE->surface->events.commit, &handleSurfaceCommit, PSURFACE, "SSessionLockSurface");
|
||||
},
|
||||
pWlrLock, "wlr_session_lock_v1");
|
||||
|
||||
m_sSessionLock.hyprListener_unlock.initCallback(
|
||||
&pWlrLock->events.unlock,
|
||||
[&](void* owner, void* data) {
|
||||
Debug::log(LOG, "Session Unlocked");
|
||||
|
||||
m_sSessionLock.hyprListener_destroy.removeCallback();
|
||||
m_sSessionLock.hyprListener_newSurface.removeCallback();
|
||||
m_sSessionLock.hyprListener_unlock.removeCallback();
|
||||
|
||||
m_sSessionLock.active = false;
|
||||
|
||||
m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.clear();
|
||||
|
||||
g_pCompositor->m_sSeat.exclusiveClient = nullptr;
|
||||
g_pInputManager->refocus();
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
},
|
||||
pWlrLock, "wlr_session_lock_v1");
|
||||
|
||||
m_sSessionLock.hyprListener_destroy.initCallback(
|
||||
&pWlrLock->events.destroy,
|
||||
[&](void* owner, void* data) {
|
||||
Debug::log(LOG, "Session Lock Abandoned");
|
||||
|
||||
m_sSessionLock.hyprListener_destroy.removeCallback();
|
||||
m_sSessionLock.hyprListener_newSurface.removeCallback();
|
||||
m_sSessionLock.hyprListener_unlock.removeCallback();
|
||||
|
||||
g_pCompositor->m_sSeat.exclusiveClient = nullptr;
|
||||
|
||||
g_pCompositor->focusSurface(nullptr);
|
||||
|
||||
m_sSessionLock.pWlrLock = nullptr;
|
||||
|
||||
for (auto& m : g_pCompositor->m_vMonitors)
|
||||
g_pHyprRenderer->damageMonitor(m.get());
|
||||
},
|
||||
pWlrLock, "wlr_session_lock_v1");
|
||||
|
||||
wlr_session_lock_v1_send_locked(pWlrLock);
|
||||
|
||||
g_pSessionLockManager->activateLock();
|
||||
pLock->sendLocked();
|
||||
}
|
||||
|
||||
bool CSessionLockManager::isSessionLocked() {
|
||||
return m_sSessionLock.active;
|
||||
return PROTO::sessionLock->isLocked();
|
||||
}
|
||||
|
||||
SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64_t id) {
|
||||
for (auto& sls : m_sSessionLock.vSessionLockSurfaces) {
|
||||
if (!m_pSessionLock)
|
||||
return nullptr;
|
||||
|
||||
for (auto& sls : m_pSessionLock->vSessionLockSurfaces) {
|
||||
if (sls->iMonitorID == id) {
|
||||
if (sls->mapped)
|
||||
return sls.get();
|
||||
|
@ -151,11 +102,14 @@ SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64
|
|||
// We don't want the red screen to flash.
|
||||
// This violates the protocol a bit, but tries to handle the missing sync between a lock surface beeing created and the red screen beeing drawn.
|
||||
float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) {
|
||||
const auto& NOMAPPEDSURFACETIMER = m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.find(id);
|
||||
if (!m_pSessionLock)
|
||||
return 0.F;
|
||||
|
||||
if (NOMAPPEDSURFACETIMER == m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.end()) {
|
||||
m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers.emplace(id, CTimer());
|
||||
m_sSessionLock.mMonitorsWithoutMappedSurfaceTimers[id].reset();
|
||||
const auto& NOMAPPEDSURFACETIMER = m_pSessionLock->mMonitorsWithoutMappedSurfaceTimers.find(id);
|
||||
|
||||
if (NOMAPPEDSURFACETIMER == m_pSessionLock->mMonitorsWithoutMappedSurfaceTimers.end()) {
|
||||
m_pSessionLock->mMonitorsWithoutMappedSurfaceTimers.emplace(id, CTimer());
|
||||
m_pSessionLock->mMonitorsWithoutMappedSurfaceTimers[id].reset();
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
|
@ -163,8 +117,14 @@ float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) {
|
|||
}
|
||||
|
||||
bool CSessionLockManager::isSurfaceSessionLock(wlr_surface* pSurface) {
|
||||
for (auto& sls : m_sSessionLock.vSessionLockSurfaces) {
|
||||
if (sls->pWlrLockSurface->surface == pSurface)
|
||||
// TODO: this has some edge cases when it's wrong (e.g. destroyed lock but not yet surfaces)
|
||||
// but can be easily fixed when I rewrite wlr_surface
|
||||
|
||||
if (!m_pSessionLock)
|
||||
return false;
|
||||
|
||||
for (auto& sls : m_pSessionLock->vSessionLockSurfaces) {
|
||||
if (sls->surface.lock()->surface() == pSurface)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -172,20 +132,23 @@ bool CSessionLockManager::isSurfaceSessionLock(wlr_surface* pSurface) {
|
|||
}
|
||||
|
||||
void CSessionLockManager::removeSessionLockSurface(SSessionLockSurface* pSLS) {
|
||||
std::erase_if(m_sSessionLock.vSessionLockSurfaces, [&](const auto& other) { return pSLS == other.get(); });
|
||||
if (!m_pSessionLock)
|
||||
return;
|
||||
|
||||
std::erase_if(m_pSessionLock->vSessionLockSurfaces, [&](const auto& other) { return pSLS == other.get(); });
|
||||
|
||||
if (g_pCompositor->m_pLastFocus)
|
||||
return;
|
||||
|
||||
for (auto& sls : m_sSessionLock.vSessionLockSurfaces) {
|
||||
for (auto& sls : m_pSessionLock->vSessionLockSurfaces) {
|
||||
if (!sls->mapped)
|
||||
continue;
|
||||
|
||||
g_pCompositor->focusSurface(sls->pWlrLockSurface->surface);
|
||||
g_pCompositor->focusSurface(sls->surface.lock()->surface());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CSessionLockManager::activateLock() {
|
||||
m_sSessionLock.active = true;
|
||||
}
|
||||
bool CSessionLockManager::isSessionLockPresent() {
|
||||
return m_pSessionLock && !m_pSessionLock->vSessionLockSurfaces.empty();
|
||||
}
|
||||
|
|
|
@ -2,51 +2,65 @@
|
|||
|
||||
#include "../defines.hpp"
|
||||
#include "../helpers/Timer.hpp"
|
||||
#include "../helpers/signal/Listener.hpp"
|
||||
#include <cstdint>
|
||||
#include <unordered_map>
|
||||
|
||||
class CSessionLockSurface;
|
||||
class CSessionLock;
|
||||
|
||||
struct SSessionLockSurface {
|
||||
wlr_session_lock_surface_v1* pWlrLockSurface = nullptr;
|
||||
uint64_t iMonitorID = -1;
|
||||
SSessionLockSurface(SP<CSessionLockSurface> surface_);
|
||||
|
||||
bool mapped = false;
|
||||
WP<CSessionLockSurface> surface;
|
||||
wlr_surface* pWlrSurface = nullptr;
|
||||
uint64_t iMonitorID = -1;
|
||||
|
||||
DYNLISTENER(map);
|
||||
DYNLISTENER(destroy);
|
||||
DYNLISTENER(commit);
|
||||
bool mapped = false;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener map;
|
||||
CHyprSignalListener destroy;
|
||||
CHyprSignalListener commit;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
struct SSessionLock {
|
||||
bool active = false;
|
||||
wlr_session_lock_v1* pWlrLock = nullptr;
|
||||
WP<CSessionLock> lock;
|
||||
|
||||
std::vector<std::unique_ptr<SSessionLockSurface>> vSessionLockSurfaces;
|
||||
std::unordered_map<uint64_t, CTimer> mMonitorsWithoutMappedSurfaceTimers;
|
||||
|
||||
DYNLISTENER(newSurface);
|
||||
DYNLISTENER(unlock);
|
||||
DYNLISTENER(destroy);
|
||||
struct {
|
||||
CHyprSignalListener newSurface;
|
||||
CHyprSignalListener unlock;
|
||||
CHyprSignalListener destroy;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CSessionLockManager {
|
||||
public:
|
||||
CSessionLockManager() = default;
|
||||
CSessionLockManager();
|
||||
~CSessionLockManager() = default;
|
||||
|
||||
void onNewSessionLock(wlr_session_lock_v1*);
|
||||
SSessionLockSurface* getSessionLockSurfaceForMonitor(uint64_t);
|
||||
|
||||
float getRedScreenAlphaForMonitor(uint64_t);
|
||||
|
||||
bool isSessionLocked();
|
||||
bool isSessionLockPresent();
|
||||
bool isSurfaceSessionLock(wlr_surface*);
|
||||
|
||||
void removeSessionLockSurface(SSessionLockSurface*);
|
||||
|
||||
void activateLock();
|
||||
|
||||
private:
|
||||
SSessionLock m_sSessionLock;
|
||||
UP<SSessionLock> m_pSessionLock;
|
||||
|
||||
struct {
|
||||
CHyprSignalListener newLock;
|
||||
} listeners;
|
||||
|
||||
void onNewSessionLock(SP<CSessionLock> pWlrLock);
|
||||
};
|
||||
|
||||
inline std::unique_ptr<CSessionLockManager> g_pSessionLockManager;
|
|
@ -9,6 +9,7 @@
|
|||
#include "../../protocols/RelativePointer.hpp"
|
||||
#include "../../protocols/PointerConstraints.hpp"
|
||||
#include "../../protocols/IdleNotify.hpp"
|
||||
#include "../../protocols/SessionLock.hpp"
|
||||
|
||||
CInputManager::CInputManager() {
|
||||
m_sListeners.setCursorShape = PROTO::cursorShape->events.setShape.registerListener([this](std::any data) {
|
||||
|
@ -236,7 +237,7 @@ void CInputManager::mouseMoveUnified(uint32_t time, bool refocus) {
|
|||
if (!PSLS)
|
||||
return;
|
||||
|
||||
foundSurface = PSLS->pWlrLockSurface->surface;
|
||||
foundSurface = PSLS->surface.lock()->surface();
|
||||
surfacePos = PMONITOR->vecPosition;
|
||||
}
|
||||
|
||||
|
|
202
src/protocols/SessionLock.cpp
Normal file
202
src/protocols/SessionLock.cpp
Normal file
|
@ -0,0 +1,202 @@
|
|||
#include "SessionLock.hpp"
|
||||
#include "../Compositor.hpp"
|
||||
|
||||
#define LOGM PROTO::sessionLock->protoLog
|
||||
|
||||
CSessionLockSurface::CSessionLockSurface(SP<CExtSessionLockSurfaceV1> resource_, wlr_surface* surface_, CMonitor* pMonitor_, WP<CSessionLock> owner_) :
|
||||
resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) {
|
||||
if (!resource->resource())
|
||||
return;
|
||||
|
||||
resource->setDestroy([this](CExtSessionLockSurfaceV1* r) {
|
||||
events.destroy.emit();
|
||||
PROTO::sessionLock->destroyResource(this);
|
||||
});
|
||||
resource->setOnDestroy([this](CExtSessionLockSurfaceV1* r) {
|
||||
events.destroy.emit();
|
||||
PROTO::sessionLock->destroyResource(this);
|
||||
});
|
||||
|
||||
resource->setAckConfigure([this](CExtSessionLockSurfaceV1* r, uint32_t serial) { ackdConfigure = true; });
|
||||
|
||||
hyprListener_surfaceCommit.initCallback(
|
||||
&pSurface->events.commit,
|
||||
[this](void* owner, void* data) {
|
||||
if (!pSurface->current.buffer) {
|
||||
LOGM(ERR, "SessionLock attached a null buffer");
|
||||
wl_resource_post_error(resource->resource(), EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER, "Null buffer attached");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ackdConfigure) {
|
||||
LOGM(ERR, "SessionLock committed without an ack");
|
||||
wl_resource_post_error(resource->resource(), EXT_SESSION_LOCK_SURFACE_V1_ERROR_COMMIT_BEFORE_FIRST_ACK, "Committed surface before first ack");
|
||||
return;
|
||||
}
|
||||
|
||||
if (committed)
|
||||
events.commit.emit();
|
||||
else
|
||||
events.map.emit();
|
||||
committed = true;
|
||||
},
|
||||
this, "SessionLockSurface");
|
||||
|
||||
hyprListener_surfaceDestroy.initCallback(
|
||||
&pSurface->events.destroy,
|
||||
[this](void* owner, void* data) {
|
||||
LOGM(WARN, "SessionLockSurface object remains but surface is being destroyed???");
|
||||
hyprListener_surfaceCommit.removeCallback();
|
||||
hyprListener_surfaceDestroy.removeCallback();
|
||||
pSurface = nullptr;
|
||||
},
|
||||
this, "SessionLockSurface");
|
||||
|
||||
sendConfigure();
|
||||
|
||||
listeners.monitorMode = pMonitor->events.modeChanged.registerListener([this](std::any data) { sendConfigure(); });
|
||||
}
|
||||
|
||||
CSessionLockSurface::~CSessionLockSurface() {
|
||||
hyprListener_surfaceCommit.removeCallback();
|
||||
hyprListener_surfaceDestroy.removeCallback();
|
||||
events.destroy.emit(); // just in case.
|
||||
}
|
||||
|
||||
void CSessionLockSurface::sendConfigure() {
|
||||
const auto CLIENT = wl_resource_get_client(resource->resource());
|
||||
const auto SERIAL = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, CLIENT));
|
||||
resource->sendConfigure(SERIAL, pMonitor->vecSize.x, pMonitor->vecSize.y);
|
||||
}
|
||||
|
||||
bool CSessionLockSurface::good() {
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
bool CSessionLockSurface::inert() {
|
||||
return sessionLock.expired();
|
||||
}
|
||||
|
||||
CMonitor* CSessionLockSurface::monitor() {
|
||||
return pMonitor;
|
||||
}
|
||||
|
||||
wlr_surface* CSessionLockSurface::surface() {
|
||||
return pSurface;
|
||||
}
|
||||
|
||||
CSessionLock::CSessionLock(SP<CExtSessionLockV1> resource_) : resource(resource_) {
|
||||
if (!resource->resource())
|
||||
return;
|
||||
|
||||
resource->setDestroy([this](CExtSessionLockV1* r) { PROTO::sessionLock->destroyResource(this); });
|
||||
resource->setOnDestroy([this](CExtSessionLockV1* r) { PROTO::sessionLock->destroyResource(this); });
|
||||
|
||||
resource->setGetLockSurface([this](CExtSessionLockV1* r, uint32_t id, wl_resource* surf, wl_resource* output) {
|
||||
if (inert) {
|
||||
LOGM(ERR, "Lock is trying to send getLockSurface after it's inert");
|
||||
return;
|
||||
}
|
||||
|
||||
PROTO::sessionLock->onGetLockSurface(r, id, surf, output);
|
||||
});
|
||||
|
||||
resource->setUnlockAndDestroy([this](CExtSessionLockV1* r) {
|
||||
events.unlockAndDestroy.emit();
|
||||
inert = true;
|
||||
PROTO::sessionLock->locked = false;
|
||||
PROTO::sessionLock->destroyResource(this);
|
||||
});
|
||||
}
|
||||
|
||||
CSessionLock::~CSessionLock() {
|
||||
events.destroyed.emit();
|
||||
}
|
||||
|
||||
void CSessionLock::sendLocked() {
|
||||
resource->sendLocked();
|
||||
}
|
||||
|
||||
bool CSessionLock::good() {
|
||||
return resource->resource();
|
||||
}
|
||||
|
||||
CSessionLockProtocol::CSessionLockProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
|
||||
;
|
||||
}
|
||||
|
||||
void CSessionLockProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
|
||||
const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CExtSessionLockManagerV1>(client, ver, id)).get();
|
||||
RESOURCE->setOnDestroy([this](CExtSessionLockManagerV1* p) { this->onManagerResourceDestroy(p->resource()); });
|
||||
|
||||
RESOURCE->setDestroy([this](CExtSessionLockManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); });
|
||||
RESOURCE->setLock([this](CExtSessionLockManagerV1* pMgr, uint32_t id) { this->onLock(pMgr, id); });
|
||||
}
|
||||
|
||||
void CSessionLockProtocol::onManagerResourceDestroy(wl_resource* res) {
|
||||
std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
|
||||
}
|
||||
|
||||
void CSessionLockProtocol::destroyResource(CSessionLock* lock) {
|
||||
std::erase_if(m_vLocks, [&](const auto& other) { return other.get() == lock; });
|
||||
}
|
||||
|
||||
void CSessionLockProtocol::destroyResource(CSessionLockSurface* surf) {
|
||||
std::erase_if(m_vLockSurfaces, [&](const auto& other) { return other.get() == surf; });
|
||||
}
|
||||
|
||||
void CSessionLockProtocol::onLock(CExtSessionLockManagerV1* pMgr, uint32_t id) {
|
||||
|
||||
LOGM(LOG, "New sessionLock with id {}", id);
|
||||
|
||||
const auto CLIENT = wl_resource_get_client(pMgr->resource());
|
||||
const auto RESOURCE = m_vLocks.emplace_back(std::make_unique<CSessionLock>(std::make_shared<CExtSessionLockV1>(CLIENT, wl_resource_get_version(pMgr->resource()), id)));
|
||||
|
||||
if (!RESOURCE->good()) {
|
||||
wl_resource_post_no_memory(pMgr->resource());
|
||||
m_vLocks.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_vLocks.size() > 1) {
|
||||
LOGM(ERR, "Tried to lock a locked session");
|
||||
RESOURCE->resource->sendFinished();
|
||||
RESOURCE->inert = true;
|
||||
return;
|
||||
}
|
||||
|
||||
locked = true;
|
||||
|
||||
events.newLock.emit(RESOURCE);
|
||||
}
|
||||
|
||||
void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id, wl_resource* surface, wl_resource* output) {
|
||||
LOGM(LOG, "New sessionLockSurface with id {}", id);
|
||||
|
||||
auto PSURFACE = wlr_surface_from_resource(surface);
|
||||
auto PMONITOR = g_pCompositor->getMonitorFromOutput(wlr_output_from_resource(output));
|
||||
|
||||
SP<CSessionLock> sessionLock;
|
||||
for (auto& l : m_vLocks) {
|
||||
if (l->resource.get() == lock) {
|
||||
sessionLock = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const auto CLIENT = wl_resource_get_client(lock->resource());
|
||||
const auto RESOURCE = m_vLockSurfaces.emplace_back(
|
||||
std::make_unique<CSessionLockSurface>(std::make_shared<CExtSessionLockSurfaceV1>(CLIENT, wl_resource_get_version(lock->resource()), id), PSURFACE, PMONITOR, sessionLock));
|
||||
|
||||
if (!RESOURCE->good()) {
|
||||
wl_resource_post_no_memory(lock->resource());
|
||||
m_vLockSurfaces.pop_back();
|
||||
return;
|
||||
}
|
||||
|
||||
sessionLock->events.newLockSurface.emit(RESOURCE);
|
||||
}
|
||||
|
||||
bool CSessionLockProtocol::isLocked() {
|
||||
return locked;
|
||||
}
|
102
src/protocols/SessionLock.hpp
Normal file
102
src/protocols/SessionLock.hpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "WaylandProtocol.hpp"
|
||||
#include "ext-session-lock-v1.hpp"
|
||||
#include "../helpers/signal/Signal.hpp"
|
||||
|
||||
class CMonitor;
|
||||
class CSessionLock;
|
||||
|
||||
class CSessionLockSurface {
|
||||
public:
|
||||
CSessionLockSurface(SP<CExtSessionLockSurfaceV1> resource_, wlr_surface* surface_, CMonitor* pMonitor_, WP<CSessionLock> owner_);
|
||||
~CSessionLockSurface();
|
||||
|
||||
bool good();
|
||||
bool inert();
|
||||
CMonitor* monitor();
|
||||
wlr_surface* surface();
|
||||
|
||||
struct {
|
||||
CSignal map;
|
||||
CSignal destroy;
|
||||
CSignal commit;
|
||||
} events;
|
||||
|
||||
private:
|
||||
SP<CExtSessionLockSurfaceV1> resource;
|
||||
WP<CSessionLock> sessionLock;
|
||||
wlr_surface* pSurface = nullptr;
|
||||
CMonitor* pMonitor = nullptr;
|
||||
|
||||
bool ackdConfigure = false;
|
||||
bool committed = false;
|
||||
|
||||
void sendConfigure();
|
||||
|
||||
DYNLISTENER(surfaceCommit);
|
||||
DYNLISTENER(surfaceDestroy);
|
||||
|
||||
struct {
|
||||
CHyprSignalListener monitorMode;
|
||||
} listeners;
|
||||
};
|
||||
|
||||
class CSessionLock {
|
||||
public:
|
||||
CSessionLock(SP<CExtSessionLockV1> resource_);
|
||||
~CSessionLock();
|
||||
|
||||
bool good();
|
||||
void sendLocked();
|
||||
|
||||
struct {
|
||||
CSignal newLockSurface; // SP<CSessionLockSurface>
|
||||
CSignal unlockAndDestroy;
|
||||
CSignal destroyed; // fires regardless of whether there was a unlockAndDestroy or not.
|
||||
} events;
|
||||
|
||||
private:
|
||||
SP<CExtSessionLockV1> resource;
|
||||
|
||||
bool inert = false;
|
||||
|
||||
friend class CSessionLockProtocol;
|
||||
};
|
||||
|
||||
class CSessionLockProtocol : public IWaylandProtocol {
|
||||
public:
|
||||
CSessionLockProtocol(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);
|
||||
|
||||
bool isLocked();
|
||||
|
||||
struct {
|
||||
CSignal newLock; // SP<CSessionLock>
|
||||
} events;
|
||||
|
||||
private:
|
||||
void onManagerResourceDestroy(wl_resource* res);
|
||||
void destroyResource(CSessionLock* lock);
|
||||
void destroyResource(CSessionLockSurface* surf);
|
||||
void onLock(CExtSessionLockManagerV1* pMgr, uint32_t id);
|
||||
void onGetLockSurface(CExtSessionLockV1* lock, uint32_t id, wl_resource* surface, wl_resource* output);
|
||||
|
||||
bool locked = false;
|
||||
|
||||
//
|
||||
std::vector<UP<CExtSessionLockManagerV1>> m_vManagers;
|
||||
std::vector<SP<CSessionLock>> m_vLocks;
|
||||
std::vector<SP<CSessionLockSurface>> m_vLockSurfaces;
|
||||
|
||||
friend class CSessionLock;
|
||||
friend class CSessionLockSurface;
|
||||
};
|
||||
|
||||
namespace PROTO {
|
||||
inline UP<CSessionLockProtocol> sessionLock;
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
#include "../managers/CursorManager.hpp"
|
||||
#include "../desktop/Window.hpp"
|
||||
#include "../desktop/LayerSurface.hpp"
|
||||
#include "../protocols/SessionLock.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include <xf86drm.h>
|
||||
|
@ -739,12 +740,12 @@ void CHyprRenderer::renderSessionLockSurface(SSessionLockSurface* pSurface, CMon
|
|||
SRenderData renderdata = {pMonitor, time, pMonitor->vecPosition.x, pMonitor->vecPosition.y};
|
||||
|
||||
renderdata.blur = false;
|
||||
renderdata.surface = pSurface->pWlrLockSurface->surface;
|
||||
renderdata.surface = pSurface->surface.lock()->surface();
|
||||
renderdata.decorate = false;
|
||||
renderdata.w = pMonitor->vecSize.x;
|
||||
renderdata.h = pMonitor->vecSize.y;
|
||||
|
||||
wlr_surface_for_each_surface(pSurface->pWlrLockSurface->surface, renderSurface, &renderdata);
|
||||
renderSurface(renderdata.surface, 0, 0, &renderdata);
|
||||
}
|
||||
|
||||
void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPACE pWorkspace, timespec* time, const Vector2D& translate, const float& scale) {
|
||||
|
@ -763,7 +764,7 @@ void CHyprRenderer::renderAllClientsForWorkspace(CMonitor* pMonitor, PHLWORKSPAC
|
|||
if (!pMonitor)
|
||||
return;
|
||||
|
||||
if (!g_pCompositor->m_sSeat.exclusiveClient && g_pSessionLockManager->isSessionLocked()) {
|
||||
if (g_pSessionLockManager->isSessionLocked() && !g_pSessionLockManager->isSessionLockPresent()) {
|
||||
// locked with no exclusive, draw only red
|
||||
CBox boxe = {0, 0, INT16_MAX, INT16_MAX};
|
||||
g_pHyprOpenGL->renderRect(&boxe, CColor(1.0, 0.2, 0.2, 1.0));
|
||||
|
|
Loading…
Reference in a new issue