File indexing completed on 2024-04-28 16:49:43

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Daniel Vratil <dvratil@redhat.com>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-or-later
0005  *
0006  */
0007 
0008 #include "backendloader.h"
0009 #include "abstractbackend.h"
0010 #include "backenddbuswrapper.h"
0011 #include "backendloaderadaptor.h"
0012 #include "backendmanager_p.h"
0013 #include "kscreen_backendLauncher_debug.h"
0014 
0015 #include <QCoreApplication>
0016 #include <QDBusConnectionInterface>
0017 #include <QDir>
0018 #include <QPluginLoader>
0019 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0020 #include <private/qtx11extras_p.h>
0021 #else
0022 #include <QX11Info>
0023 #endif
0024 
0025 #include <memory>
0026 
0027 #include <QDBusConnection>
0028 #include <QDBusInterface>
0029 
0030 void pluginDeleter(QPluginLoader *p)
0031 {
0032     if (p) {
0033         qCDebug(KSCREEN_BACKEND_LAUNCHER) << "Unloading" << p->fileName();
0034         p->unload();
0035         delete p;
0036     }
0037 }
0038 
0039 BackendLoader::BackendLoader()
0040     : QObject()
0041     , QDBusContext()
0042     , mLoader(nullptr)
0043     , mBackend(nullptr)
0044 {
0045 }
0046 
0047 BackendLoader::~BackendLoader()
0048 {
0049     delete mBackend;
0050     pluginDeleter(mLoader);
0051     qCDebug(KSCREEN_BACKEND_LAUNCHER) << "Backend loader destroyed";
0052 }
0053 
0054 bool BackendLoader::init()
0055 {
0056     QDBusConnection dbus = QDBusConnection::sessionBus();
0057     new BackendLoaderAdaptor(this);
0058     if (!dbus.registerObject(QStringLiteral("/"), this, QDBusConnection::ExportAdaptors)) {
0059         qCWarning(KSCREEN_BACKEND_LAUNCHER) << "Failed to export backend to DBus: another launcher already running?";
0060         qCWarning(KSCREEN_BACKEND_LAUNCHER) << dbus.lastError().message();
0061         return false;
0062     }
0063 
0064     return true;
0065 }
0066 
0067 QString BackendLoader::backend() const
0068 {
0069     if (mBackend) {
0070         return mBackend->backend()->name();
0071     }
0072 
0073     return QString();
0074 }
0075 
0076 bool BackendLoader::requestBackend(const QString &backendName, const QVariantMap &arguments)
0077 {
0078     if (mBackend) {
0079         // If an backend is already loaded, but it's not the same as the one
0080         // requested, then it's an error
0081         if (!backendName.isEmpty() && mBackend->backend()->name() != backendName) {
0082             sendErrorReply(QDBusError::Failed, QStringLiteral("Another backend is already active"));
0083             return false;
0084         } else {
0085             // If caller requested the same one as already loaded, or did not
0086             // request a specific backend, hapilly reuse the existing one
0087             return true;
0088         }
0089     }
0090 
0091     KScreen::AbstractBackend *backend = loadBackend(backendName, arguments);
0092     if (!backend) {
0093         return false;
0094     }
0095 
0096     mBackend = new BackendDBusWrapper(backend);
0097     if (!mBackend->init()) {
0098         delete mBackend;
0099         mBackend = nullptr;
0100         pluginDeleter(mLoader);
0101         mLoader = nullptr;
0102         return false;
0103     }
0104     return true;
0105 }
0106 
0107 KScreen::AbstractBackend *BackendLoader::loadBackend(const QString &name, const QVariantMap &arguments)
0108 {
0109     if (mLoader == nullptr) {
0110         std::unique_ptr<QPluginLoader, void (*)(QPluginLoader *)> loader(new QPluginLoader(), pluginDeleter);
0111         mLoader = loader.release();
0112     }
0113     return KScreen::BackendManager::loadBackendPlugin(mLoader, name, arguments);
0114 }
0115 
0116 void BackendLoader::quit()
0117 {
0118     qApp->quit();
0119 }