diff options
| author | Maximilian Seidler <78690852+PointerDilemma@users.noreply.github.com> | 2026-05-03 15:58:03 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-03 14:58:03 +0100 |
| commit | aa5e38041ed332416ac2f5ace908389c35b28192 (patch) | |
| tree | 9a602755cbc15759219af3071529be03b1fd4431 | |
| parent | 6ec0228c38a6203e4789fe7e7e793a558521c109 (diff) | |
sessionLock: send locked instead of denied when missing a lock frame for 5 seconds (#14271)
The protocol seems to allow this, because it explicitly mentions either
session lock surface or compositor blanking the output in this sentence:
> 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.
Since `locked_screen_delay` is capped to 5 seconds,
after the 5 seconds this timer is registered for, we assume that
all outputs are covered either by lockedead or by an actual lock frame.
Thus sending locked is ok.
| -rw-r--r-- | src/managers/SessionLockManager.cpp | 33 | ||||
| -rw-r--r-- | src/managers/SessionLockManager.hpp | 4 |
2 files changed, 16 insertions, 21 deletions
diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index 8890e2e0..6e45c923 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -105,8 +105,10 @@ void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) { return; } - m_sessionLock->sendDeniedTimer = makeShared<CEventLoopTimer>( - // Within this arbitrary amount of time, a session-lock client is expected to create and commit a lock surface for each output. If the client fails to do that, it will be denied. + m_sessionLock->sendLockedTimer = makeShared<CEventLoopTimer>( + // Clients get sent the "locked" event after they submitted a lock frame for each output. + // If they fail to do this, we send the "locked" event after a fixed amount of time here. + // Previously we sent denied after this timeout, but that forcefully makes the client exit and the protocol doesn't require that anyways. std::chrono::seconds(5), [](auto, auto) { if (!g_pSessionLockManager || g_pSessionLockManager->clientLocked() || g_pSessionLockManager->clientDenied()) @@ -115,29 +117,22 @@ void CSessionLockManager::onNewSessionLock(SP<CSessionLock> pLock) { if (!g_pSessionLockManager->m_sessionLock || !g_pSessionLockManager->m_sessionLock->lock) return; - if (g_pCompositor->m_unsafeState || !g_pCompositor->m_aqBackend->hasSession() || !g_pCompositor->m_aqBackend->session->active) { - // Because the session is inactive, there is a good reason for why the client did't manage to render to all outputs. - // We send locked, although this could lead to imperfect frames when we start to render again. - g_pSessionLockManager->m_sessionLock->lock->sendLocked(); - g_pSessionLockManager->m_sessionLock->hasSentLocked = true; - return; - } - - LOGM(Log::WARN, "Kicking lockscreen client, because it failed to render to all outputs within 5 seconds"); - g_pSessionLockManager->m_sessionLock->lock->sendDenied(); - g_pSessionLockManager->m_sessionLock->hasSentDenied = true; + LOGM(Log::WARN, + "Sending locked after a 5 second timeout. This happens when we failed to render a lock frame from the client for every output. Lockdead frames may be shown."); + g_pSessionLockManager->m_sessionLock->lock->sendLocked(); + g_pSessionLockManager->m_sessionLock->hasSentLocked = true; }, nullptr); - g_pEventLoopManager->addTimer(m_sessionLock->sendDeniedTimer); + g_pEventLoopManager->addTimer(m_sessionLock->sendLockedTimer); } -void CSessionLockManager::removeSendDeniedTimer() { - if (!m_sessionLock || !m_sessionLock->sendDeniedTimer) +void CSessionLockManager::removeSendLockedTimer() { + if (!m_sessionLock || !m_sessionLock->sendLockedTimer) return; - g_pEventLoopManager->removeTimer(m_sessionLock->sendDeniedTimer); - m_sessionLock->sendDeniedTimer.reset(); + g_pEventLoopManager->removeTimer(m_sessionLock->sendLockedTimer); + m_sessionLock->sendLockedTimer.reset(); } bool CSessionLockManager::isSessionLocked() { @@ -169,7 +164,7 @@ void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) { std::ranges::all_of(g_pCompositor->m_monitors, [this](auto m) { return !m->m_enabled || !m->m_dpmsStatus || m_sessionLock->lockedMonitors.contains(m->m_id); }); if (LOCKED && m_sessionLock->lock->good()) { - removeSendDeniedTimer(); + removeSendLockedTimer(); m_sessionLock->lock->sendLocked(); m_sessionLock->hasSentLocked = true; } diff --git a/src/managers/SessionLockManager.hpp b/src/managers/SessionLockManager.hpp index efcaf09a..dba2758e 100644 --- a/src/managers/SessionLockManager.hpp +++ b/src/managers/SessionLockManager.hpp @@ -31,7 +31,7 @@ struct SSessionLockSurface { struct SSessionLock { WP<CSessionLock> lock; CTimer lockTimer; - SP<CEventLoopTimer> sendDeniedTimer; + SP<CEventLoopTimer> sendLockedTimer; std::vector<SP<SSessionLockSurface>> vSessionLockSurfaces; @@ -73,7 +73,7 @@ class CSessionLockManager { } m_listeners; void onNewSessionLock(SP<CSessionLock> pWlrLock); - void removeSendDeniedTimer(); + void removeSendLockedTimer(); }; inline UP<CSessionLockManager> g_pSessionLockManager; |
