From 01971cb6c7b7607329314645bf46e83d985eafeb Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Mon, 14 Jul 2025 13:13:54 +0200 Subject: session-lock: don't render workspaces when locked (#10865) Avoid rendering the workspace behind if we are locked --- src/managers/SessionLockManager.cpp | 83 ++++++++++++++++++++++++------------- 1 file changed, 55 insertions(+), 28 deletions(-) (limited to 'src/managers/SessionLockManager.cpp') diff --git a/src/managers/SessionLockManager.cpp b/src/managers/SessionLockManager.cpp index bfd819cf..9ef37806 100644 --- a/src/managers/SessionLockManager.cpp +++ b/src/managers/SessionLockManager.cpp @@ -3,9 +3,10 @@ #include "../config/ConfigValue.hpp" #include "../protocols/FractionalScale.hpp" #include "../protocols/SessionLock.hpp" -#include "../managers/SeatManager.hpp" #include "../render/Renderer.hpp" -#include "../managers/input/InputManager.hpp" +#include "./managers/SeatManager.hpp" +#include "./managers/input/InputManager.hpp" +#include "./managers/eventLoop/EventLoopManager.hpp" #include #include @@ -49,16 +50,19 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { static auto PALLOWRELOCK = CConfigValue("misc:allow_session_lock_restore"); if (PROTO::sessionLock->isLocked() && !*PALLOWRELOCK) { - Debug::log(LOG, "Cannot re-lock, misc:allow_session_lock_restore is disabled"); + LOGM(LOG, "Cannot re-lock, misc:allow_session_lock_restore is disabled"); pLock->sendDenied(); return; } - Debug::log(LOG, "Session got locked by {:x}", (uintptr_t)pLock.get()); + if (m_sessionLock && !clientDenied() && !clientLocked()) + return; // Not allowing to relock in case the old lock is still in a limbo + + LOGM(LOG, "Session got locked by {:x}", (uintptr_t)pLock.get()); m_sessionLock = makeUnique(); m_sessionLock->lock = pLock; - m_sessionLock->mLockTimer.reset(); + m_sessionLock->lockTimer.reset(); m_sessionLock->listeners.newSurface = pLock->m_events.newLockSurface.listen([this](const SP& surface) { const auto PMONITOR = surface->monitor(); @@ -87,14 +91,48 @@ void CSessionLockManager::onNewSessionLock(SP pLock) { g_pCompositor->focusSurface(nullptr); g_pSeatManager->setGrab(nullptr); + m_sessionLock->sendDeniedTimer = makeShared( + // 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. + std::chrono::seconds(5), + [](auto, auto) { + if (!g_pSessionLockManager || g_pSessionLockManager->clientLocked() || g_pSessionLockManager->clientDenied()) + 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 recieve locked or denied. + // 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; + } + + if (g_pSessionLockManager->m_sessionLock && g_pSessionLockManager->m_sessionLock->lock) { + g_pSessionLockManager->m_sessionLock->lock->sendDenied(); + g_pSessionLockManager->m_sessionLock->hasSentDenied = true; + } + }, + nullptr); + + if (m_sessionLock->sendDeniedTimer) + g_pEventLoopManager->addTimer(m_sessionLock->sendDeniedTimer); + // Normally the locked event is sent after each output rendered a lock screen frame. // When there are no outputs, send it right away. if (g_pCompositor->m_unsafeState) { + removeSendDeniedTimer(); m_sessionLock->lock->sendLocked(); m_sessionLock->hasSentLocked = true; } } +void CSessionLockManager::removeSendDeniedTimer() { + if (!m_sessionLock || !m_sessionLock->sendDeniedTimer) + return; + + g_pEventLoopManager->removeTimer(m_sessionLock->sendDeniedTimer); + m_sessionLock->sendDeniedTimer.reset(); +} + bool CSessionLockManager::isSessionLocked() { return PROTO::sessionLock->isLocked(); } @@ -115,28 +153,13 @@ WP CSessionLockManager::getSessionLockSurfaceForMonitor(uin return {}; } -// We don't want the red screen to flash. -float CSessionLockManager::getRedScreenAlphaForMonitor(uint64_t id) { - if (!m_sessionLock) - return 1.F; - - const auto& NOMAPPEDSURFACETIMER = m_sessionLock->mMonitorsWithoutMappedSurfaceTimers.find(id); - - if (NOMAPPEDSURFACETIMER == m_sessionLock->mMonitorsWithoutMappedSurfaceTimers.end()) { - m_sessionLock->mMonitorsWithoutMappedSurfaceTimers.emplace(id, CTimer()); - m_sessionLock->mMonitorsWithoutMappedSurfaceTimers[id].reset(); - return 0.f; - } - - return std::clamp(NOMAPPEDSURFACETIMER->second.getSeconds() - /* delay for screencopy */ 0.5f, 0.f, 1.f); -} - void CSessionLockManager::onLockscreenRenderedOnMonitor(uint64_t id) { - if (!m_sessionLock || m_sessionLock->hasSentLocked) + if (!m_sessionLock || m_sessionLock->hasSentLocked || m_sessionLock->hasSentDenied) return; m_sessionLock->lockedMonitors.emplace(id); const bool LOCKED = std::ranges::all_of(g_pCompositor->m_monitors, [this](auto m) { return m_sessionLock->lockedMonitors.contains(m->m_id); }); if (LOCKED && m_sessionLock->lock->good()) { + removeSendDeniedTimer(); m_sessionLock->lock->sendLocked(); m_sessionLock->hasSentLocked = true; } @@ -157,6 +180,10 @@ bool CSessionLockManager::isSurfaceSessionLock(SP pSurface) return false; } +bool CSessionLockManager::anySessionLockSurfacesPresent() { + return m_sessionLock && std::ranges::any_of(m_sessionLock->vSessionLockSurfaces, [](const auto& surf) { return surf->mapped; }); +} + void CSessionLockManager::removeSessionLockSurface(SSessionLockSurface* pSLS) { if (!m_sessionLock) return; @@ -175,19 +202,19 @@ void CSessionLockManager::removeSessionLockSurface(SSessionLockSurface* pSLS) { } } -bool CSessionLockManager::isSessionLockPresent() { - return m_sessionLock && !m_sessionLock->vSessionLockSurfaces.empty(); +bool CSessionLockManager::clientLocked() { + return m_sessionLock && m_sessionLock->hasSentLocked; } -bool CSessionLockManager::anySessionLockSurfacesPresent() { - return m_sessionLock && std::ranges::any_of(m_sessionLock->vSessionLockSurfaces, [](const auto& surf) { return surf->mapped; }); +bool CSessionLockManager::clientDenied() { + return m_sessionLock && m_sessionLock->hasSentDenied; } bool CSessionLockManager::shallConsiderLockMissing() { if (!m_sessionLock) - return false; + return true; static auto LOCKDEAD_SCREEN_DELAY = CConfigValue("misc:lockdead_screen_delay"); - return m_sessionLock->mLockTimer.getMillis() > *LOCKDEAD_SCREEN_DELAY; + return m_sessionLock->lockTimer.getMillis() > *LOCKDEAD_SCREEN_DELAY; } -- cgit v1.2.3