Introduce infrastructure for compositor extensions
The scripting api is not suitable for implementing all features that should not be implemented in libkwin. For example, the krunner integration or screencasting are the things that don't belong to be compiled right into kwin and yet we don't have any other choice. This change introduces a quick and dirty plugin infrastructure that can be used to implement things such as colord integration, krunner integration, etc.
This commit is contained in:
parent
a482d73de2
commit
c766e5da6d
25 changed files with 516 additions and 33 deletions
|
@ -1,8 +1,7 @@
|
|||
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
|
||||
|
||||
project(KWin)
|
||||
set(PROJECT_VERSION "5.20.80")
|
||||
set(PROJECT_VERSION_MAJOR 5)
|
||||
set(PROJECT_VERSION "5.20.80") # Handled by release scripts
|
||||
project(KWin VERSION ${PROJECT_VERSION})
|
||||
|
||||
set(QT_MIN_VERSION "5.15.0")
|
||||
set(KF5_MIN_VERSION "5.74")
|
||||
|
@ -506,6 +505,8 @@ set(kwin_SRCS
|
|||
overlaywindow.cpp
|
||||
placement.cpp
|
||||
platform.cpp
|
||||
plugin.cpp
|
||||
pluginmanager.cpp
|
||||
pointer_input.cpp
|
||||
popup_input_filter.cpp
|
||||
rootinfo_filter.cpp
|
||||
|
@ -633,6 +634,7 @@ qt5_add_dbus_adaptor(kwin_SRCS org.kde.kwin.ColorCorrect.xml colorcorrection/col
|
|||
qt5_add_dbus_adaptor(kwin_SRCS ${kwin_effects_dbus_xml} effects.h KWin::EffectsHandlerImpl)
|
||||
qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.VirtualDesktopManager.xml dbusinterface.h KWin::VirtualDesktopManagerDBusInterface)
|
||||
qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.Session.xml sm.h KWin::SessionManager)
|
||||
qt5_add_dbus_adaptor(kwin_SRCS org.kde.KWin.Plugins.xml dbusinterface.h KWin::PluginManagerDBusInterface)
|
||||
if (KWIN_BUILD_RUNNERS)
|
||||
qt5_add_dbus_adaptor(kwin_SRCS "runners/org.kde.krunner1.xml" runners/windowsrunnerinterface.h KWin::WindowsRunner)
|
||||
endif()
|
||||
|
@ -781,30 +783,8 @@ set(kwin_WAYLAND_SRCS
|
|||
main_wayland.cpp
|
||||
tabletmodemanager.cpp
|
||||
)
|
||||
ecm_qt_declare_logging_category(kwin_WAYLAND_SRCS
|
||||
HEADER
|
||||
kwinscreencast_logging.h
|
||||
IDENTIFIER
|
||||
KWIN_SCREENCAST
|
||||
CATEGORY_NAME
|
||||
kwin_screencast
|
||||
DEFAULT_SEVERITY
|
||||
Warning
|
||||
)
|
||||
|
||||
add_executable(kwin_wayland ${kwin_WAYLAND_SRCS} ${kwin_XWAYLAND_SRCS})
|
||||
|
||||
|
||||
if (PipeWire_FOUND)
|
||||
target_sources(kwin_wayland
|
||||
PRIVATE
|
||||
screencast/eglnativefence.cpp
|
||||
screencast/screencastmanager.cpp
|
||||
screencast/pipewirecore.cpp
|
||||
screencast/pipewirestream.cpp)
|
||||
target_link_libraries(kwin_wayland PkgConfig::PipeWire)
|
||||
endif()
|
||||
|
||||
target_link_libraries(kwin_wayland
|
||||
kwin
|
||||
KF5::Crash
|
||||
|
@ -834,6 +814,10 @@ target_link_libraries(kwin_wayland
|
|||
KF5IdleTimeKWinPlugin
|
||||
)
|
||||
|
||||
if (PipeWire_FOUND)
|
||||
target_link_libraries(kwin_wayland KWinScreencastPlugin)
|
||||
endif()
|
||||
|
||||
########### install files ###############
|
||||
|
||||
install(FILES kwin.kcfg DESTINATION ${KCFG_INSTALL_DIR} RENAME ${KWIN_NAME}.kcfg)
|
||||
|
@ -846,6 +830,7 @@ install(
|
|||
org.kde.kwin.ColorCorrect.xml
|
||||
org.kde.kwin.Compositing.xml
|
||||
org.kde.kwin.Effects.xml
|
||||
org.kde.KWin.Plugins.xml
|
||||
DESTINATION
|
||||
${KDE_INSTALL_DBUSINTERFACEDIR}
|
||||
)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*/
|
||||
#include "kwin_wayland_test.h"
|
||||
#include "../../platform.h"
|
||||
#include "../../pluginmanager.h"
|
||||
#include "../../composite.h"
|
||||
#include "../../effects.h"
|
||||
#include "../../wayland_server.h"
|
||||
|
@ -130,6 +131,7 @@ void WaylandTestApplication::performStartup()
|
|||
// try creating the Wayland Backend
|
||||
createInput();
|
||||
createBackend();
|
||||
PluginManager::create(this);
|
||||
}
|
||||
|
||||
void WaylandTestApplication::createBackend()
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
#define KWIN_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}
|
||||
#define KWIN_VERSION_MINOR ${PROJECT_VERSION_MINOR}
|
||||
#define KWIN_VERSION_PATCH ${PROJECT_VERSION_PATCH}
|
||||
|
||||
#cmakedefine KWIN_BUILD_DECORATIONS 1
|
||||
#cmakedefine KWIN_BUILD_TABBOX 1
|
||||
#cmakedefine KWIN_BUILD_ACTIVITIES 1
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
// own
|
||||
#include "dbusinterface.h"
|
||||
#include "compositingadaptor.h"
|
||||
#include "pluginsadaptor.h"
|
||||
#include "virtualdesktopmanageradaptor.h"
|
||||
|
||||
// kwin
|
||||
|
@ -20,6 +21,7 @@
|
|||
#include "main.h"
|
||||
#include "placement.h"
|
||||
#include "platform.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "kwinadaptor.h"
|
||||
#include "scene.h"
|
||||
#include "unmanaged.h"
|
||||
|
@ -515,4 +517,35 @@ void VirtualDesktopManagerDBusInterface::removeDesktop(const QString &id)
|
|||
m_manager->removeVirtualDesktop(id.toUtf8());
|
||||
}
|
||||
|
||||
PluginManagerDBusInterface::PluginManagerDBusInterface(PluginManager *manager)
|
||||
: QObject(manager)
|
||||
, m_manager(manager)
|
||||
{
|
||||
new PluginsAdaptor(this);
|
||||
|
||||
QDBusConnection::sessionBus().registerObject(QStringLiteral("/Plugins"),
|
||||
QStringLiteral("org.kde.KWin.Plugins"),
|
||||
this);
|
||||
}
|
||||
|
||||
QStringList PluginManagerDBusInterface::loadedPlugins() const
|
||||
{
|
||||
return m_manager->loadedPlugins();
|
||||
}
|
||||
|
||||
QStringList PluginManagerDBusInterface::availablePlugins() const
|
||||
{
|
||||
return m_manager->availablePlugins();
|
||||
}
|
||||
|
||||
bool PluginManagerDBusInterface::LoadPlugin(const QString &name)
|
||||
{
|
||||
return m_manager->loadPlugin(name);
|
||||
}
|
||||
|
||||
void PluginManagerDBusInterface::UnloadPlugin(const QString &name)
|
||||
{
|
||||
m_manager->unloadPlugin(name);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
class Compositor;
|
||||
class PluginManager;
|
||||
class VirtualDesktopManager;
|
||||
|
||||
/**
|
||||
|
@ -238,6 +239,28 @@ private:
|
|||
VirtualDesktopManager *m_manager;
|
||||
};
|
||||
|
||||
class PluginManagerDBusInterface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.kde.KWin.Plugins")
|
||||
|
||||
Q_PROPERTY(QStringList LoadedPlugins READ loadedPlugins)
|
||||
Q_PROPERTY(QStringList AvailablePlugins READ availablePlugins)
|
||||
|
||||
public:
|
||||
explicit PluginManagerDBusInterface(PluginManager *manager);
|
||||
|
||||
QStringList loadedPlugins() const;
|
||||
QStringList availablePlugins() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
bool LoadPlugin(const QString &name);
|
||||
void UnloadPlugin(const QString &name);
|
||||
|
||||
private:
|
||||
PluginManager *m_manager;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // KWIN_DBUS_INTERFACE_H
|
||||
|
|
|
@ -14,11 +14,9 @@
|
|||
// kwin
|
||||
#include "platform.h"
|
||||
#include "effects.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "tabletmodemanager.h"
|
||||
|
||||
#ifdef PipeWire_FOUND
|
||||
#include "screencast/screencastmanager.h"
|
||||
#endif
|
||||
#include "wayland_server.h"
|
||||
#include "xwl/xwayland.h"
|
||||
|
||||
|
@ -64,6 +62,9 @@ Q_IMPORT_PLUGIN(KWinIntegrationPlugin)
|
|||
Q_IMPORT_PLUGIN(KGlobalAccelImpl)
|
||||
Q_IMPORT_PLUGIN(KWindowSystemKWinPlugin)
|
||||
Q_IMPORT_PLUGIN(KWinIdleTimePoller)
|
||||
#ifdef PipeWire_FOUND
|
||||
Q_IMPORT_PLUGIN(ScreencastManagerFactory)
|
||||
#endif
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
@ -157,9 +158,7 @@ void ApplicationWayland::performStartup()
|
|||
InputMethod::create(this);
|
||||
createBackend();
|
||||
TabletModeManager::create(this);
|
||||
#ifdef PipeWire_FOUND
|
||||
new ScreencastManager(this);
|
||||
#endif
|
||||
PluginManager::create(this);
|
||||
}
|
||||
|
||||
void ApplicationWayland::createBackend()
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <config-kwin.h>
|
||||
|
||||
#include "platform.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "sm.h"
|
||||
#include "workspace.h"
|
||||
#include "xcbutils.h"
|
||||
|
@ -248,6 +249,7 @@ void ApplicationX11::performStartup()
|
|||
connect(platform(), &Platform::screensQueried, this,
|
||||
[this] {
|
||||
createWorkspace();
|
||||
PluginManager::create(this);
|
||||
|
||||
Xcb::sync(); // Trigger possible errors, there's still a chance to abort
|
||||
|
||||
|
|
32
org.kde.KWin.Plugins.xml
Normal file
32
org.kde.KWin.Plugins.xml
Normal file
|
@ -0,0 +1,32 @@
|
|||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.kde.KWin.Plugins">
|
||||
<!--
|
||||
The list of all currently loaded plugins.
|
||||
-->
|
||||
<property name="LoadedPlugins" type="as" access="read"/>
|
||||
|
||||
<!--
|
||||
The list of all available plugins.
|
||||
-->
|
||||
<property name="AvailablePlugins" type="as" access="read"/>
|
||||
|
||||
<!--
|
||||
Loads a plugin with the specified @a name.
|
||||
|
||||
If the plugin has been loaded successfully, @c true will be returned;
|
||||
otherwise @c false is returned.
|
||||
-->
|
||||
<method name="LoadPlugin">
|
||||
<arg type="b" direction="out"/>
|
||||
<arg name="name" type="s" direction="in"/>
|
||||
</method>
|
||||
|
||||
<!--
|
||||
Unloads a plugin with the specified @a name.
|
||||
-->
|
||||
<method name="UnloadPlugin">
|
||||
<arg name="name" type="s" direction="in"/>
|
||||
</method>
|
||||
</interface>
|
||||
</node>
|
22
plugin.cpp
Normal file
22
plugin.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
Plugin::Plugin(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
PluginFactory::PluginFactory(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace KWin
|
52
plugin.h
Normal file
52
plugin.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <config-kwin.h>
|
||||
|
||||
#include "kwinglobals.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
#define KWIN_PLUGIN_API_VERSION QT_VERSION_CHECK(KWIN_VERSION_MAJOR, \
|
||||
KWIN_VERSION_MINOR, \
|
||||
KWIN_VERSION_PATCH)
|
||||
|
||||
#define PluginFactory_iid "org.kde.kwin.PluginFactoryInterface"
|
||||
|
||||
/**
|
||||
* The Plugin class is the baseclass for all binary compositor extensions.
|
||||
*
|
||||
* Note that a binary extension must be recompiled with every new KWin release.
|
||||
*/
|
||||
class KWIN_EXPORT Plugin : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Plugin(QObject *parent = nullptr);
|
||||
};
|
||||
|
||||
/**
|
||||
* The PluginFactory class creates binary compositor extensions.
|
||||
*/
|
||||
class KWIN_EXPORT PluginFactory : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PluginFactory(QObject *parent = nullptr);
|
||||
|
||||
virtual Plugin *create() const = 0;
|
||||
};
|
||||
|
||||
} // namespace KWin
|
||||
|
||||
Q_DECLARE_INTERFACE(KWin::PluginFactory, PluginFactory_iid)
|
188
pluginmanager.cpp
Normal file
188
pluginmanager.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "pluginmanager.h"
|
||||
#include "dbusinterface.h"
|
||||
#include "main.h"
|
||||
#include "plugin.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <KConfigGroup>
|
||||
#include <KPluginFactory>
|
||||
#include <KPluginLoader>
|
||||
#include <KPluginMetaData>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
KWIN_SINGLETON_FACTORY(PluginManager)
|
||||
|
||||
static const QString s_pluginDirectory = QStringLiteral("kwin/plugins");
|
||||
|
||||
static QJsonValue readPluginInfo(const QJsonObject &metadata, const QString &key)
|
||||
{
|
||||
return metadata.value(QLatin1String("KPlugin")).toObject().value(key);
|
||||
}
|
||||
|
||||
PluginManager::PluginManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
const KConfigGroup config(kwinApp()->config(), QStringLiteral("Plugins"));
|
||||
|
||||
auto checkEnabled = [&config](const QString &pluginId, const QJsonObject &metadata) {
|
||||
const QString configKey = pluginId + QLatin1String("Enabled");
|
||||
if (config.hasKey(configKey)) {
|
||||
return config.readEntry(configKey, false);
|
||||
}
|
||||
return readPluginInfo(metadata, QStringLiteral("EnabledByDefault")).toBool(false);
|
||||
};
|
||||
|
||||
const QVector<QStaticPlugin> staticPlugins = QPluginLoader::staticPlugins();
|
||||
for (const QStaticPlugin &staticPlugin : staticPlugins) {
|
||||
const QJsonObject rootMetaData = staticPlugin.metaData();
|
||||
if (rootMetaData.value(QLatin1String("IID")) != QLatin1String(PluginFactory_iid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const QJsonObject pluginMetaData = rootMetaData.value(QLatin1String("MetaData")).toObject();
|
||||
const QString pluginId = readPluginInfo(pluginMetaData, QStringLiteral("Id")).toString();
|
||||
if (pluginId.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (m_staticPlugins.contains(pluginId)) {
|
||||
qCWarning(KWIN_CORE) << "Conflicting plugin id" << pluginId;
|
||||
continue;
|
||||
}
|
||||
|
||||
m_staticPlugins.insert(pluginId, staticPlugin);
|
||||
|
||||
if (checkEnabled(pluginId, pluginMetaData)) {
|
||||
loadStaticPlugin(pluginId);
|
||||
}
|
||||
}
|
||||
|
||||
const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(s_pluginDirectory);
|
||||
for (const KPluginMetaData &metadata : plugins) {
|
||||
if (m_plugins.contains(metadata.pluginId())) {
|
||||
qCWarning(KWIN_CORE) << "Conflicting plugin id" << metadata.pluginId();
|
||||
continue;
|
||||
}
|
||||
if (checkEnabled(metadata.pluginId(), metadata.rawData())) {
|
||||
loadDynamicPlugin(metadata);
|
||||
}
|
||||
}
|
||||
|
||||
new PluginManagerDBusInterface(this);
|
||||
}
|
||||
|
||||
PluginManager::~PluginManager()
|
||||
{
|
||||
s_self = nullptr;
|
||||
}
|
||||
|
||||
QStringList PluginManager::loadedPlugins() const
|
||||
{
|
||||
return m_plugins.keys();
|
||||
}
|
||||
|
||||
QStringList PluginManager::availablePlugins() const
|
||||
{
|
||||
QStringList ret = m_staticPlugins.keys();
|
||||
|
||||
const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(s_pluginDirectory);
|
||||
for (const KPluginMetaData &metadata : plugins) {
|
||||
ret.append(metadata.pluginId());
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PluginManager::loadPlugin(const QString &pluginId)
|
||||
{
|
||||
if (m_plugins.contains(pluginId)) {
|
||||
qCDebug(KWIN_CORE) << "Plugin with id" << pluginId << "is already loaded";
|
||||
return false;
|
||||
}
|
||||
return loadStaticPlugin(pluginId) || loadDynamicPlugin(pluginId);
|
||||
}
|
||||
|
||||
bool PluginManager::loadStaticPlugin(const QString &pluginId)
|
||||
{
|
||||
auto staticIt = m_staticPlugins.find(pluginId);
|
||||
if (staticIt == m_staticPlugins.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QScopedPointer<PluginFactory> factory(qobject_cast<PluginFactory *>(staticIt->instance()));
|
||||
if (!factory) {
|
||||
qCWarning(KWIN_CORE) << "Failed to get plugin factory for" << pluginId;
|
||||
return false;
|
||||
}
|
||||
|
||||
return instantiatePlugin(pluginId, factory.data());
|
||||
}
|
||||
|
||||
bool PluginManager::loadDynamicPlugin(const QString &pluginId)
|
||||
{
|
||||
const auto offers = KPluginLoader::findPluginsById(s_pluginDirectory, pluginId);
|
||||
for (const KPluginMetaData &metadata : offers) {
|
||||
if (loadDynamicPlugin(metadata)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PluginManager::loadDynamicPlugin(const KPluginMetaData &metadata)
|
||||
{
|
||||
if (!metadata.isValid()) {
|
||||
qCDebug(KWIN_CORE) << "PluginManager::loadPlugin needs a valid plugin metadata";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString pluginId = metadata.pluginId();
|
||||
KPluginLoader pluginLoader(metadata.fileName());
|
||||
if (pluginLoader.pluginVersion() != KWIN_PLUGIN_API_VERSION) {
|
||||
qCWarning(KWIN_CORE) << pluginId << "has mismatching plugin version";
|
||||
return false;
|
||||
}
|
||||
|
||||
QScopedPointer<PluginFactory> factory(qobject_cast<PluginFactory *>(pluginLoader.instance()));
|
||||
if (!factory) {
|
||||
qCWarning(KWIN_CORE) << "Failed to get plugin factory for" << pluginId;
|
||||
return false;
|
||||
}
|
||||
|
||||
return instantiatePlugin(pluginId, factory.data());
|
||||
}
|
||||
|
||||
bool PluginManager::instantiatePlugin(const QString &pluginId, PluginFactory *factory)
|
||||
{
|
||||
Plugin *plugin = factory->create();
|
||||
if (!plugin) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_plugins.insert(pluginId, plugin);
|
||||
plugin->setParent(this);
|
||||
|
||||
connect(plugin, &QObject::destroyed, this, [this, pluginId]() {
|
||||
m_plugins.remove(pluginId);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PluginManager::unloadPlugin(const QString &pluginId)
|
||||
{
|
||||
Plugin *plugin = m_plugins.take(pluginId);
|
||||
if (!plugin) {
|
||||
qCWarning(KWIN_CORE) << "No plugin with the specified id:" << pluginId;
|
||||
}
|
||||
delete plugin;
|
||||
}
|
||||
|
||||
} // namespace KWin
|
51
pluginmanager.h
Normal file
51
pluginmanager.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "kwinglobals.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QStaticPlugin>
|
||||
|
||||
#include <KPluginMetaData>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class Plugin;
|
||||
class PluginFactory;
|
||||
|
||||
/**
|
||||
* The PluginManager class loads and unloads binary compositor extensions.
|
||||
*/
|
||||
class KWIN_EXPORT PluginManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
~PluginManager() override;
|
||||
|
||||
QStringList loadedPlugins() const;
|
||||
QStringList availablePlugins() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
bool loadPlugin(const QString &pluginId);
|
||||
void unloadPlugin(const QString &pluginId);
|
||||
|
||||
private:
|
||||
bool loadStaticPlugin(const QString &pluginId);
|
||||
bool loadDynamicPlugin(const KPluginMetaData &metadata);
|
||||
bool loadDynamicPlugin(const QString &pluginId);
|
||||
bool instantiatePlugin(const QString &pluginId, PluginFactory *factory);
|
||||
|
||||
QHash<QString, Plugin *> m_plugins;
|
||||
QHash<QString, QStaticPlugin> m_staticPlugins;
|
||||
KWIN_SINGLETON(PluginManager)
|
||||
};
|
||||
|
||||
} // namespace KWin
|
|
@ -9,3 +9,6 @@ add_subdirectory(kpackage)
|
|||
if (KWIN_BUILD_DECORATIONS)
|
||||
add_subdirectory(kdecorations)
|
||||
endif()
|
||||
if (PipeWire_FOUND)
|
||||
add_subdirectory(screencast)
|
||||
endif()
|
||||
|
|
18
plugins/screencast/CMakeLists.txt
Normal file
18
plugins/screencast/CMakeLists.txt
Normal file
|
@ -0,0 +1,18 @@
|
|||
set(screencast_SOURCES
|
||||
eglnativefence.cpp
|
||||
main.cpp
|
||||
pipewirecore.cpp
|
||||
pipewirestream.cpp
|
||||
screencastmanager.cpp
|
||||
)
|
||||
|
||||
ecm_qt_declare_logging_category(screencast_SOURCES
|
||||
HEADER kwinscreencast_logging.h
|
||||
IDENTIFIER KWIN_SCREENCAST
|
||||
CATEGORY_NAME kwin_screencast
|
||||
DEFAULT_SEVERITY Warning
|
||||
)
|
||||
|
||||
add_library(KWinScreencastPlugin OBJECT ${screencast_SOURCES})
|
||||
target_compile_definitions(KWinScreencastPlugin PRIVATE QT_STATICPLUGIN)
|
||||
target_link_libraries(KWinScreencastPlugin kwin PkgConfig::PipeWire)
|
46
plugins/screencast/main.cpp
Normal file
46
plugins/screencast/main.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "screencastmanager.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <KPluginFactory>
|
||||
|
||||
using namespace KWin;
|
||||
|
||||
class KWIN_EXPORT ScreencastManagerFactory : public PluginFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID PluginFactory_iid FILE "metadata.json")
|
||||
Q_INTERFACES(KWin::PluginFactory)
|
||||
|
||||
public:
|
||||
explicit ScreencastManagerFactory(QObject *parent = nullptr);
|
||||
|
||||
Plugin *create() const override;
|
||||
};
|
||||
|
||||
ScreencastManagerFactory::ScreencastManagerFactory(QObject *parent)
|
||||
: PluginFactory(parent)
|
||||
{
|
||||
}
|
||||
|
||||
Plugin *ScreencastManagerFactory::create() const
|
||||
{
|
||||
switch (kwinApp()->operationMode()) {
|
||||
case Application::OperationModeX11:
|
||||
return nullptr;
|
||||
case Application::OperationModeXwayland:
|
||||
case Application::OperationModeWaylandOnly:
|
||||
return new ScreencastManager();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
K_EXPORT_PLUGIN_VERSION(KWIN_PLUGIN_API_VERSION)
|
||||
|
||||
#include "main.moc"
|
6
plugins/screencast/metadata.json
Normal file
6
plugins/screencast/metadata.json
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"KPlugin": {
|
||||
"EnabledByDefault": true,
|
||||
"Id": "kwin5_plugin_screencast"
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ namespace KWin
|
|||
{
|
||||
|
||||
ScreencastManager::ScreencastManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
: Plugin(parent)
|
||||
, m_screencast(waylandServer()->display()->createScreencastV1Interface(this))
|
||||
{
|
||||
connect(m_screencast, &KWaylandServer::ScreencastV1Interface::windowScreencastRequested,
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
#include <KWaylandServer/screencast_v1_interface.h>
|
||||
|
||||
namespace KWin
|
||||
|
@ -15,7 +17,7 @@ namespace KWin
|
|||
|
||||
class PipeWireStream;
|
||||
|
||||
class ScreencastManager : public QObject
|
||||
class ScreencastManager : public Plugin
|
||||
{
|
||||
Q_OBJECT
|
||||
|
|
@ -33,6 +33,7 @@
|
|||
#include "netinfo.h"
|
||||
#include "outline.h"
|
||||
#include "placement.h"
|
||||
#include "pluginmanager.h"
|
||||
#include "rules.h"
|
||||
#include "screenedge.h"
|
||||
#include "screens.h"
|
||||
|
@ -1669,6 +1670,20 @@ QString Workspace::supportInformation() const
|
|||
support.append(static_cast<EffectsHandlerImpl*>(effects)->supportInformation(effect));
|
||||
support.append(QStringLiteral("\n"));
|
||||
}
|
||||
support.append(QLatin1String("\nLoaded Plugins:\n"));
|
||||
support.append(QLatin1String("---------------\n"));
|
||||
QStringList loadedPlugins = PluginManager::self()->loadedPlugins();
|
||||
loadedPlugins.sort();
|
||||
for (const QString &plugin : qAsConst(loadedPlugins)) {
|
||||
support.append(plugin + QLatin1Char('\n'));
|
||||
}
|
||||
support.append(QLatin1String("\nAvailable Plugins:\n"));
|
||||
support.append(QLatin1String("------------------\n"));
|
||||
QStringList availablePlugins = PluginManager::self()->availablePlugins();
|
||||
availablePlugins.sort();
|
||||
for (const QString &plugin : qAsConst(availablePlugins)) {
|
||||
support.append(plugin + QLatin1Char('\n'));
|
||||
}
|
||||
} else {
|
||||
support.append(QStringLiteral("Compositing is not active\n"));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue