diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt
--- a/src/client/CMakeLists.txt
+++ b/src/client/CMakeLists.txt
@@ -61,6 +61,7 @@
xdgshell_v6.cpp
xdgshell_stable.cpp
xdgoutput.cpp
+ screencasting.cpp
../compat/wayland-xdg-shell-v5-protocol.c
)
@@ -202,6 +203,11 @@
BASENAME keystate
)
+ecm_add_qtwayland_client_protocol(CLIENT_LIB_SRCS
+ PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/screencast.xml
+ BASENAME org-kde-kwin-screencast-unstable-v1
+)
+
set(CLIENT_GENERATED_FILES
${CMAKE_CURRENT_BINARY_DIR}/wayland-fullscreen-shell-client-protocol.h
${CMAKE_CURRENT_BINARY_DIR}/wayland-output-management-client-protocol.h
@@ -289,6 +295,7 @@
keyboard.h
keystate.h
remote_access.h
+ screencasting.h
outputconfiguration.h
outputmanagement.h
outputdevice.h
diff --git a/src/client/protocols/screencast.xml b/src/client/protocols/screencast.xml
new file mode 100644
--- /dev/null
+++ b/src/client/protocols/screencast.xml
@@ -0,0 +1,56 @@
+
+
+
+
+ SPDX-License-Identifier: LGPL-2.1-or-later
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/client/screencasting.h b/src/client/screencasting.h
new file mode 100644
--- /dev/null
+++ b/src/client/screencasting.h
@@ -0,0 +1,78 @@
+/*
+ SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#pragma once
+
+#include
+#include
+#include
+#include
+
+#include
+
+struct org_kde_kwin_remote_access_manager;
+struct org_kde_kwin_remote_buffer;
+struct wl_output;
+
+namespace KWayland
+{
+namespace Client
+{
+class EventQueue;
+class VideoStreamingPrivate;
+class ScreencastingSourcePrivate;
+
+class KWAYLANDCLIENT_EXPORT ScreencastingSource
+{
+ Q_GADGET
+public:
+ ScreencastingSource();
+ ScreencastingSource(const ScreencastingSource& other);
+ virtual ~ScreencastingSource();
+
+ quint32 sourceId() const;
+ QString iconName() const;
+ QString description() const;
+ bool isOutput() const;
+ QRect geometry() const;
+
+ bool operator!=(const ScreencastingSource& other) const;
+
+protected:
+ ScreencastingSource(quint32 sourceId, const QString &description, const QString &iconName, bool isOutput, const QRect &geometry);
+
+private:
+ friend class VideoStreamingPrivate;
+ QSharedPointer d;
+};
+
+class KWAYLANDCLIENT_EXPORT Screencasting : public QObject
+{
+ Q_OBJECT
+public:
+ explicit Screencasting(QObject *parent = nullptr);
+ ~Screencasting() override;
+
+ QVector sources() const;
+
+ void create(const ScreencastingSource& source);
+ void close(quint32 nodeid);
+
+Q_SIGNALS:
+ void initialized();
+ void created(const ScreencastingSource& source, quint32 nodeid);
+ void failed(const ScreencastingSource& source, const QString &error);
+ void closed(quint32 nodeid);
+ void sourcesChanged();
+
+private:
+ QScopedPointer d;
+};
+
+}
+}
+
+Q_DECLARE_METATYPE(KWayland::Client::ScreencastingSource);
diff --git a/src/client/screencasting.cpp b/src/client/screencasting.cpp
new file mode 100644
--- /dev/null
+++ b/src/client/screencasting.cpp
@@ -0,0 +1,143 @@
+/*
+ SPDX-FileCopyrightText: 2020 Aleix Pol Gonzalez
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "screencasting.h"
+#include "qwayland-org-kde-kwin-screencast-unstable-v1.h"
+#include
+
+using namespace KWayland::Client;
+
+class KWayland::Client::ScreencastingSourcePrivate
+{
+public:
+ ScreencastingSourcePrivate(quint32 sourceId, const QString &description, const QString &iconName, bool isOutput, const QRect &geometry)
+ : sourceId(sourceId)
+ , description(description)
+ , iconName(iconName)
+ , isOutput(isOutput)
+ , geometry(geometry)
+ {}
+
+ const quint32 sourceId;
+ const QString description;
+ const QString iconName;
+ const bool isOutput;
+ const QRect geometry;
+};
+
+ScreencastingSource::ScreencastingSource()
+ : d(new ScreencastingSourcePrivate(0, {}, {}, false, {}))
+{}
+
+ScreencastingSource::ScreencastingSource(quint32 sourceId, const QString &description, const QString &iconName, bool isOutput, const QRect &geometry)
+ : d(new ScreencastingSourcePrivate(sourceId, description, iconName, isOutput, geometry))
+{}
+
+ScreencastingSource::ScreencastingSource(const ScreencastingSource& other)
+ : d(other.d)
+{}
+
+ScreencastingSource::~ScreencastingSource() = default;
+
+quint32 ScreencastingSource::sourceId() const
+{
+ return d->sourceId;
+}
+
+QString ScreencastingSource::description() const
+{
+ return d->description;
+}
+
+QString ScreencastingSource::iconName() const
+{
+ return d->iconName;
+}
+
+bool ScreencastingSource::isOutput() const
+{
+ return d->isOutput;
+}
+
+QRect ScreencastingSource::geometry() const
+{
+ return d->geometry;
+}
+
+bool ScreencastingSource::operator!=(const ScreencastingSource& other) const
+{
+ return d != other.d;
+}
+
+class KWayland::Client::VideoStreamingPrivate : public QtWayland::org_kde_kwin_screencast_unstable_v1
+{
+public:
+ VideoStreamingPrivate(Screencasting *q)
+ : q(q)
+ {}
+
+ void org_kde_kwin_screencast_unstable_v1_addSource(uint32_t sourceId, const QString & description, const QString & iconName, uint32_t type,
+ int32_t geometryX, int32_t geometryY, int32_t geometryWidth, int32_t geometryHeight) override
+ {
+ m_sources << ScreencastingSource(sourceId, description, iconName, type==SourceType_monitor,
+ {geometryX, geometryY, geometryWidth, geometryHeight});
+ if (m_done)
+ Q_EMIT q->sourcesChanged();
+ }
+ void org_kde_kwin_screencast_unstable_v1_removeSource(uint32_t sourceId) override {
+ auto it = std::find_if(m_sources.begin(), m_sources.end(), [sourceId] (const ScreencastingSource &source) {
+ return source.sourceId() == sourceId;
+ });
+ Q_ASSERT(it != m_sources.end());
+ m_sources.erase(it);
+ Q_EMIT q->sourcesChanged();
+ }
+
+ void org_kde_kwin_screencast_unstable_v1_done() override {
+ m_done = true;
+ Q_EMIT q->initialized();
+ Q_EMIT q->sourcesChanged();
+ }
+
+ void org_kde_kwin_screencast_unstable_v1_created(uint32_t nodeid, uint32_t sourceId) override {
+ Q_EMIT q->created(sourceById(sourceId), nodeid);
+ }
+
+ ScreencastingSource sourceById(quint32 sourceId) {
+ auto it = std::find_if(m_sources.begin(), m_sources.end(), [sourceId] (const ScreencastingSource &source) {
+ return source.sourceId() == sourceId;
+ });
+ if (it == m_sources.constEnd())
+ return {};
+ return *it;
+ }
+
+ bool m_done = false;
+ QVector m_sources;
+ Screencasting *const q;
+};
+
+Screencasting::Screencasting(QObject* parent)
+ : QObject(parent)
+ , d(new VideoStreamingPrivate(this))
+{}
+
+Screencasting::~Screencasting() = default;
+
+void Screencasting::close(quint32 nodeid)
+{
+ d->close(nodeid);
+}
+
+void Screencasting::create(const ScreencastingSource& source)
+{
+ d->create(source.sourceId());
+}
+
+QVector Screencasting::sources() const
+{
+ return d->m_sources;
+}
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt
--- a/src/server/CMakeLists.txt
+++ b/src/server/CMakeLists.txt
@@ -64,6 +64,7 @@
xdgshell_v5_interface.cpp
xdgshell_v5_interface.cpp
xdgshell_v6_interface.cpp
+ screencasting_interface.cpp
)
ecm_qt_declare_logging_category(SERVER_LIB_SRCS
@@ -234,6 +235,11 @@
BASENAME tablet-unstable-v2
)
+ecm_add_qtwayland_server_protocol(SERVER_LIB_SRCS
+ PROTOCOL PROTOCOL ${KWayland_SOURCE_DIR}/src/client/protocols/screencast.xml
+ BASENAME org-kde-kwin-screencast-unstable-v1
+)
+
set(SERVER_GENERATED_SRCS
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-client-protocol.h
${CMAKE_CURRENT_BINARY_DIR}/wayland-blur-server-protocol.h
@@ -293,6 +299,8 @@
${CMAKE_CURRENT_BINARY_DIR}/wayland-xdg-shell-v6-server-protocol.h
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-tablet-unstable-v2.h
${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-tablet-unstable-v2.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-screecast-unstable-v1.h
+ ${CMAKE_CURRENT_BINARY_DIR}/qwayland-server-screecast-unstable-v1.cpp
)
set_source_files_properties(${SERVER_GENERATED_SRCS} PROPERTIES SKIP_AUTOMOC ON)
@@ -369,6 +377,7 @@
relativepointer_interface.h
remote_access_interface.h
resource.h
+ screencasting_interface.h
seat_interface.h
server_decoration_interface.h
server_decoration_palette_interface.h
diff --git a/src/server/display.h b/src/server/display.h
--- a/src/server/display.h
+++ b/src/server/display.h
@@ -80,6 +80,7 @@
class KeyStateInterface;
class LinuxDmabufUnstableV1Interface;
class TabletManagerInterface;
+class ScreencastingInterface;
/**
* @brief Class holding the Wayland server display loop.
@@ -318,6 +319,13 @@
*/
TabletManagerInterface *createTabletManagerInterface(QObject *parent = nullptr);
+ /**
+ * Creates an interface to request video feeds of different compositor resources
+ *
+ * @since 5.70
+ */
+ ScreencastingInterface *createScreencastingInterface(QObject *parent = nullptr);
+
/**
* Gets the ClientConnection for the given @p client.
* If there is no ClientConnection yet for the given @p client, it will be created.
diff --git a/src/server/display.cpp b/src/server/display.cpp
--- a/src/server/display.cpp
+++ b/src/server/display.cpp
@@ -31,6 +31,7 @@
#include "relativepointer_interface_p.h"
#include "remote_access_interface.h"
#include "seat_interface.h"
+#include "screencasting_interface.h"
#include "server_decoration_interface.h"
#include "server_decoration_palette_interface.h"
#include "shadow_interface.h"
@@ -378,6 +379,13 @@
return d;
}
+ScreencastingInterface *Display::createScreencastingInterface(QObject *parent)
+{
+ auto s = new ScreencastingInterface(this, parent);
+ connect(this, &Display::aboutToTerminate, s, [s] { delete s; });
+ return s;
+}
+
TextInputManagerInterface *Display::createTextInputManager(const TextInputInterfaceVersion &version, QObject *parent)
{
TextInputManagerInterface *t = nullptr;