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
+ videostreaming.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
+ videostreaming.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,51 @@
+
+
+
+
+ SPDX-License-Identifier: LGPL-2.1-or-later
+ ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/client/videostreaming.h b/src/client/videostreaming.h
new file mode 100644
--- /dev/null
+++ b/src/client/videostreaming.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 VideoStreamSourcePrivate;
+
+class KWAYLANDCLIENT_EXPORT VideoStreamSource
+{
+ Q_GADGET
+public:
+ VideoStreamSource();
+ VideoStreamSource(const VideoStreamSource& other);
+ virtual ~VideoStreamSource();
+
+ quint32 sourceId() const;
+ QString iconName() const;
+ QString description() const;
+ bool isOutput() const;
+ QRect geometry() const;
+
+ bool operator!=(const VideoStreamSource& other) const;
+
+protected:
+ VideoStreamSource(quint32 sourceId, const QString &description, const QString &iconName, bool isOutput, const QRect &geometry);
+
+private:
+ friend class VideoStreamingPrivate;
+ QSharedPointer d;
+};
+
+class KWAYLANDCLIENT_EXPORT VideoStreaming : public QObject
+{
+ Q_OBJECT
+public:
+ explicit VideoStreaming(QObject *parent = nullptr);
+ ~VideoStreaming() override;
+
+ QVector sources() const;
+
+ void create(const VideoStreamSource& source);
+ void close(quint32 nodeid);
+
+Q_SIGNALS:
+ void initialized();
+ void created(const VideoStreamSource& source, quint32 nodeid);
+ void failed(const VideoStreamSource& source, const QString &error);
+ void closed(quint32 nodeid);
+ void sourcesChanged();
+
+private:
+ QScopedPointer d;
+};
+
+}
+}
+
+Q_DECLARE_METATYPE(KWayland::Client::VideoStreamSource);
diff --git a/src/client/videostreaming.cpp b/src/client/videostreaming.cpp
new file mode 100644
--- /dev/null
+++ b/src/client/videostreaming.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 "videostreaming.h"
+#include "qwayland-org-kde-kwin-screencast-unstable-v1.h"
+#include
+
+using namespace KWayland::Client;
+
+class KWayland::Client::VideoStreamSourcePrivate
+{
+public:
+ VideoStreamSourcePrivate(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;
+};
+
+VideoStreamSource::VideoStreamSource()
+ : d(new VideoStreamSourcePrivate(0, {}, {}, false, {}))
+{}
+
+VideoStreamSource::VideoStreamSource(quint32 sourceId, const QString &description, const QString &iconName, bool isOutput, const QRect &geometry)
+ : d(new VideoStreamSourcePrivate(sourceId, description, iconName, isOutput, geometry))
+{}
+
+VideoStreamSource::VideoStreamSource(const VideoStreamSource& other)
+ : d(other.d)
+{}
+
+VideoStreamSource::~VideoStreamSource() = default;
+
+quint32 VideoStreamSource::sourceId() const
+{
+ return d->sourceId;
+}
+
+QString VideoStreamSource::description() const
+{
+ return d->description;
+}
+
+QString VideoStreamSource::iconName() const
+{
+ return d->iconName;
+}
+
+bool VideoStreamSource::isOutput() const
+{
+ return d->isOutput;
+}
+
+QRect VideoStreamSource::geometry() const
+{
+ return d->geometry;
+}
+
+bool VideoStreamSource::operator!=(const VideoStreamSource& other) const
+{
+ return d != other.d;
+}
+
+class KWayland::Client::VideoStreamingPrivate : public QtWayland::org_kde_kwin_screencast
+{
+public:
+ VideoStreamingPrivate(VideoStreaming *q)
+ : q(q)
+ {}
+
+ void org_kde_kwin_screencast_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 << VideoStreamSource(sourceId, description, iconName, type==SourceType_output,
+ {geometryX, geometryY, geometryWidth, geometryHeight});
+ if (m_done)
+ Q_EMIT q->sourcesChanged();
+ }
+ void org_kde_kwin_screencast_removeSource(uint32_t sourceId) override {
+ auto it = std::find_if(m_sources.begin(), m_sources.end(), [sourceId] (const VideoStreamSource &source) {
+ return source.sourceId() == sourceId;
+ });
+ Q_ASSERT(it != m_sources.end());
+ m_sources.erase(it);
+ Q_EMIT q->sourcesChanged();
+ }
+
+ void org_kde_kwin_screencast_done() override {
+ m_done = true;
+ Q_EMIT q->initialized();
+ Q_EMIT q->sourcesChanged();
+ }
+
+ void org_kde_kwin_screencast_created(int32_t nodeid, uint32_t sourceId) override {
+ Q_EMIT q->created(sourceById(sourceId), nodeid);
+ }
+
+ VideoStreamSource sourceById(quint32 sourceId) {
+ auto it = std::find_if(m_sources.begin(), m_sources.end(), [sourceId] (const VideoStreamSource &source) {
+ return source.sourceId() == sourceId;
+ });
+ if (it == m_sources.constEnd())
+ return {};
+ return *it;
+ }
+
+ bool m_done = false;
+ QVector m_sources;
+ VideoStreaming *const q;
+};
+
+VideoStreaming::VideoStreaming(QObject* parent)
+ : QObject(parent)
+ , d(new VideoStreamingPrivate(this))
+{}
+
+VideoStreaming::~VideoStreaming() = default;
+
+void VideoStreaming::close(quint32 nodeid)
+{
+ d->close(nodeid);
+}
+
+void VideoStreaming::create(const VideoStreamSource& source)
+{
+ d->create(source.sourceId());
+}
+
+QVector VideoStreaming::sources() const
+{
+ return d->m_sources;
+}