File indexing completed on 2024-04-21 03:59:29
0001 /* 0002 SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 #include "kwindoweffects_dummy_p.h" 0007 #include "kwindowshadow_dummy_p.h" 0008 #include "kwindowsystem_debug.h" 0009 #include "kwindowsystem_dummy_p.h" 0010 #include "kwindowsystemplugininterface_p.h" 0011 #include "pluginwrapper_p.h" 0012 0013 #include <QDir> 0014 #include <QGuiApplication> 0015 #include <QJsonArray> 0016 #include <QLibrary> 0017 #include <QPluginLoader> 0018 0019 Q_GLOBAL_STATIC(KWindowSystemPluginWrapper, s_pluginWrapper) 0020 0021 static QStringList pluginCandidates() 0022 { 0023 QStringList ret; 0024 const auto paths = QCoreApplication::libraryPaths(); 0025 for (const QString &path : paths) { 0026 static const QStringList searchFolders{ 0027 QStringLiteral("/kf6/org.kde.kwindowsystem.platforms"), 0028 QStringLiteral("/kf6/kwindowsystem"), 0029 }; 0030 for (const QString &searchFolder : searchFolders) { 0031 QDir pluginDir(path + searchFolder); 0032 if (!pluginDir.exists()) { 0033 continue; 0034 } 0035 const auto entries = pluginDir.entryList(QDir::Files | QDir::NoDotAndDotDot); 0036 for (const QString &entry : entries) { 0037 ret << pluginDir.absoluteFilePath(entry); 0038 } 0039 } 0040 } 0041 return ret; 0042 } 0043 0044 static bool checkPlatform(const QJsonObject &metadata, const QString &platformName) 0045 { 0046 const QJsonArray platforms = metadata.value(QStringLiteral("MetaData")).toObject().value(QStringLiteral("platforms")).toArray(); 0047 return std::any_of(platforms.begin(), platforms.end(), [&platformName](const QJsonValue &value) { 0048 return QString::compare(platformName, value.toString(), Qt::CaseInsensitive) == 0; 0049 }); 0050 } 0051 0052 static KWindowSystemPluginInterface *loadPlugin() 0053 { 0054 if (!qobject_cast<QGuiApplication *>(QCoreApplication::instance())) { 0055 qCWarning(LOG_KWINDOWSYSTEM) << "Cannot use KWindowSystem without a QGuiApplication"; 0056 return nullptr; 0057 } 0058 0059 QString platformName = QGuiApplication::platformName(); 0060 if (platformName == QLatin1String("flatpak")) { 0061 // here we cannot know what is the actual windowing system, let's try it's env variable 0062 const auto flatpakPlatform = QString::fromLocal8Bit(qgetenv("QT_QPA_FLATPAK_PLATFORM")); 0063 if (!flatpakPlatform.isEmpty()) { 0064 platformName = flatpakPlatform; 0065 } 0066 } 0067 0068 const QList<QStaticPlugin> staticPlugins = QPluginLoader::staticPlugins(); 0069 for (const QStaticPlugin &staticPlugin : staticPlugins) { 0070 const QJsonObject metadata = staticPlugin.metaData(); 0071 if (metadata.value(QLatin1String("IID")) != QLatin1String(KWindowSystemPluginInterface_iid)) { 0072 continue; 0073 } 0074 if (checkPlatform(metadata, platformName)) { 0075 KWindowSystemPluginInterface *interface = qobject_cast<KWindowSystemPluginInterface *>(staticPlugin.instance()); 0076 if (interface) { 0077 qCDebug(LOG_KWINDOWSYSTEM) << "Loaded a static plugin for platform" << platformName; 0078 return interface; 0079 } 0080 } 0081 } 0082 0083 const auto candidates = pluginCandidates(); 0084 for (const QString &candidate : candidates) { 0085 if (!QLibrary::isLibrary(candidate)) { 0086 continue; 0087 } 0088 QPluginLoader loader(candidate); 0089 if (checkPlatform(loader.metaData(), platformName)) { 0090 KWindowSystemPluginInterface *interface = qobject_cast<KWindowSystemPluginInterface *>(loader.instance()); 0091 if (interface) { 0092 qCDebug(LOG_KWINDOWSYSTEM) << "Loaded plugin" << candidate << "for platform" << platformName; 0093 return interface; 0094 } 0095 } 0096 } 0097 0098 qCWarning(LOG_KWINDOWSYSTEM) << "Could not find any platform plugin"; 0099 return nullptr; 0100 } 0101 0102 KWindowSystemPluginWrapper::KWindowSystemPluginWrapper() 0103 : m_plugin(loadPlugin()) 0104 , m_effects() 0105 { 0106 if (m_plugin) { 0107 m_effects.reset(m_plugin->createEffects()); 0108 } 0109 if (!m_effects) { 0110 m_effects.reset(new KWindowEffectsPrivateDummy()); 0111 } 0112 } 0113 0114 KWindowSystemPluginWrapper::~KWindowSystemPluginWrapper() 0115 { 0116 } 0117 0118 KWindowEffectsPrivate *KWindowSystemPluginWrapper::effects() const 0119 { 0120 return m_effects.get(); 0121 } 0122 0123 KWindowSystemPrivate *KWindowSystemPluginWrapper::createWindowSystem() const 0124 { 0125 KWindowSystemPrivate *p = nullptr; 0126 if (m_plugin) { 0127 p = m_plugin->createWindowSystem(); 0128 } 0129 if (!p) { 0130 p = new KWindowSystemPrivateDummy(); 0131 } 0132 return p; 0133 } 0134 0135 KWindowShadowPrivate *KWindowSystemPluginWrapper::createWindowShadow() const 0136 { 0137 KWindowShadowPrivate *p = nullptr; 0138 if (m_plugin) { 0139 p = m_plugin->createWindowShadow(); 0140 } 0141 if (!p) { 0142 p = new KWindowShadowPrivateDummy(); 0143 } 0144 return p; 0145 } 0146 0147 KWindowShadowTilePrivate *KWindowSystemPluginWrapper::createWindowShadowTile() const 0148 { 0149 KWindowShadowTilePrivate *p = nullptr; 0150 if (m_plugin) { 0151 p = m_plugin->createWindowShadowTile(); 0152 } 0153 if (!p) { 0154 p = new KWindowShadowTilePrivateDummy(); 0155 } 0156 return p; 0157 } 0158 0159 const KWindowSystemPluginWrapper &KWindowSystemPluginWrapper::self() 0160 { 0161 return *s_pluginWrapper; 0162 }