Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 40 additions & 8 deletions src/shell/lockscreen/lock_screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ void LockScreen::unlock() {
}

m_pendingAfterLocked = {};
m_suspendTimeoutTimer.stop();
invalidatePendingAuthentication();
stopFingerprint();

Expand Down Expand Up @@ -350,15 +351,25 @@ bool LockScreen::isActive() const noexcept { return m_lockPending || m_locked; }

bool LockScreen::isSessionLocked() const noexcept { return m_locked; }

bool LockScreen::tryFlushPendingAfterLocked() {
if (m_locked && m_pendingAfterLocked && allSurfacesReady()) {
auto pending = std::move(m_pendingAfterLocked);
m_pendingAfterLocked = {};
m_suspendTimeoutTimer.stop();
DeferredCall::callLater(std::move(pending));
return true;
}
return false;
}

void LockScreen::runAfterSessionLocked(std::function<void()> fn) {
if (fn == nullptr) {
return;
}
if (m_locked) {
DeferredCall::callLater(std::move(fn));
m_pendingAfterLocked = std::move(fn);
if (tryFlushPendingAfterLocked()) {
return;
}
m_pendingAfterLocked = std::move(fn);
if (isActive()) {
return;
}
Expand All @@ -382,17 +393,24 @@ void LockScreen::handleLocked(void* data, ext_session_lock_v1* /*lock*/) {
instance.surface->setLockedState(true);
instance.surface->setOnLogin([self]() { self->tryAuthenticate(); });
}

// Start the fallback timer (3 seconds) to trigger suspend anyway if surfaces take too long to render
self->m_suspendTimeoutTimer.start(std::chrono::seconds(3), [self]() {
if (self->m_pendingAfterLocked) {
kLog.warn("Lock screen surfaces took too long to render; suspending fallback triggered");
auto pending = std::move(self->m_pendingAfterLocked);
self->m_pendingAfterLocked = {};
DeferredCall::callLater(std::move(pending));
}
});

self->updatePromptOnSurfaces();
self->startFingerprint();
kLog.info("session is locked");
if (self->m_onSessionLocked) {
self->m_onSessionLocked();
}
if (self->m_pendingAfterLocked) {
auto pending = std::move(self->m_pendingAfterLocked);
self->m_pendingAfterLocked = {};
DeferredCall::callLater(std::move(pending));
}
self->tryFlushPendingAfterLocked();
}

void LockScreen::handleFinished(void* data, ext_session_lock_v1* /*lock*/) {
Expand Down Expand Up @@ -456,6 +474,18 @@ bool LockScreen::shouldUseBlurredDesktop() const {
&& m_wayland->hasScreencopy();
}

bool LockScreen::allSurfacesReady() const {
if (m_instances.empty()) {
return false;
}
for (const auto& instance : m_instances) {
if (instance.surface != nullptr && !instance.surface->firstFrameRendered()) {
return false;
}
}
return true;
}

void LockScreen::primeDesktopCaptures() {
if (m_configService != nullptr && !m_configService->isLockScreenEnabled()) {
return;
Expand Down Expand Up @@ -609,6 +639,7 @@ void LockScreen::createInstance(const WaylandOutput& output) {
surface->setDesktopCapture(std::move(captureIt->second));
m_desktopCaptures.erase(captureIt);
}
surface->setRenderCallback([this]() { tryFlushPendingAfterLocked(); });
surface->setOnLogin([this]() { tryAuthenticate(); });
surface->setOnPasswordChanged([this](const std::string& value) { handlePasswordEdited(value); });
surface->setPromptState(m_user, m_password, m_status, m_statusIsError, m_authenticating);
Expand All @@ -632,6 +663,7 @@ void LockScreen::createInstance(const WaylandOutput& output) {

void LockScreen::resetLockState() {
m_pendingAfterLocked = {};
m_suspendTimeoutTimer.stop();
m_lockDeferred = false;
if (m_lock == nullptr) {
m_lockPending = false;
Expand Down
4 changes: 4 additions & 0 deletions src/shell/lockscreen/lock_screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "auth/pam_authenticator.h"
#include "capture/screencopy_capture.h"
#include "core/timer_manager.h"

#include <cstdint>
#include <functional>
Expand Down Expand Up @@ -81,6 +82,8 @@ class LockScreen {
void syncInstances();
void captureDesktopSnapshots();
[[nodiscard]] bool shouldUseBlurredDesktop() const;
[[nodiscard]] bool allSurfacesReady() const;
bool tryFlushPendingAfterLocked();
void applyLockscreenStyle(LockSurface& surface) const;
void applyOutputRestriction();
void applyWallpaperStyleToSurfaces();
Expand Down Expand Up @@ -124,4 +127,5 @@ class LockScreen {
std::function<void()> m_onSessionLocked;
std::function<void()> m_onSessionUnlocked;
std::function<void()> m_onLockEngaged;
Timer m_suspendTimeoutTimer;
};
13 changes: 13 additions & 0 deletions src/shell/lockscreen/lock_surface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ void LockSurface::handleConfigure(
std::uint32_t height
) {
auto* self = static_cast<LockSurface*>(data);
if (self->width() != width || self->height() != height) {
self->m_firstFrameRendered = false;
}
ext_session_lock_surface_v1_ack_configure(lockSurface, serial);
self->Surface::onConfigure(width, height);
}
Expand Down Expand Up @@ -830,3 +833,13 @@ void LockSurface::onGpuResourcesInvalidated() {
m_wallpaperDirty = true;
requestLayout();
}

void LockSurface::render() {
Surface::render();
if (!m_firstFrameRendered) {
m_firstFrameRendered = true;
if (m_renderCallback) {
m_renderCallback();
}
}
}
8 changes: 8 additions & 0 deletions src/shell/lockscreen/lock_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,17 @@ class LockSurface : public Surface {
void setOutputKey(std::string outputKey) { m_outputKey = std::move(outputKey); }
void setWidgetsHost(LockscreenWidgetsHost* host) noexcept { m_widgetsHost = host; }

[[nodiscard]] bool firstFrameRendered() const noexcept { return m_firstFrameRendered; }
void setRenderCallback(std::function<void()> callback) { m_renderCallback = std::move(callback); }

static void handleConfigure(
void* data, ext_session_lock_surface_v1* lockSurface, std::uint32_t serial, std::uint32_t width,
std::uint32_t height
);

protected:
void render() override;

private:
void prepareFrame(bool needsUpdate, bool needsLayout);
void applyWallpaperTexture();
Expand Down Expand Up @@ -119,4 +125,6 @@ class LockSurface : public Surface {
bool m_authenticating = false;
std::string m_outputKey;
LockscreenWidgetsHost* m_widgetsHost = nullptr;
bool m_firstFrameRendered = false;
std::function<void()> m_renderCallback;
};
Loading