diff options
author | Junxuan Liao <[email protected]> | 2024-07-13 18:32:08 +0800 |
---|---|---|
committer | GitHub <[email protected]> | 2024-07-13 12:32:08 +0200 |
commit | 7486576fa7a3d394254cb07734679df4b2469071 (patch) | |
tree | 6f62e6c73cfec489ca2e068f0018fb0a1ad62da5 | |
parent | f85c6416c6f5e56c75178ecb24c11e346069197d (diff) | |
download | Hyprland-7486576fa7a3d394254cb07734679df4b2469071.tar.gz Hyprland-7486576fa7a3d394254cb07734679df4b2469071.zip |
session-lock: send `locked` after the lock screen is properly rendered (#6850)
The protocol says:
> The locked event "must not be sent until a new "locked" frame (either from a
> session lock surface or the compositor blanking the output) has been presented
> on all outputs and no security sensitive normal/unlocked content is possibly
> visible".
This helps users ensure the screen is properly locked before suspending
the machine. (e.g. with swaylock --ready-fd)
-rw-r--r-- | src/managers/SessionLockManager.cpp | 15 | ||||
-rw-r--r-- | src/managers/SessionLockManager.hpp | 8 | ||||
-rw-r--r-- | src/render/Renderer.cpp | 3 |
3 files changed, 23 insertions, 3 deletions
diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index b4695e0e..83ff3ee7 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -3,6 +3,7 @@ #include "../config/ConfigValue.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" +#include <algorithm> SSessionLockSurface::SSessionLockSurface(SP<CSessionLockSurface> surface_) : surface(surface_) { pWlrSurface = surface->surface(); @@ -77,7 +78,6 @@ void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) { g_pHyprRenderer->damageMonitor(m.get()); }); - pLock->sendLocked(); g_pCompositor->focusSurface(nullptr); } @@ -102,7 +102,6 @@ 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) { if (!m_pSessionLock) return 0.F; @@ -118,6 +117,18 @@ float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) { return std::clamp(NOMAPPEDSURFACETIMER->second.getSeconds() - /* delay for screencopy */ 0.5f, 0.f, 1.f); } +void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) { + if (!m_pSessionLock || m_pSessionLock->m_hasSentLocked) + return; + m_pSessionLock->m_lockedMonitors.emplace(id); + const auto MONITORS = g_pCompositor->m_vMonitors; + const bool LOCKED = std::all_of(MONITORS.begin(), MONITORS.end(), [this](auto m) { return m_pSessionLock->m_lockedMonitors.contains(m->ID); }); + if (LOCKED) { + m_pSessionLock->lock->sendLocked(); + m_pSessionLock->m_hasSentLocked = true; + } +} + bool CSessionLockManager::isSurfaceSessionLock(SP<CWLSurfaceResource> 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 diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index fe4a4434..b01ee288 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -5,6 +5,7 @@ #include "../helpers/signal/Signal.hpp" #include <cstdint> #include <unordered_map> +#include <unordered_set> class CSessionLockSurface; class CSessionLock; @@ -37,6 +38,9 @@ struct SSessionLock { CHyprSignalListener unlock; CHyprSignalListener destroy; } listeners; + + bool m_hasSentLocked = false; + std::unordered_set<uint64_t> m_lockedMonitors; }; class CSessionLockManager { @@ -54,6 +58,8 @@ class CSessionLockManager { void removeSessionLockSurface(SSessionLockSurface*); + void onLockscreenRenderedOnMonitor(uint64_t id); + private: UP<SSessionLock> m_pSessionLock; @@ -64,4 +70,4 @@ class CSessionLockManager { void onNewSessionLock(SP<CSessionLock> pWlrLock); }; -inline std::unique_ptr<CSessionLockManager> g_pSessionLockManager;
\ No newline at end of file +inline std::unique_ptr<CSessionLockManager> g_pSessionLockManager; diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp index 955a16b9..a7f3c941 100644 --- a/src/render/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -990,8 +990,11 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB if (ALPHA < 1.f) /* animate */ damageMonitor(pMonitor); + else + g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } else { renderSessionLockSurface(PSLS, pMonitor, now); + g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID); } } } |