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)
This commit is contained in:
Junxuan Liao 2024-07-13 18:32:08 +08:00 committed by GitHub
parent f85c6416c6
commit 7486576fa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 23 additions and 3 deletions

View File

@ -3,6 +3,7 @@
#include "../config/ConfigValue.hpp" #include "../config/ConfigValue.hpp"
#include "../protocols/FractionalScale.hpp" #include "../protocols/FractionalScale.hpp"
#include "../protocols/SessionLock.hpp" #include "../protocols/SessionLock.hpp"
#include <algorithm>
SSessionLockSurface::SSessionLockSurface(SP<CSessionLockSurface> surface_) : surface(surface_) { SSessionLockSurface::SSessionLockSurface(SP<CSessionLockSurface> surface_) : surface(surface_) {
pWlrSurface = surface->surface(); pWlrSurface = surface->surface();
@ -77,7 +78,6 @@ void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) {
g_pHyprRenderer->damageMonitor(m.get()); g_pHyprRenderer->damageMonitor(m.get());
}); });
pLock->sendLocked();
g_pCompositor->focusSurface(nullptr); g_pCompositor->focusSurface(nullptr);
} }
@ -102,7 +102,6 @@ SSessionLockSurface* CSessionLockManager::getSessionLockSurfaceForMonitor(uint64
} }
// We don't want the red screen to flash. // 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) { float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) {
if (!m_pSessionLock) if (!m_pSessionLock)
return 0.F; 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); 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) { bool CSessionLockManager::isSurfaceSessionLock(SP<CWLSurfaceResource> pSurface) {
// TODO: this has some edge cases when it's wrong (e.g. destroyed lock but not yet surfaces) // 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 // but can be easily fixed when I rewrite wlr_surface

View File

@ -5,6 +5,7 @@
#include "../helpers/signal/Signal.hpp" #include "../helpers/signal/Signal.hpp"
#include <cstdint> #include <cstdint>
#include <unordered_map> #include <unordered_map>
#include <unordered_set>
class CSessionLockSurface; class CSessionLockSurface;
class CSessionLock; class CSessionLock;
@ -37,6 +38,9 @@ struct SSessionLock {
CHyprSignalListener unlock; CHyprSignalListener unlock;
CHyprSignalListener destroy; CHyprSignalListener destroy;
} listeners; } listeners;
bool m_hasSentLocked = false;
std::unordered_set<uint64_t> m_lockedMonitors;
}; };
class CSessionLockManager { class CSessionLockManager {
@ -54,6 +58,8 @@ class CSessionLockManager {
void removeSessionLockSurface(SSessionLockSurface*); void removeSessionLockSurface(SSessionLockSurface*);
void onLockscreenRenderedOnMonitor(uint64_t id);
private: private:
UP<SSessionLock> m_pSessionLock; UP<SSessionLock> m_pSessionLock;

View File

@ -990,8 +990,11 @@ void CHyprRenderer::renderLockscreen(CMonitor* pMonitor, timespec* now, const CB
if (ALPHA < 1.f) /* animate */ if (ALPHA < 1.f) /* animate */
damageMonitor(pMonitor); damageMonitor(pMonitor);
else
g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID);
} else { } else {
renderSessionLockSurface(PSLS, pMonitor, now); renderSessionLockSurface(PSLS, pMonitor, now);
g_pSessionLockManager->onLockscreenRenderedOnMonitor(pMonitor->ID);
} }
} }
} }