Changeset View
Changeset View
Standalone View
Standalone View
src/server/screencasting_interface.cpp
- This file was added.
1 | /* | ||||
---|---|---|---|---|---|
2 | SPDX-FileCopyrightText: 2016 Oleg Chernovskiy <kanedias@xaker.ru> | ||||
3 | | ||||
4 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL | ||||
5 | */ | ||||
6 | | ||||
7 | #include "screencasting_interface.h" | ||||
8 | #include "display.h" | ||||
9 | #include <QDebug> | ||||
10 | | ||||
11 | #include "qwayland-server-org-kde-kwin-screencast-unstable-v1.h" | ||||
12 | | ||||
13 | using namespace KWayland::Server; | ||||
14 | | ||||
15 | static int s_version = 1; | ||||
16 | | ||||
17 | class KWayland::Server::ScreencastingSourcePrivate | ||||
18 | { | ||||
19 | public: | ||||
20 | ScreencastingSourcePrivate(const QString &description, const QString &iconName, bool isOutput, const QRect &geometry, std::function<void(const ScreencastingSource &,wl_resource *r)> call) | ||||
21 | : sourceId(0) | ||||
22 | , description(description) | ||||
23 | , iconName(iconName) | ||||
24 | , isOutput(isOutput) | ||||
25 | , geometry(geometry) | ||||
26 | , call(call) | ||||
27 | {} | ||||
28 | | ||||
29 | quint32 sourceId; | ||||
30 | const QString description; | ||||
31 | const QString iconName; | ||||
32 | const bool isOutput; | ||||
33 | const QRect geometry; | ||||
34 | const std::function<void(const ScreencastingSource &,wl_resource *r)> call; | ||||
35 | }; | ||||
36 | | ||||
37 | ScreencastingSource::ScreencastingSource() | ||||
38 | : d(new ScreencastingSourcePrivate({}, {}, false, {}, [] (const ScreencastingSource &, wl_resource *) {})) | ||||
39 | {} | ||||
40 | | ||||
41 | ScreencastingSource::ScreencastingSource(const QString &description, const QString &iconName, bool isOutput, const QRect &geometry, std::function<void(const ScreencastingSource &,wl_resource *r)> call) | ||||
42 | : d(new ScreencastingSourcePrivate(description, iconName, isOutput, geometry, call)) | ||||
43 | {} | ||||
44 | | ||||
45 | ScreencastingSource::ScreencastingSource(const ScreencastingSource& other) | ||||
46 | : d(other.d) | ||||
47 | {} | ||||
48 | | ||||
49 | ScreencastingSource::~ScreencastingSource() = default; | ||||
50 | | ||||
51 | quint32 ScreencastingSource::sourceId() const | ||||
52 | { | ||||
53 | return d->sourceId; | ||||
54 | } | ||||
55 | | ||||
56 | QString ScreencastingSource::description() const | ||||
57 | { | ||||
58 | return d->description; | ||||
59 | } | ||||
60 | | ||||
61 | QString ScreencastingSource::iconName() const | ||||
62 | { | ||||
63 | return d->iconName; | ||||
64 | } | ||||
65 | | ||||
66 | bool ScreencastingSource::isOutput() const | ||||
67 | { | ||||
68 | return d->isOutput; | ||||
69 | } | ||||
70 | | ||||
71 | QRect ScreencastingSource::geometry() const | ||||
72 | { | ||||
73 | return d->geometry; | ||||
74 | } | ||||
75 | | ||||
76 | bool ScreencastingSource::operator!=(const ScreencastingSource &other) const | ||||
77 | { | ||||
78 | return d != other.d; | ||||
79 | } | ||||
80 | | ||||
81 | void KWayland::Server::ScreencastingSource::call(wl_resource* r) | ||||
82 | { | ||||
83 | d->call(*this, r); | ||||
84 | } | ||||
85 | | ||||
86 | class KWayland::Server::ScreencastingInterfacePrivate : public QtWaylandServer::org_kde_kwin_screencast_unstable_v1 | ||||
87 | { | ||||
88 | public: | ||||
89 | ScreencastingInterfacePrivate(Display *display, ScreencastingInterface* q) | ||||
90 | : QtWaylandServer::org_kde_kwin_screencast_unstable_v1(*display, s_version) | ||||
91 | , q(q) | ||||
92 | { | ||||
93 | } | ||||
94 | | ||||
95 | void org_kde_kwin_screencast_unstable_v1_bind_resource(Resource *resource) override { | ||||
96 | for (auto source : qAsConst(m_sources)) { | ||||
97 | sendSource(resource, source); | ||||
98 | } | ||||
99 | send_done(resource->handle); | ||||
100 | } | ||||
101 | | ||||
102 | void org_kde_kwin_screencast_unstable_v1_destroy_resource(Resource *resource) override { | ||||
103 | const auto nodes = m_activeStreams.take(resource->handle); | ||||
104 | for (quint32 node : nodes) { | ||||
105 | Q_EMIT q->stop(node); | ||||
106 | } | ||||
107 | } | ||||
108 | | ||||
109 | void org_kde_kwin_screencast_unstable_v1_create(Resource *resource, uint32_t sourceId) override { | ||||
110 | auto it = std::find_if(m_sources.begin(), m_sources.end(), [sourceId] (const ScreencastingSource &source) { return source.sourceId() == sourceId; }); | ||||
111 | if (it == m_sources.end()) { | ||||
112 | q->sendFailed(resource->handle, sourceId, QObject::tr("Source %1 does not exist").arg(sourceId)); | ||||
113 | return; | ||||
114 | } | ||||
115 | | ||||
116 | it->call(resource->handle); | ||||
117 | } | ||||
118 | | ||||
119 | void org_kde_kwin_screencast_unstable_v1_close(Resource *, uint32_t nodeId) override { | ||||
120 | Q_EMIT q->stop(nodeId); | ||||
121 | } | ||||
122 | | ||||
123 | void sendSource(Resource* resource, const ScreencastingSource &source) { | ||||
124 | const QRect geometry = source.geometry(); | ||||
125 | send_addSource(resource->handle, source.sourceId(), source.description(), source.iconName(), source.isOutput(), geometry.x(), geometry.y(), geometry.width(), geometry.height()); | ||||
126 | } | ||||
127 | | ||||
128 | void addSource(ScreencastingSource &source) { | ||||
129 | static quint32 id = 0; | ||||
130 | auto f = [] (const ScreencastingSource &source) { return source.sourceId() == id; }; | ||||
131 | while (id == 0 || std::find_if(m_sources.cbegin(), m_sources.cend(), f) != m_sources.cend()) { | ||||
132 | ++id; | ||||
133 | } | ||||
134 | source.d->sourceId = id; | ||||
135 | | ||||
136 | m_sources << source; | ||||
137 | } | ||||
138 | | ||||
139 | QHash<wl_resource*, QVector<quint32>> m_activeStreams; | ||||
140 | QVector<ScreencastingSource> m_sources; | ||||
141 | ScreencastingInterface *const q; | ||||
142 | }; | ||||
143 | | ||||
144 | ScreencastingInterface::ScreencastingInterface(Display *display, QObject *parent) | ||||
145 | : QObject(parent) | ||||
146 | , d(new ScreencastingInterfacePrivate(display, this)) | ||||
147 | { | ||||
148 | } | ||||
149 | | ||||
150 | ScreencastingInterface::~ScreencastingInterface() = default; | ||||
151 | | ||||
152 | void ScreencastingInterface::addSource(const ScreencastingSource &source) | ||||
153 | { | ||||
154 | Q_ASSERT(source.sourceId() == 0); | ||||
155 | | ||||
156 | ScreencastingSource ourSource = source; | ||||
157 | d->addSource(ourSource); | ||||
158 | | ||||
159 | for (auto r : d->resourceMap()) { | ||||
160 | d->sendSource(r, ourSource); | ||||
161 | } | ||||
162 | } | ||||
163 | | ||||
164 | void ScreencastingInterface::removeSource(const ScreencastingSource &sourceToRemove) | ||||
165 | { | ||||
166 | auto it = std::find_if(d->m_sources.begin(), d->m_sources.end(), [&sourceToRemove] (const ScreencastingSource &source) { return source.sourceId() == sourceToRemove.sourceId(); }); | ||||
167 | if (it == d->m_sources.end()) { | ||||
168 | return; | ||||
169 | } | ||||
170 | | ||||
171 | d->m_sources.erase(it); | ||||
172 | | ||||
173 | for (auto r : d->resourceMap()) { | ||||
174 | d->send_removeSource(r->handle, sourceToRemove.sourceId()); | ||||
175 | } | ||||
176 | } | ||||
177 | | ||||
178 | void ScreencastingInterface::sendCreated(wl_resource *resource, quint32 nodeid, quint32 sourceid) | ||||
179 | { | ||||
180 | d->m_activeStreams[resource].append(nodeid); | ||||
181 | d->send_created(resource, nodeid, sourceid); | ||||
182 | } | ||||
183 | | ||||
184 | void ScreencastingInterface::sendFailed(wl_resource* resource, quint32 sourceid, const QString& error) | ||||
185 | { | ||||
186 | d->send_failed(resource, sourceid, error); | ||||
187 | } | ||||
188 | | ||||
189 | void KWayland::Server::ScreencastingInterface::sendClosed(wl_resource* resource, quint32 nodeid) | ||||
190 | { | ||||
191 | d->m_activeStreams[resource].removeAll(nodeid); | ||||
192 | d->send_closed(resource, nodeid); | ||||
193 | } |