wayland/lock: initialize lock content before starting lock

Reduces any chances of the compositor displaying a blank frame first.
This commit is contained in:
outfoxxed 2024-06-18 20:34:16 -07:00
parent 71a65c4d3c
commit 8ec245ac66
Signed by: outfoxxed
GPG key ID: 4C88A185FB89301E
4 changed files with 79 additions and 57 deletions

View file

@ -46,16 +46,10 @@ void WlSessionLock::onReload(QObject* oldInstance) {
} }
// clang-format on // clang-format on
if (this->lockTarget) { this->realizeLockTarget(old);
if (!this->manager->lock()) this->lockTarget = false;
this->updateSurfaces(old);
} else {
this->setLocked(false);
}
} }
void WlSessionLock::updateSurfaces(WlSessionLock* old) { void WlSessionLock::updateSurfaces(bool show, WlSessionLock* old) {
if (this->manager->isLocked()) {
auto screens = QGuiApplication::screens(); auto screens = QGuiApplication::screens();
auto map = this->surfaces.toStdMap(); auto map = this->surfaces.toStdMap();
@ -66,12 +60,6 @@ void WlSessionLock::updateSurfaces(WlSessionLock* old) {
} }
} }
if (this->mSurfaceComponent == nullptr) {
qWarning() << "WlSessionLock.surface is null. Aborting lock.";
this->unlock();
return;
}
for (auto* screen: screens) { for (auto* screen: screens) {
if (!this->surfaces.contains(screen)) { if (!this->surfaces.contains(screen)) {
auto* instanceObj = auto* instanceObj =
@ -91,15 +79,39 @@ void WlSessionLock::updateSurfaces(WlSessionLock* old) {
auto* oldInstance = old == nullptr ? nullptr : old->surfaces.value(screen, nullptr); auto* oldInstance = old == nullptr ? nullptr : old->surfaces.value(screen, nullptr);
instance->reload(oldInstance); instance->reload(oldInstance);
instance->attach();
this->surfaces[screen] = instance; this->surfaces[screen] = instance;
} }
}
if (show) {
if (!this->manager->isLocked()) {
qFatal() << "Tried to show lockscreen surfaces without active lock";
}
for (auto* surface: this->surfaces.values()) { for (auto* surface: this->surfaces.values()) {
surface->show(); surface->show();
} }
} }
}
void WlSessionLock::realizeLockTarget(WlSessionLock* old) {
if (this->lockTarget) {
if (this->mSurfaceComponent == nullptr) {
qWarning() << "WlSessionLock.surface is null. Aborting lock.";
this->unlock();
return;
}
// preload initial surfaces to make the chance of the compositor displaying a blank
// frame before the lock surfaces are shown as low as possible.
this->updateSurfaces(false);
if (!this->manager->lock()) this->lockTarget = false;
this->updateSurfaces(true, old);
} else {
this->unlock(); // emits lockStateChanged
} }
} }
@ -118,7 +130,7 @@ void WlSessionLock::unlock() {
} }
} }
void WlSessionLock::onScreensChanged() { this->updateSurfaces(); } void WlSessionLock::onScreensChanged() { this->updateSurfaces(true); }
bool WlSessionLock::isLocked() const { bool WlSessionLock::isLocked() const {
return this->manager == nullptr ? this->lockTarget : this->manager->isLocked(); return this->manager == nullptr ? this->lockTarget : this->manager->isLocked();
@ -137,18 +149,17 @@ void WlSessionLock::setLocked(bool locked) {
return; return;
} }
if (locked) { this->realizeLockTarget();
if (!this->manager->lock()) this->lockTarget = false;
this->updateSurfaces();
if (this->lockTarget) emit this->lockStateChanged();
} else {
this->unlock(); // emits lockStateChanged
}
} }
QQmlComponent* WlSessionLock::surfaceComponent() const { return this->mSurfaceComponent; } QQmlComponent* WlSessionLock::surfaceComponent() const { return this->mSurfaceComponent; }
void WlSessionLock::setSurfaceComponent(QQmlComponent* surfaceComponent) { void WlSessionLock::setSurfaceComponent(QQmlComponent* surfaceComponent) {
if (this->manager != nullptr && this->manager->isLocked()) {
qCritical() << "WlSessionLock.surfaceComponent cannot be changed while the lock is active.";
return;
}
if (this->mSurfaceComponent != nullptr) this->mSurfaceComponent->deleteLater(); if (this->mSurfaceComponent != nullptr) this->mSurfaceComponent->deleteLater();
if (surfaceComponent != nullptr) surfaceComponent->setParent(this); if (surfaceComponent != nullptr) surfaceComponent->setParent(this);
@ -202,6 +213,8 @@ void WlSessionLockSurface::onReload(QObject* oldInstance) {
} }
void WlSessionLockSurface::attach() { void WlSessionLockSurface::attach() {
if (this->ext->isAttached()) return;
if (auto* parent = qobject_cast<WlSessionLock*>(this->parent())) { if (auto* parent = qobject_cast<WlSessionLock*>(this->parent())) {
if (!this->ext->attach(this->window, parent->manager)) { if (!this->ext->attach(this->window, parent->manager)) {
qFatal() << "Failed to attach WlSessionLockSurface"; qFatal() << "Failed to attach WlSessionLockSurface";
@ -220,7 +233,10 @@ QQuickWindow* WlSessionLockSurface::disownWindow() {
return window; return window;
} }
void WlSessionLockSurface::show() { this->ext->setVisible(); } void WlSessionLockSurface::show() {
this->attach();
this->ext->setVisible();
}
QQuickItem* WlSessionLockSurface::contentItem() const { return this->mContentItem; } QQuickItem* WlSessionLockSurface::contentItem() const { return this->mContentItem; }
@ -257,8 +273,11 @@ void WlSessionLockSurface::setScreen(QScreen* qscreen) {
QObject::connect(qscreen, &QObject::destroyed, this, &WlSessionLockSurface::onScreenDestroyed); QObject::connect(qscreen, &QObject::destroyed, this, &WlSessionLockSurface::onScreenDestroyed);
} }
if (this->window == nullptr) this->mScreen = qscreen; if (this->window == nullptr) {
else this->window->setScreen(qscreen); this->mScreen = qscreen;
} else {
this->window->setScreen(qscreen);
}
emit this->screenChanged(); emit this->screenChanged();
} }

View file

@ -97,7 +97,8 @@ private slots:
void onScreensChanged(); void onScreensChanged();
private: private:
void updateSurfaces(WlSessionLock* old = nullptr); void updateSurfaces(bool show, WlSessionLock* old = nullptr);
void realizeLockTarget(WlSessionLock* old = nullptr);
SessionLockManager* manager = nullptr; SessionLockManager* manager = nullptr;
QQmlComponent* mSurfaceComponent = nullptr; QQmlComponent* mSurfaceComponent = nullptr;

View file

@ -63,6 +63,8 @@ LockWindowExtension* LockWindowExtension::get(QWindow* window) {
} }
} }
bool LockWindowExtension::isAttached() const { return this->surface != nullptr; }
bool LockWindowExtension::attach(QWindow* window, SessionLockManager* manager) { bool LockWindowExtension::attach(QWindow* window, SessionLockManager* manager) {
if (this->surface != nullptr) if (this->surface != nullptr)
qFatal() << "Cannot change the attached window of a LockWindowExtension"; qFatal() << "Cannot change the attached window of a LockWindowExtension";

View file

@ -61,6 +61,8 @@ public:
~LockWindowExtension() override; ~LockWindowExtension() override;
Q_DISABLE_COPY_MOVE(LockWindowExtension); Q_DISABLE_COPY_MOVE(LockWindowExtension);
[[nodiscard]] bool isAttached() const;
// Attach this lock extension to the given window. // Attach this lock extension to the given window.
// The extension is reparented to the window and replaces any existing lock extension. // The extension is reparented to the window and replaces any existing lock extension.
// Returns false if the window cannot be used. // Returns false if the window cannot be used.
@ -70,8 +72,6 @@ public:
// To make a window invisible, destroy it as it cannot be recovered. // To make a window invisible, destroy it as it cannot be recovered.
void setVisible(); void setVisible();
[[nodiscard]] bool isLocked() const;
static LockWindowExtension* get(QWindow* window); static LockWindowExtension* get(QWindow* window);
signals: signals: