File indexing completed on 2024-12-08 07:59:35
0001 /* 0002 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "pluginmanager.h" 0008 #include "dbusinterface.h" 0009 #include "main.h" 0010 #include "plugin.h" 0011 #include "utils/common.h" 0012 0013 #include <KConfigGroup> 0014 #include <KPluginFactory> 0015 #include <KPluginMetaData> 0016 #include <QPluginLoader> 0017 0018 namespace KWin 0019 { 0020 0021 static const QString s_pluginDirectory = QStringLiteral("kwin/plugins"); 0022 0023 static QJsonValue readPluginInfo(const QJsonObject &metadata, const QString &key) 0024 { 0025 return metadata.value(QLatin1String("KPlugin")).toObject().value(key); 0026 } 0027 0028 PluginManager::PluginManager() 0029 { 0030 const KConfigGroup config(kwinApp()->config(), QStringLiteral("Plugins")); 0031 0032 auto checkEnabled = [&config](const QString &pluginId, const QJsonObject &metadata) { 0033 const QString configKey = pluginId + QLatin1String("Enabled"); 0034 if (config.hasKey(configKey)) { 0035 return config.readEntry(configKey, false); 0036 } 0037 return readPluginInfo(metadata, QStringLiteral("EnabledByDefault")).toBool(false); 0038 }; 0039 0040 const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(s_pluginDirectory); 0041 for (const KPluginMetaData &metadata : plugins) { 0042 if (m_plugins.find(metadata.pluginId()) != m_plugins.end()) { 0043 qCWarning(KWIN_CORE) << "Conflicting plugin id" << metadata.pluginId(); 0044 continue; 0045 } 0046 if (checkEnabled(metadata.pluginId(), metadata.rawData())) { 0047 loadPlugin(metadata); 0048 } 0049 } 0050 0051 new PluginManagerDBusInterface(this); 0052 } 0053 0054 PluginManager::~PluginManager() = default; 0055 0056 QStringList PluginManager::loadedPlugins() const 0057 { 0058 QStringList ret; 0059 ret.reserve(m_plugins.size()); 0060 for (const auto &[key, _] : m_plugins) { 0061 ret.push_back(key); 0062 } 0063 return ret; 0064 } 0065 0066 QStringList PluginManager::availablePlugins() const 0067 { 0068 const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(s_pluginDirectory); 0069 0070 QStringList ret; 0071 ret.reserve(plugins.size()); 0072 0073 for (const KPluginMetaData &metadata : plugins) { 0074 ret.append(metadata.pluginId()); 0075 } 0076 0077 return ret; 0078 } 0079 0080 bool PluginManager::loadPlugin(const QString &pluginId) 0081 { 0082 if (m_plugins.find(pluginId) != m_plugins.end()) { 0083 qCDebug(KWIN_CORE) << "Plugin with id" << pluginId << "is already loaded"; 0084 return false; 0085 } 0086 const KPluginMetaData metadata = KPluginMetaData::findPluginById(s_pluginDirectory, pluginId); 0087 if (metadata.isValid()) { 0088 if (loadPlugin(metadata)) { 0089 return true; 0090 } 0091 } 0092 return false; 0093 } 0094 0095 bool PluginManager::loadPlugin(const KPluginMetaData &metadata) 0096 { 0097 if (!metadata.isValid()) { 0098 qCDebug(KWIN_CORE) << "PluginManager::loadPlugin needs a valid plugin metadata"; 0099 return false; 0100 } 0101 0102 const QString pluginId = metadata.pluginId(); 0103 QPluginLoader pluginLoader(metadata.fileName()); 0104 if (pluginLoader.metaData().value("IID").toString() != PluginFactory_iid) { 0105 qCWarning(KWIN_CORE) << pluginId << "has mismatching plugin version"; 0106 return false; 0107 } 0108 0109 std::unique_ptr<PluginFactory> factory(qobject_cast<PluginFactory *>(pluginLoader.instance())); 0110 if (!factory) { 0111 qCWarning(KWIN_CORE) << "Failed to get plugin factory for" << pluginId; 0112 return false; 0113 } 0114 0115 if (std::unique_ptr<Plugin> plugin = factory->create()) { 0116 m_plugins[pluginId] = std::move(plugin); 0117 return true; 0118 } else { 0119 return false; 0120 } 0121 } 0122 0123 void PluginManager::unloadPlugin(const QString &pluginId) 0124 { 0125 auto it = m_plugins.find(pluginId); 0126 if (it != m_plugins.end()) { 0127 m_plugins.erase(it); 0128 } else { 0129 qCWarning(KWIN_CORE) << "No plugin with the specified id:" << pluginId; 0130 } 0131 } 0132 0133 } // namespace KWin 0134 0135 #include "moc_pluginmanager.cpp"