wayland/lock: initialize lock content before starting lock
Reduces any chances of the compositor displaying a blank frame first.
This commit is contained in:
parent
71a65c4d3c
commit
8ec245ac66
|
@ -46,60 +46,72 @@ 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 {
|
void WlSessionLock::updateSurfaces(bool show, WlSessionLock* old) {
|
||||||
this->setLocked(false);
|
auto screens = QGuiApplication::screens();
|
||||||
|
|
||||||
|
auto map = this->surfaces.toStdMap();
|
||||||
|
for (auto& [screen, surface]: map) {
|
||||||
|
if (!screens.contains(screen)) {
|
||||||
|
this->surfaces.remove(screen);
|
||||||
|
surface->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto* screen: screens) {
|
||||||
|
if (!this->surfaces.contains(screen)) {
|
||||||
|
auto* instanceObj =
|
||||||
|
this->mSurfaceComponent->create(QQmlEngine::contextForObject(this->mSurfaceComponent));
|
||||||
|
auto* instance = qobject_cast<WlSessionLockSurface*>(instanceObj);
|
||||||
|
|
||||||
|
if (instance == nullptr) {
|
||||||
|
qWarning(
|
||||||
|
) << "WlSessionLock.surface does not create a WlSessionLockSurface. Aborting lock.";
|
||||||
|
if (instanceObj != nullptr) instanceObj->deleteLater();
|
||||||
|
this->unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->setParent(this);
|
||||||
|
instance->setScreen(screen);
|
||||||
|
|
||||||
|
auto* oldInstance = old == nullptr ? nullptr : old->surfaces.value(screen, nullptr);
|
||||||
|
instance->reload(oldInstance);
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
surface->show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WlSessionLock::updateSurfaces(WlSessionLock* old) {
|
void WlSessionLock::realizeLockTarget(WlSessionLock* old) {
|
||||||
if (this->manager->isLocked()) {
|
if (this->lockTarget) {
|
||||||
auto screens = QGuiApplication::screens();
|
|
||||||
|
|
||||||
auto map = this->surfaces.toStdMap();
|
|
||||||
for (auto& [screen, surface]: map) {
|
|
||||||
if (!screens.contains(screen)) {
|
|
||||||
this->surfaces.remove(screen);
|
|
||||||
surface->deleteLater();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this->mSurfaceComponent == nullptr) {
|
if (this->mSurfaceComponent == nullptr) {
|
||||||
qWarning() << "WlSessionLock.surface is null. Aborting lock.";
|
qWarning() << "WlSessionLock.surface is null. Aborting lock.";
|
||||||
this->unlock();
|
this->unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto* screen: screens) {
|
// preload initial surfaces to make the chance of the compositor displaying a blank
|
||||||
if (!this->surfaces.contains(screen)) {
|
// frame before the lock surfaces are shown as low as possible.
|
||||||
auto* instanceObj =
|
this->updateSurfaces(false);
|
||||||
this->mSurfaceComponent->create(QQmlEngine::contextForObject(this->mSurfaceComponent));
|
|
||||||
auto* instance = qobject_cast<WlSessionLockSurface*>(instanceObj);
|
|
||||||
|
|
||||||
if (instance == nullptr) {
|
if (!this->manager->lock()) this->lockTarget = false;
|
||||||
qWarning(
|
|
||||||
) << "WlSessionLock.surface does not create a WlSessionLockSurface. Aborting lock.";
|
|
||||||
if (instanceObj != nullptr) instanceObj->deleteLater();
|
|
||||||
this->unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->setParent(this);
|
this->updateSurfaces(true, old);
|
||||||
instance->setScreen(screen);
|
} else {
|
||||||
|
this->unlock(); // emits lockStateChanged
|
||||||
auto* oldInstance = old == nullptr ? nullptr : old->surfaces.value(screen, nullptr);
|
|
||||||
instance->reload(oldInstance);
|
|
||||||
instance->attach();
|
|
||||||
|
|
||||||
this->surfaces[screen] = instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto* surface: this->surfaces.values()) {
|
|
||||||
surface->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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";
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in a new issue