diff --git a/greeter/CMakeLists.txt b/greeter/CMakeLists.txt --- a/greeter/CMakeLists.txt +++ b/greeter/CMakeLists.txt @@ -12,6 +12,7 @@ greeterapp.cpp main.cpp noaccessnetworkaccessmanagerfactory.cpp + wallpaper_integration.cpp ) qt5_add_resources(kscreenlocker_greet_SRCS fallbacktheme.qrc) diff --git a/greeter/greeterapp.h b/greeter/greeterapp.h --- a/greeter/greeterapp.h +++ b/greeter/greeterapp.h @@ -44,6 +44,7 @@ namespace ScreenLocker { class Unlocker; +class WallpaperIntegration; class UnlockApp : public QGuiApplication { @@ -83,6 +84,7 @@ void initialize(); void initializeWayland(); void shareEvent(QEvent *e, KQuickAddons::QuickViewSharedEngine *from); + void loadWallpaperPlugin(KQuickAddons::QuickViewSharedEngine *view); QString m_packageName; QUrl m_mainQmlPath; @@ -107,6 +109,7 @@ org_kde_ksld *m_ksldInterface = nullptr; KWayland::Client::PlasmaShell *m_plasmaShell = nullptr; + WallpaperIntegration *m_wallpaperIntegration; }; } // namespace diff --git a/greeter/greeterapp.cpp b/greeter/greeterapp.cpp --- a/greeter/greeterapp.cpp +++ b/greeter/greeterapp.cpp @@ -22,12 +22,14 @@ #include "kscreensaversettings.h" #include "authenticator.h" #include "noaccessnetworkaccessmanagerfactory.h" +#include "wallpaper_integration.h" // KDE #include #include #include #include +#include #include //Plasma #include @@ -51,6 +53,7 @@ #include #include #include +#include #include // Wayland @@ -97,6 +100,7 @@ , m_authenticator(new Authenticator(this)) , m_graceTime(0) , m_noLock(false) + , m_wallpaperIntegration(new WallpaperIntegration(this)) { connect(m_authenticator, &Authenticator::succeeded, this, &QCoreApplication::quit); initialize(); @@ -148,6 +152,10 @@ m_mainQmlPath = QUrl::fromLocalFile(package.filePath("lockscreenmainscript")); + m_wallpaperIntegration->setConfig(KScreenSaverSettings::self()->sharedConfig()); + m_wallpaperIntegration->setPluginName(KScreenSaverSettings::self()->wallpaperPlugin()); + m_wallpaperIntegration->init(); + installEventFilter(this); } @@ -172,6 +180,37 @@ m_plasmaShell = r->createPlasmaShell(i.name, i.version, this); } +void UnlockApp::loadWallpaperPlugin(KQuickAddons::QuickViewSharedEngine *view) +{ + auto package = m_wallpaperIntegration->package(); + if (!package.isValid()) { + qWarning() << "Error loading the wallpaper, no valid package loaded"; + return; + } + + auto qmlObject = new KDeclarative::QmlObjectSharedEngine(view); + qmlObject->setInitializationDelayed(true); + qmlObject->setPackage(package); + qmlObject->rootContext()->setContextProperty(QStringLiteral("wallpaper"), m_wallpaperIntegration); + view->setProperty("wallpaperGraphicsObject", QVariant::fromValue(qmlObject->rootObject())); + connect(qmlObject, &KDeclarative::QmlObject::finished, this, + [this, qmlObject, view] { + auto item = qobject_cast(qmlObject->rootObject()); + if (!item) { + qWarning() << "Wallpaper needs to be a QtQuick Item"; + return; + } + item->setParentItem(view->rootObject()); + item->setZ(-1000); + + //set anchors + QQmlExpression expr(qmlObject->engine()->rootContext(), item, QStringLiteral("parent")); + QQmlProperty prop(item, QStringLiteral("anchors.fill")); + prop.write(expr.evaluate()); + } + ); +} + void UnlockApp::desktopResized() { const int nScreens = screens().count(); @@ -191,11 +230,6 @@ KDeclarative::KDeclarative declarative; declarative.setDeclarativeEngine(view->engine()); declarative.setupBindings(); - // overwrite the factory set by kdeclarative - auto oldFactory = view->engine()->networkAccessManagerFactory(); - view->engine()->setNetworkAccessManagerFactory(nullptr); - delete oldFactory; - view->engine()->setNetworkAccessManagerFactory(new NoAccessNetworkAccessManagerFactory); if (!m_testing) { if (QX11Info::isPlatformX11()) { @@ -219,7 +253,6 @@ } } - // engine stuff QQmlContext* context = view->engine()->rootContext(); const KUser user; @@ -243,6 +276,13 @@ } 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); + QQmlProperty lockProperty(view->rootObject(), QStringLiteral("locked")); lockProperty.write(m_immediateLock || (!m_noLock && !m_delayedLockTimer)); @@ -274,6 +314,13 @@ if (plasmaSurface) { plasmaSurface->setPosition(view->geometry().topLeft()); } + if (auto object = view->property("wallpaperGraphicsObject").value()) { + //initialize with our size to avoid as much resize events as possible + object->completeInitialization({ + {QStringLiteral("width"), view->width()}, + {QStringLiteral("height"), view->height()} + }); + } connect(screen, &QScreen::geometryChanged, diff --git a/greeter/wallpaper_integration.h b/greeter/wallpaper_integration.h new file mode 100644 --- /dev/null +++ b/greeter/wallpaper_integration.h @@ -0,0 +1,84 @@ +/******************************************************************** + KSld - the KDE Screenlocker Daemon + This file is part of the KDE project. + +Copyright (C) 2016 Martin Gräßlin + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#ifndef KSCREENLOCKER_WALLPAPER_INTEGRATION_H +#define KSCREENLOCKER_WALLPAPER_INTEGRATION_H + +#include +#include + +class KConfigLoader; + +namespace KDeclarative +{ +class ConfigPropertyMap; +class QmlObject; +} + +namespace ScreenLocker +{ + +class WallpaperIntegration : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString pluginName READ pluginName NOTIFY packageChanged) + Q_PROPERTY(KDeclarative::ConfigPropertyMap *configuration READ configuration NOTIFY configurationChanged) + +public: + WallpaperIntegration(QObject *parent); + virtual ~WallpaperIntegration(); + + void init(); + + void setConfig(const KSharedConfig::Ptr &config) { + m_config = config; + } + QString pluginName() const { + return m_pluginName; + } + void setPluginName(const QString &name); + + KPackage::Package package() const { + return m_package; + } + + KDeclarative::ConfigPropertyMap *configuration() const { + return m_configuration; + } + +Q_SIGNALS: + void packageChanged(); + void configurationChanged(); + +private: + KConfigLoader *configScheme(); + QString m_pluginName; + KPackage::Package m_package; + KSharedConfig::Ptr m_config; + KConfigLoader *m_configLoader = nullptr; + KDeclarative::ConfigPropertyMap *m_configuration = nullptr; +}; + +} + +#endif diff --git a/greeter/wallpaper_integration.cpp b/greeter/wallpaper_integration.cpp new file mode 100644 --- /dev/null +++ b/greeter/wallpaper_integration.cpp @@ -0,0 +1,82 @@ +/******************************************************************** + KSld - the KDE Screenlocker Daemon + This file is part of the KDE project. + +Copyright (C) 2016 Martin Gräßlin + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of +the License or (at your option) version 3 or any later version +accepted by the membership of KDE e.V. (or its successor approved +by the membership of KDE e.V.), which shall act as a proxy +defined in Section 14 of version 3 of the license. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*********************************************************************/ +#include "wallpaper_integration.h" + +#include +#include +#include +#include +#include + +#include + +namespace ScreenLocker +{ + +WallpaperIntegration::WallpaperIntegration(QObject *parent) + : QObject(parent) + , m_package(KPackage::PackageLoader::self()->loadPackage(QStringLiteral("Plasma/Wallpaper"))) +{ + qRegisterMetaType(); +} + +WallpaperIntegration::~WallpaperIntegration() = default; + +void WallpaperIntegration::init() +{ + if (!m_package.isValid()) { + return; + } + if (auto config = configScheme()) { + m_configuration = new KDeclarative::ConfigPropertyMap(config, this); + } +} + +void WallpaperIntegration::setPluginName(const QString &name) +{ + if (m_pluginName == name) { + return; + } + m_pluginName = name; + m_package.setPath(name); + emit packageChanged(); +} + +KConfigLoader *WallpaperIntegration::configScheme() +{ + if (!m_configLoader) { + const QString xmlPath = m_package.filePath(QByteArrayLiteral("config"), QStringLiteral("main.xml")); + + const KConfigGroup cfg = m_config->group("Greeter").group("Wallpaper").group(m_pluginName); + + if (xmlPath.isEmpty()) { + m_configLoader = new KConfigLoader(cfg, 0, this); + } else { + QFile file(xmlPath); + m_configLoader = new KConfigLoader(cfg, &file, this); + } + } + return m_configLoader; +} + +} diff --git a/kcfg/kscreenlockersettings.kcfg b/kcfg/kscreenlockersettings.kcfg --- a/kcfg/kscreenlockersettings.kcfg +++ b/kcfg/kscreenlockersettings.kcfg @@ -43,5 +43,10 @@ + + org.kde.image + + +