Directory: | ./ |
---|---|
File: | server/primary_selection.cpp |
Date: | 2024-01-22 17:25:27 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 160 | 172 | 93.0% |
Branches: | 38 | 74 | 51.4% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | SPDX-FileCopyrightText: 2020 Adrien Faveraux <af@brain-networks.fr> | ||
3 | SPDX-FileCopyrightText: 2021 Francesco Sorrentino <francesco.sorr@gmail.com> | ||
4 | |||
5 | SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only | ||
6 | */ | ||
7 | #include "primary_selection_p.h" | ||
8 | |||
9 | #include "client.h" | ||
10 | #include "data_control_v1_p.h" | ||
11 | #include "display.h" | ||
12 | #include "seat_p.h" | ||
13 | #include "selection_p.h" | ||
14 | |||
15 | namespace Wrapland::Server | ||
16 | { | ||
17 | |||
18 | const struct zwp_primary_selection_device_manager_v1_interface | ||
19 | primary_selection_device_manager::Private::s_interface | ||
20 | = { | ||
21 | cb<create_source>, | ||
22 | cb<get_device>, | ||
23 | resourceDestroyCallback, | ||
24 | }; | ||
25 | |||
26 | 49 | primary_selection_device_manager::Private::Private(Display* display, | |
27 | primary_selection_device_manager* q_ptr) | ||
28 | 49 | : device_manager<primary_selection_device_manager_global>( | |
29 | 49 | q_ptr, | |
30 | 49 | display, | |
31 | &zwp_primary_selection_device_manager_v1_interface, | ||
32 | &s_interface) | ||
33 | 49 | { | |
34 |
1/2✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
|
49 | create(); |
35 | 49 | } | |
36 | |||
37 | 49 | primary_selection_device_manager::primary_selection_device_manager(Display* display) | |
38 |
2/4✓ Branch 0 taken 49 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 49 times.
|
49 | : d_ptr(new Private(display, this)) |
39 | 49 | { | |
40 | 49 | } | |
41 | |||
42 | 98 | primary_selection_device_manager::~primary_selection_device_manager() = default; | |
43 | |||
44 | 11 | void primary_selection_device_manager::create_source(Client* client, uint32_t version, uint32_t id) | |
45 | { | ||
46 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | auto src_res = new primary_selection_source_res(client, version, id); |
47 | // TODO(romangg): Catch oom. | ||
48 | |||
49 | 11 | Q_EMIT source_created(src_res->src()); | |
50 | 11 | } | |
51 | |||
52 | 14 | void primary_selection_device_manager::get_device(Client* client, | |
53 | uint32_t version, | ||
54 | uint32_t id, | ||
55 | Seat* seat) | ||
56 | { | ||
57 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | auto device = new primary_selection_device(client, version, id, seat); |
58 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (!device) { |
59 | ✗ | return; | |
60 | } | ||
61 | |||
62 | 7 | seat->d_ptr->primary_selection_devices.register_device(device); | |
63 | 7 | Q_EMIT device_created(device); | |
64 | 7 | } | |
65 | |||
66 | const struct zwp_primary_selection_device_v1_interface | ||
67 | primary_selection_device::Private::s_interface | ||
68 | = { | ||
69 | set_selection_callback, | ||
70 | destroyCallback, | ||
71 | }; | ||
72 | |||
73 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
14 | primary_selection_device::Private::Private(Client* client, |
74 | uint32_t version, | ||
75 | uint32_t id, | ||
76 | Seat* seat, | ||
77 | primary_selection_device* q_ptr) | ||
78 | 14 | : Wayland::Resource<primary_selection_device>(client, | |
79 | 7 | version, | |
80 | 7 | id, | |
81 | &zwp_primary_selection_device_v1_interface, | ||
82 | &s_interface, | ||
83 | 7 | q_ptr) | |
84 | 7 | , m_seat(seat) | |
85 | 7 | { | |
86 | 7 | } | |
87 | |||
88 | 14 | primary_selection_device::Private::~Private() = default; | |
89 | |||
90 | 11 | void primary_selection_device::Private::set_selection_callback(wl_client* /*wlClient*/, | |
91 | wl_resource* wlResource, | ||
92 | wl_resource* wlSource, | ||
93 | uint32_t /*id*/) | ||
94 | { | ||
95 | // TODO(unknown author): verify serial | ||
96 | 11 | auto handle = Resource::get_handle(wlResource); | |
97 | 11 | set_selection(handle, handle->d_ptr, wlSource); | |
98 | 11 | } | |
99 | |||
100 | 18 | void primary_selection_device::send_selection(Wrapland::Server::primary_selection_source* source) | |
101 | { | ||
102 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 5 times.
|
18 | if (!source) { |
103 | 5 | send_clear_selection(); | |
104 | 5 | return; | |
105 | } | ||
106 | |||
107 | 13 | auto offer = d_ptr->sendDataOffer(source); | |
108 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (!offer) { |
109 | ✗ | return; | |
110 | } | ||
111 | |||
112 | 13 | d_ptr->send<zwp_primary_selection_device_v1_send_selection>(offer->d_ptr->resource); | |
113 | 18 | } | |
114 | |||
115 | 5 | void primary_selection_device::send_clear_selection() | |
116 | { | ||
117 | 5 | d_ptr->send<zwp_primary_selection_device_v1_send_selection>(nullptr); | |
118 | 5 | } | |
119 | |||
120 | primary_selection_offer* | ||
121 | 13 | primary_selection_device::Private::sendDataOffer(primary_selection_source* source) | |
122 | { | ||
123 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (!source) { |
124 | // A data offer can only exist together with a source. | ||
125 | ✗ | return nullptr; | |
126 | } | ||
127 | |||
128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | auto offer = new primary_selection_offer(client->handle, version, source); |
129 | |||
130 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
13 | if (!offer->d_ptr->resource) { |
131 | ✗ | delete offer; | |
132 | ✗ | return nullptr; | |
133 | } | ||
134 | |||
135 | 13 | send<zwp_primary_selection_device_v1_send_data_offer>(offer->d_ptr->resource); | |
136 | 13 | offer->send_offer(); | |
137 | 13 | return offer; | |
138 | 13 | } | |
139 | |||
140 | 7 | primary_selection_device::primary_selection_device(Client* client, | |
141 | uint32_t version, | ||
142 | uint32_t id, | ||
143 | Seat* seat) | ||
144 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | : d_ptr(new Private(client, version, id, seat, this)) |
145 | 7 | { | |
146 | 7 | } | |
147 | |||
148 | 14 | primary_selection_device::~primary_selection_device() = default; | |
149 | |||
150 | 20 | primary_selection_source* primary_selection_device::selection() | |
151 | { | ||
152 | 20 | return d_ptr->selection; | |
153 | } | ||
154 | |||
155 | 14 | Client* primary_selection_device::client() const | |
156 | { | ||
157 | 14 | return d_ptr->client->handle; | |
158 | } | ||
159 | |||
160 | 2 | Seat* primary_selection_device::seat() const | |
161 | { | ||
162 | 2 | return d_ptr->m_seat; | |
163 | } | ||
164 | |||
165 | const struct zwp_primary_selection_offer_v1_interface primary_selection_offer::Private::s_interface | ||
166 | = { | ||
167 | receive_callback, | ||
168 | destroyCallback, | ||
169 | }; | ||
170 | |||
171 | 13 | primary_selection_offer::Private::Private(Client* client, | |
172 | uint32_t version, | ||
173 | primary_selection_source* source, | ||
174 | primary_selection_offer* q_ptr) | ||
175 | 26 | : Wayland::Resource<primary_selection_offer>(client, | |
176 | 13 | version, | |
177 | 0, | ||
178 | &zwp_primary_selection_offer_v1_interface, | ||
179 | &s_interface, | ||
180 | 13 | q_ptr) | |
181 | 13 | , source(source) | |
182 | 13 | { | |
183 | 13 | } | |
184 | |||
185 | 26 | primary_selection_offer::Private::~Private() = default; | |
186 | |||
187 | 1 | void primary_selection_offer::Private::receive_callback(wl_client* /*wlClient*/, | |
188 | wl_resource* wlResource, | ||
189 | char const* mimeType, | ||
190 | int32_t fd) | ||
191 | { | ||
192 | 1 | auto handle = Resource::get_handle(wlResource); | |
193 | 1 | receive_mime_type_offer(handle->d_ptr->source, mimeType, fd); | |
194 | 1 | } | |
195 | |||
196 | 13 | primary_selection_offer::primary_selection_offer(Client* client, | |
197 | uint32_t version, | ||
198 | primary_selection_source* source) | ||
199 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
13 | : d_ptr(new Private(client, version, source, this)) |
200 | 13 | { | |
201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | assert(source); |
202 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
|
26 | QObject::connect(source, |
203 | &primary_selection_source::mime_type_offered, | ||
204 | this, | ||
205 | 14 | [this](std::string const& mimeType) { | |
206 | 1 | d_ptr->send<zwp_primary_selection_offer_v1_send_offer>(mimeType.c_str()); | |
207 | 1 | }); | |
208 |
1/2✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
|
19 | QObject::connect(source, &primary_selection_source::resourceDestroyed, this, [this] { |
209 | 6 | d_ptr->source = nullptr; | |
210 | 6 | }); | |
211 | 13 | } | |
212 | |||
213 | 26 | primary_selection_offer::~primary_selection_offer() = default; | |
214 | |||
215 | 13 | void primary_selection_offer::send_offer() | |
216 | { | ||
217 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 12 times.
|
25 | for (auto const& mimeType : d_ptr->source->mime_types()) { |
218 |
1/2✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
|
12 | d_ptr->send<zwp_primary_selection_offer_v1_send_offer>(mimeType.c_str()); |
219 | } | ||
220 | 13 | } | |
221 | |||
222 | 13 | primary_selection_source::Private::Private(primary_selection_source* q_ptr) | |
223 | 13 | : q_ptr{q_ptr} | |
224 | { | ||
225 | 13 | } | |
226 | |||
227 | 13 | primary_selection_source::primary_selection_source() | |
228 |
2/4✓ Branch 0 taken 13 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 13 times.
|
13 | : d_ptr(new primary_selection_source::Private(this)) |
229 | 13 | { | |
230 | 13 | } | |
231 | |||
232 | 11 | primary_selection_source_res_impl::primary_selection_source_res_impl( | |
233 | Client* client, | ||
234 | uint32_t version, | ||
235 | uint32_t id, | ||
236 | primary_selection_source_res* q_ptr) | ||
237 | 22 | : Wayland::Resource<primary_selection_source_res>(client, | |
238 | 11 | version, | |
239 | 11 | id, | |
240 | &zwp_primary_selection_source_v1_interface, | ||
241 | &s_interface, | ||
242 | 11 | q_ptr) | |
243 | 11 | , q_ptr{q_ptr} | |
244 | 11 | { | |
245 | 11 | } | |
246 | |||
247 | const struct zwp_primary_selection_source_v1_interface | ||
248 | primary_selection_source_res_impl::s_interface | ||
249 | = { | ||
250 | offer_callback, | ||
251 | destroyCallback, | ||
252 | }; | ||
253 | |||
254 | 10 | void primary_selection_source_res_impl::offer_callback(wl_client* /*wlClient*/, | |
255 | wl_resource* wlResource, | ||
256 | char const* mimeType) | ||
257 | { | ||
258 | 10 | auto handle = Resource::get_handle(wlResource); | |
259 | 10 | offer_mime_type(handle->src_priv(), mimeType); | |
260 | 10 | } | |
261 | |||
262 | 11 | primary_selection_source_res::primary_selection_source_res(Client* client, | |
263 | uint32_t version, | ||
264 | uint32_t id) | ||
265 |
2/4✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
11 | : pub_src{new primary_selection_source} |
266 |
2/4✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
11 | , impl{new primary_selection_source_res_impl(client, version, id, this)} |
267 | 11 | { | |
268 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | QObject::connect(this, |
269 | &primary_selection_source_res::resourceDestroyed, | ||
270 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | src(), |
271 | 11 | &primary_selection_source::resourceDestroyed); | |
272 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | src_priv()->res = this; |
273 | 11 | } | |
274 | |||
275 | 8 | void primary_selection_source_res::cancel() const | |
276 | { | ||
277 | 8 | impl->send<zwp_primary_selection_source_v1_send_cancelled>(); | |
278 | 8 | impl->client->flush(); | |
279 | 8 | } | |
280 | |||
281 | 1 | void primary_selection_source_res::request_data(std::string const& mimeType, qint32 fd) const | |
282 | { | ||
283 | 1 | impl->send<zwp_primary_selection_source_v1_send_send>(mimeType.c_str(), fd); | |
284 | 1 | close(fd); | |
285 | 1 | } | |
286 | |||
287 | 31 | primary_selection_source* primary_selection_source_res::src() const | |
288 | { | ||
289 | 31 | return src_priv()->q_ptr; | |
290 | } | ||
291 | |||
292 | 52 | primary_selection_source::Private* primary_selection_source_res::src_priv() const | |
293 | { | ||
294 | 52 | return pub_src->d_ptr.get(); | |
295 | } | ||
296 | |||
297 | 21 | std::vector<std::string> primary_selection_source::mime_types() const | |
298 | { | ||
299 | 21 | return d_ptr->mimeTypes; | |
300 | } | ||
301 | |||
302 | 9 | void primary_selection_source::cancel() const | |
303 | { | ||
304 | 18 | std::visit([](auto&& res) { res->cancel(); }, d_ptr->res); | |
305 | 9 | } | |
306 | |||
307 | 2 | void primary_selection_source::request_data(std::string const& mimeType, qint32 fd) const | |
308 | { | ||
309 | 4 | std::visit([&](auto&& res) { res->request_data(mimeType, fd); }, d_ptr->res); | |
310 | 2 | } | |
311 | |||
312 | template<class... Ts> | ||
313 | // NOLINTNEXTLINE(fuchsia-multiple-inheritance) | ||
314 | struct overload : Ts... { | ||
315 | using Ts::operator()...; | ||
316 | }; | ||
317 | template<class... Ts> | ||
318 | overload(Ts...) -> overload<Ts...>; | ||
319 | |||
320 | ✗ | Client* primary_selection_source::client() const | |
321 | { | ||
322 | ✗ | Client* cl{nullptr}; | |
323 | |||
324 | ✗ | std::visit(overload{[&](primary_selection_source_res* res) { cl = res->impl->client->handle; }, | |
325 | ✗ | [&](data_control_source_v1_res* res) { cl = res->impl->client->handle; }, | |
326 | ✗ | [&](primary_selection_source_ext* /*unused*/) {}}, | |
327 | ✗ | d_ptr->res); | |
328 | |||
329 | ✗ | return cl; | |
330 | } | ||
331 | |||
332 | 1 | primary_selection_source_ext::Private::Private(primary_selection_source_ext* q_ptr) | |
333 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | : pub_src{new primary_selection_source} |
334 | 1 | , q_ptr{q_ptr} | |
335 | { | ||
336 | 1 | pub_src->d_ptr->res = q_ptr; | |
337 | 1 | } | |
338 | |||
339 | 1 | primary_selection_source_ext::primary_selection_source_ext() | |
340 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | : d_ptr{new Private(this)} |
341 | 1 | { | |
342 | 1 | } | |
343 | |||
344 | 1 | primary_selection_source_ext::~primary_selection_source_ext() | |
345 | 1 | { | |
346 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | Q_EMIT d_ptr->pub_src->resourceDestroyed(); |
347 | 1 | } | |
348 | |||
349 | 1 | void primary_selection_source_ext::offer(std::string const& mime_typ) | |
350 | { | ||
351 | 1 | offer_mime_type(d_ptr->pub_src->d_ptr.get(), mime_typ.c_str()); | |
352 | 1 | } | |
353 | |||
354 | 1 | primary_selection_source* primary_selection_source_ext::src() const | |
355 | { | ||
356 | 1 | return d_ptr->pub_src.get(); | |
357 | } | ||
358 | |||
359 | } | ||
360 |