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 }