KWindowSystem

pluginwrapper.cpp
1 /*
2  SPDX-FileCopyrightText: 2015 Martin Gräßlin <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5 */
6 #include "kwindoweffects_dummy_p.h"
7 #include "kwindowinfo_dummy_p.h"
8 #include "kwindowshadow_dummy_p.h"
9 #include "kwindowsystem_debug.h"
10 #include "kwindowsystem_dummy_p.h"
11 #include "kwindowsystemplugininterface_p.h"
12 #include "pluginwrapper_p.h"
13 
14 #include <QDir>
15 #include <QGuiApplication>
16 #include <QJsonArray>
17 #include <QLibrary>
18 #include <QPluginLoader>
19 
20 Q_GLOBAL_STATIC(KWindowSystemPluginWrapper, s_pluginWrapper)
21 
22 static QStringList pluginCandidates()
23 {
24  QStringList ret;
25  const auto paths = QCoreApplication::libraryPaths();
26  for (const QString &path : paths) {
27  static const QStringList searchFolders{
28  QStringLiteral("/kf5/org.kde.kwindowsystem.platforms"),
29  QStringLiteral("/kf5/kwindowsystem"),
30  };
31  for (const QString &searchFolder : searchFolders) {
32  QDir pluginDir(path + searchFolder);
33  if (!pluginDir.exists()) {
34  continue;
35  }
36  const auto entries = pluginDir.entryList(QDir::Files | QDir::NoDotAndDotDot);
37  for (const QString &entry : entries) {
38  ret << pluginDir.absoluteFilePath(entry);
39  }
40  }
41  }
42  return ret;
43 }
44 
45 static bool checkPlatform(const QJsonObject &metadata, const QString &platformName)
46 {
47  const QJsonArray platforms = metadata.value(QStringLiteral("MetaData")).toObject().value(QStringLiteral("platforms")).toArray();
48  return std::any_of(platforms.begin(), platforms.end(), [&platformName](const QJsonValue &value) {
49  return QString::compare(platformName, value.toString(), Qt::CaseInsensitive) == 0;
50  });
51 }
52 
53 static KWindowSystemPluginInterface *loadPlugin()
54 {
55  if (!qobject_cast<QGuiApplication *>(QCoreApplication::instance())) {
56  qCWarning(LOG_KWINDOWSYSTEM) << "Cannot use KWindowSystem without a QGuiApplication";
57  return nullptr;
58  }
59 
60  QString platformName = QGuiApplication::platformName();
61  if (platformName == QLatin1String("flatpak")) {
62  // here we cannot know what is the actual windowing system, let's try it's env variable
63  const auto flatpakPlatform = QString::fromLocal8Bit(qgetenv("QT_QPA_FLATPAK_PLATFORM"));
64  if (!flatpakPlatform.isEmpty()) {
65  platformName = flatpakPlatform;
66  }
67  }
68 
70  for (const QStaticPlugin &staticPlugin : staticPlugins) {
71  const QJsonObject metadata = staticPlugin.metaData();
72  if (metadata.value(QLatin1String("IID")) != QLatin1String(KWindowSystemPluginInterface_iid)) {
73  continue;
74  }
75  if (checkPlatform(metadata, platformName)) {
76  KWindowSystemPluginInterface *interface = qobject_cast<KWindowSystemPluginInterface *>(staticPlugin.instance());
77  if (interface) {
78  qCDebug(LOG_KWINDOWSYSTEM) << "Loaded a static plugin for platform" << platformName;
79  return interface;
80  }
81  }
82  }
83 
84  const auto candidates = pluginCandidates();
85  for (const QString &candidate : candidates) {
86  if (!QLibrary::isLibrary(candidate)) {
87  continue;
88  }
89  QPluginLoader loader(candidate);
90  if (checkPlatform(loader.metaData(), platformName)) {
91  KWindowSystemPluginInterface *interface = qobject_cast<KWindowSystemPluginInterface *>(loader.instance());
92  if (interface) {
93  qCDebug(LOG_KWINDOWSYSTEM) << "Loaded plugin" << candidate << "for platform" << platformName;
94  return interface;
95  }
96  }
97  }
98 
99  qCWarning(LOG_KWINDOWSYSTEM) << "Could not find any platform plugin";
100  return nullptr;
101 }
102 
103 KWindowSystemPluginWrapper::KWindowSystemPluginWrapper()
104  : m_plugin(loadPlugin())
105  , m_effects()
106 {
107  if (!m_plugin.isNull()) {
108  m_effects.reset(m_plugin->createEffects());
109  }
110  if (m_effects.isNull()) {
111  m_effects.reset(new KWindowEffectsPrivateDummy());
112  }
113 }
114 
115 KWindowSystemPluginWrapper::~KWindowSystemPluginWrapper()
116 {
117 }
118 
119 KWindowEffectsPrivate *KWindowSystemPluginWrapper::effects() const
120 {
121  return m_effects.data();
122 }
123 
124 KWindowSystemPrivate *KWindowSystemPluginWrapper::createWindowSystem() const
125 {
126  KWindowSystemPrivate *p = nullptr;
127  if (!m_plugin.isNull()) {
128  p = m_plugin->createWindowSystem();
129  }
130  if (!p) {
131  p = new KWindowSystemPrivateDummy();
132  }
133  return p;
134 }
135 
136 KWindowInfoPrivate *KWindowSystemPluginWrapper::createWindowInfo(WId window, NET::Properties properties, NET::Properties2 properties2) const
137 {
138  KWindowInfoPrivate *p = nullptr;
139  if (!m_plugin.isNull()) {
140  p = m_plugin->createWindowInfo(window, properties, properties2);
141  }
142  if (!p) {
143  p = new KWindowInfoPrivateDummy(window, properties, properties2);
144  }
145  return p;
146 }
147 
148 KWindowShadowPrivate *KWindowSystemPluginWrapper::createWindowShadow() const
149 {
150  KWindowShadowPrivate *p = nullptr;
151  if (!m_plugin.isNull()) {
152  p = m_plugin->createWindowShadow();
153  }
154  if (!p) {
155  p = new KWindowShadowPrivateDummy();
156  }
157  return p;
158 }
159 
160 KWindowShadowTilePrivate *KWindowSystemPluginWrapper::createWindowShadowTile() const
161 {
162  KWindowShadowTilePrivate *p = nullptr;
163  if (!m_plugin.isNull()) {
164  p = m_plugin->createWindowShadowTile();
165  }
166  if (!p) {
167  p = new KWindowShadowTilePrivateDummy();
168  }
169  return p;
170 }
171 
172 const KWindowSystemPluginWrapper &KWindowSystemPluginWrapper::self()
173 {
174  return *s_pluginWrapper;
175 }
QJsonArray::iterator begin()
QVector< QStaticPlugin > staticPlugins()
QString fromLocal8Bit(const char *str, int size)
QJsonObject toObject() const const
CaseInsensitive
QJsonArray toArray() const const
QCoreApplication * instance()
QJsonArray::iterator end()
QStringList libraryPaths()
QJsonValue value(const QString &key) const const
int compare(const QString &other, Qt::CaseSensitivity cs) const const
QString platformName()
bool isLibrary(const QString &fileName)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Oct 15 2021 22:41:50 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.