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