diff --git a/greeter/greeterapp.h b/greeter/greeterapp.h --- a/greeter/greeterapp.h +++ b/greeter/greeterapp.h @@ -69,9 +69,12 @@ bool supportsSeccomp() const { return m_supportsSeccomp; } + void loadCurrentScreens(); public Q_SLOTS: void desktopResized(); + void screenRemovedImpl(QScreen *screen); + void screenAddedImpl(QScreen *screen, bool shouldResizeDesktops = true); protected: bool eventFilter(QObject *obj, QEvent *event) override; diff --git a/greeter/greeterapp.cpp b/greeter/greeterapp.cpp --- a/greeter/greeterapp.cpp +++ b/greeter/greeterapp.cpp @@ -127,8 +127,8 @@ m_authenticator = createAuthenticator(); connect(m_authenticator, &Authenticator::succeeded, this, &QCoreApplication::quit); initialize(); - connect(this, &UnlockApp::screenAdded, this, &UnlockApp::desktopResized); - connect(this, &UnlockApp::screenRemoved, this, &UnlockApp::desktopResized); + connect(this, &UnlockApp::screenAdded, this, [this](QScreen *screen) { screenAddedImpl(screen, true); }); + connect(this, &UnlockApp::screenRemoved, this, [this](QScreen *screen) { screenRemovedImpl(screen); }); if (QX11Info::isPlatformX11()) { installNativeEventFilter(new FocusOutEventFilter); @@ -287,104 +287,127 @@ ); } -void UnlockApp::desktopResized() -{ - const int nScreens = screens().count(); - // remove useless views and savers - while (m_views.count() > nScreens) { - m_views.takeLast()->deleteLater(); +namespace { + static const char *screenNameProperty = "screenNameProperty"; + QScreen *screenFromName(const QList screens, const QString& name) + { + auto screenIt = std::find_if(std::begin(screens), std::end(screens), + [name](QScreen *screen) { return name == screen->name(); }); + + if (screenIt != std::end(screens)) { + return *screenIt; + } + return nullptr; } +} - // extend views and savers to current demand - for (int i = m_views.count(); i < nScreens; ++i) { - // create the view - auto *view = new KQuickAddons::QuickViewSharedEngine(); - view->setColor(Qt::black); - auto screen = QGuiApplication::screens()[i]; - view->setGeometry(screen->geometry()); +void UnlockApp::screenRemovedImpl(QScreen *removed) +{ + auto viewIt = std::find_if(std::begin(m_views), std::end(m_views), + [removed](KQuickAddons::QuickViewSharedEngine *view) { + const QString viewName = view->property(screenNameProperty).toString(); + return removed->name() == viewName; + }); - // first create KDeclarative, to be sure that it created a KIO Network Factory - KDeclarative::KDeclarative declarative; - declarative.setDeclarativeEngine(view->engine()); - declarative.setupBindings(); + Q_ASSERT(viewIt != std::end(m_views)); + auto view = *viewIt; + m_views.removeOne(view); + view->deleteLater(); + desktopResized(); +} - if (!m_testing) { - if (QX11Info::isPlatformX11()) { - view->setFlags(Qt::X11BypassWindowManagerHint); - } else { - view->setFlags(Qt::FramelessWindowHint); - } - } +void UnlockApp::screenAddedImpl(QScreen *added, bool shouldResizeDesktops) +{ + auto *view = new KQuickAddons::QuickViewSharedEngine(); + view->setColor(Qt::black); + view->setProperty(screenNameProperty, added->name()); + view->setGeometry(added->geometry()); - if (m_ksldInterface) { - view->create(); - org_kde_ksld_x11window(m_ksldInterface, view->winId()); - wl_display_flush(m_ksldConnection->display()); - } + // first create KDeclarative, to be sure that it created a KIO Network Factory + KDeclarative::KDeclarative declarative; + declarative.setDeclarativeEngine(view->engine()); + declarative.setupBindings(); - if (m_plasmaShell) { - using namespace KWayland::Client; - if (Surface *surface = Surface::fromWindow(view)) { - PlasmaShellSurface *shellSurface = m_plasmaShell->createSurface(surface, view); - view->setProperty("plasmaShellSurface", QVariant::fromValue(shellSurface)); - } + if (!m_testing) { + if (QX11Info::isPlatformX11()) { + view->setFlags(Qt::X11BypassWindowManagerHint); + } else { + view->setFlags(Qt::FramelessWindowHint); } + } + + if (m_ksldInterface) { + view->create(); + org_kde_ksld_x11window(m_ksldInterface, view->winId()); + wl_display_flush(m_ksldConnection->display()); + } - // engine stuff - QQmlContext* context = view->engine()->rootContext(); - - context->setContextProperty(QStringLiteral("kscreenlocker_userName"), m_userName); - context->setContextProperty(QStringLiteral("kscreenlocker_userImage"), m_userImage); - context->setContextProperty(QStringLiteral("authenticator"), m_authenticator); - context->setContextProperty(QStringLiteral("org_kde_plasma_screenlocker_greeter_interfaceVersion"), 2); - context->setContextProperty(QStringLiteral("org_kde_plasma_screenlocker_greeter_view"), view); - context->setContextProperty(QStringLiteral("defaultToSwitchUser"), m_defaultToSwitchUser); - context->setContextProperty(QStringLiteral("config"), m_lnfIntegration->configuration()); - - view->setSource(m_mainQmlPath); - // on error, load the fallback lockscreen to not lock the user out of the system - if (view->status() != QQmlComponent::Ready) { - static const QUrl fallbackUrl(QUrl(QStringLiteral("qrc:/fallbacktheme/LockScreen.qml"))); - - qWarning() << "Failed to load lockscreen QML, falling back to built-in locker"; - m_mainQmlPath = fallbackUrl; - view->setSource(fallbackUrl); + if (m_plasmaShell) { + using namespace KWayland::Client; + if (Surface *surface = Surface::fromWindow(view)) { + PlasmaShellSurface *shellSurface = m_plasmaShell->createSurface(surface, view); + view->setProperty("plasmaShellSurface", QVariant::fromValue(shellSurface)); } - view->setResizeMode(KQuickAddons::QuickViewSharedEngine::SizeRootObjectToView); + } - loadWallpaperPlugin(view); - // overwrite the factory set by kdeclarative - auto oldFactory = view->engine()->networkAccessManagerFactory(); - view->engine()->setNetworkAccessManagerFactory(nullptr); - delete oldFactory; - view->engine()->setNetworkAccessManagerFactory(new NoAccessNetworkAccessManagerFactory); + // engine stuff + QQmlContext* context = view->engine()->rootContext(); + context->setContextProperty(QStringLiteral("kscreenlocker_userName"), m_userName); + context->setContextProperty(QStringLiteral("kscreenlocker_userImage"), m_userImage); + context->setContextProperty(QStringLiteral("authenticator"), m_authenticator); + context->setContextProperty(QStringLiteral("org_kde_plasma_screenlocker_greeter_interfaceVersion"), 2); + context->setContextProperty(QStringLiteral("org_kde_plasma_screenlocker_greeter_view"), view); + context->setContextProperty(QStringLiteral("defaultToSwitchUser"), m_defaultToSwitchUser); + context->setContextProperty(QStringLiteral("config"), m_lnfIntegration->configuration()); - QQmlProperty lockProperty(view->rootObject(), QStringLiteral("locked")); - lockProperty.write(m_immediateLock || (!m_noLock && !m_delayedLockTimer)); + view->setSource(m_mainQmlPath); + // on error, load the fallback lockscreen to not lock the user out of the system + if (view->status() != QQmlComponent::Ready) { + static const QUrl fallbackUrl(QUrl(QStringLiteral("qrc:/fallbacktheme/LockScreen.qml"))); - QQmlProperty sleepProperty(view->rootObject(), QStringLiteral("suspendToRamSupported")); - sleepProperty.write(m_canSuspend); - if (view->rootObject() && view->rootObject()->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("suspendToRam()").constData()) != -1) { - connect(view->rootObject(), SIGNAL(suspendToRam()), SLOT(suspendToRam())); - } + qWarning() << "Failed to load lockscreen QML, falling back to built-in locker"; + m_mainQmlPath = fallbackUrl; + view->setSource(fallbackUrl); + } + view->setResizeMode(KQuickAddons::QuickViewSharedEngine::SizeRootObjectToView); - QQmlProperty hibernateProperty(view->rootObject(), QStringLiteral("suspendToDiskSupported")); - hibernateProperty.write(m_canHibernate); - if (view->rootObject() && view->rootObject()->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("suspendToDisk()").constData()) != -1) { - connect(view->rootObject(), SIGNAL(suspendToDisk()), SLOT(suspendToDisk())); - } + loadWallpaperPlugin(view); + // overwrite the factory set by kdeclarative + auto oldFactory = view->engine()->networkAccessManagerFactory(); + view->engine()->setNetworkAccessManagerFactory(nullptr); + delete oldFactory; + view->engine()->setNetworkAccessManagerFactory(new NoAccessNetworkAccessManagerFactory); + + QQmlProperty lockProperty(view->rootObject(), QStringLiteral("locked")); + lockProperty.write(m_immediateLock || (!m_noLock && !m_delayedLockTimer)); + + QQmlProperty sleepProperty(view->rootObject(), QStringLiteral("suspendToRamSupported")); + sleepProperty.write(m_canSuspend); + if (view->rootObject() && view->rootObject()->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("suspendToRam()").constData()) != -1) { + connect(view->rootObject(), SIGNAL(suspendToRam()), SLOT(suspendToRam())); + } + + QQmlProperty hibernateProperty(view->rootObject(), QStringLiteral("suspendToDiskSupported")); + hibernateProperty.write(m_canHibernate); + if (view->rootObject() && view->rootObject()->metaObject()->indexOfSignal(QMetaObject::normalizedSignature("suspendToDisk()").constData()) != -1) { + connect(view->rootObject(), SIGNAL(suspendToDisk()), SLOT(suspendToDisk())); + } - // verify that the engine's controller didn't change - Q_ASSERT(dynamic_cast(view->engine()->networkAccessManagerFactory())); + // verify that the engine's controller didn't change + Q_ASSERT(dynamic_cast(view->engine()->networkAccessManagerFactory())); - m_views << view; + m_views << view; + if (shouldResizeDesktops) { + desktopResized(); } +} - // update geometry of all views and savers - for (int i = 0; i < nScreens; ++i) { - auto *view = m_views.at(i); +void UnlockApp::desktopResized() +{ + for(auto view : m_views) { + QScreen *screen = screenFromName(screens(), view->property(screenNameProperty).toString()); + Q_ASSERT(screen); - auto screen = QGuiApplication::screens()[i]; view->setGeometry(screen->geometry()); KWayland::Client::PlasmaShellSurface *plasmaSurface = view->property("plasmaShellSurface").value(); if (plasmaSurface) { @@ -423,6 +446,14 @@ } } +void UnlockApp::loadCurrentScreens() +{ + for (auto *screen : screens()) { + UnlockApp::screenAddedImpl(screen, false); + } + desktopResized(); +} + void UnlockApp::markViewsAsVisible(KQuickAddons::QuickViewSharedEngine *view) { disconnect(view, &QQuickWindow::frameSwapped, this, nullptr); diff --git a/greeter/main.cpp b/greeter/main.cpp --- a/greeter/main.cpp +++ b/greeter/main.cpp @@ -184,6 +184,7 @@ } #endif + app.loadCurrentScreens(); app.desktopResized(); // This allow ksmserver to know when the application has actually finished setting itself up.