1 #define _POSIX_C_SOURCE 200809L
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <wlr/types/wlr_data_control_v1.h>
7 #include <wlr/types/wlr_data_device.h>
8 #include <wlr/types/wlr_primary_selection.h>
9 #include <wlr/util/log.h>
10 #include "util/signal.h"
11 #include "wlr-data-control-unstable-v1-protocol.h"
12
13 #define DATA_CONTROL_MANAGER_VERSION 2
14
15 struct data_control_source {
16 struct wl_resource *resource;
17 struct wl_array mime_types;
18 bool finalized;
19
20 // Only one of these is non-NULL.
21 struct wlr_data_source *active_source;
22 struct wlr_primary_selection_source *active_primary_source;
23 };
24
25 static const struct zwlr_data_control_source_v1_interface source_impl;
26
source_from_resource(struct wl_resource * resource)27 static struct data_control_source *source_from_resource(
28 struct wl_resource *resource) {
29 assert(wl_resource_instance_of(resource,
30 &zwlr_data_control_source_v1_interface, &source_impl));
31 return wl_resource_get_user_data(resource);
32 }
33
source_handle_offer(struct wl_client * client,struct wl_resource * resource,const char * mime_type)34 static void source_handle_offer(struct wl_client *client,
35 struct wl_resource *resource, const char *mime_type) {
36 struct data_control_source *source = source_from_resource(resource);
37 if (source == NULL) {
38 return;
39 }
40
41 if (source->finalized) {
42 wl_resource_post_error(resource,
43 ZWLR_DATA_CONTROL_SOURCE_V1_ERROR_INVALID_OFFER,
44 "cannot mutate offer after set_selection or "
45 "set_primary_selection");
46 return;
47 }
48
49 const char **mime_type_ptr;
50 wl_array_for_each(mime_type_ptr, &source->mime_types) {
51 if (strcmp(*mime_type_ptr, mime_type) == 0) {
52 wlr_log(WLR_DEBUG, "Ignoring duplicate MIME type offer %s",
53 mime_type);
54 return;
55 }
56 }
57
58 char *dup_mime_type = strdup(mime_type);
59 if (dup_mime_type == NULL) {
60 wl_resource_post_no_memory(resource);
61 return;
62 }
63
64 char **p = wl_array_add(&source->mime_types, sizeof(char *));
65 if (p == NULL) {
66 free(dup_mime_type);
67 wl_resource_post_no_memory(resource);
68 return;
69 }
70
71 *p = dup_mime_type;
72 }
73
source_handle_destroy(struct wl_client * client,struct wl_resource * resource)74 static void source_handle_destroy(struct wl_client *client,
75 struct wl_resource *resource) {
76 wl_resource_destroy(resource);
77 }
78
79 static const struct zwlr_data_control_source_v1_interface source_impl = {
80 .offer = source_handle_offer,
81 .destroy = source_handle_destroy,
82 };
83
data_control_source_destroy(struct data_control_source * source)84 static void data_control_source_destroy(struct data_control_source *source) {
85 if (source == NULL) {
86 return;
87 }
88
89 char **p;
90 wl_array_for_each(p, &source->mime_types) {
91 free(*p);
92 }
93 wl_array_release(&source->mime_types);
94
95 // Prevent destructors below from calling this recursively.
96 wl_resource_set_user_data(source->resource, NULL);
97
98 if (source->active_source != NULL) {
99 wlr_data_source_destroy(source->active_source);
100 } else if (source->active_primary_source != NULL) {
101 wlr_primary_selection_source_destroy(
102 source->active_primary_source);
103 }
104
105 free(source);
106 }
107
source_handle_resource_destroy(struct wl_resource * resource)108 static void source_handle_resource_destroy(struct wl_resource *resource) {
109 struct data_control_source *source = source_from_resource(resource);
110 data_control_source_destroy(source);
111 }
112
113
114 struct client_data_source {
115 struct wlr_data_source source;
116 struct wl_resource *resource;
117 };
118
119 static const struct wlr_data_source_impl client_source_impl;
120
121 static struct client_data_source *
client_data_source_from_source(struct wlr_data_source * wlr_source)122 client_data_source_from_source(struct wlr_data_source *wlr_source) {
123 assert(wlr_source->impl == &client_source_impl);
124 return (struct client_data_source *)wlr_source;
125 }
126
client_source_send(struct wlr_data_source * wlr_source,const char * mime_type,int fd)127 static void client_source_send(struct wlr_data_source *wlr_source,
128 const char *mime_type, int fd) {
129 struct client_data_source *source =
130 client_data_source_from_source(wlr_source);
131 zwlr_data_control_source_v1_send_send(source->resource, mime_type, fd);
132 close(fd);
133 }
134
client_source_destroy(struct wlr_data_source * wlr_source)135 static void client_source_destroy(struct wlr_data_source *wlr_source) {
136 struct client_data_source *client_source =
137 client_data_source_from_source(wlr_source);
138 struct data_control_source *source =
139 source_from_resource(client_source->resource);
140 free(client_source);
141
142 if (source == NULL) {
143 return;
144 }
145
146 source->active_source = NULL;
147
148 zwlr_data_control_source_v1_send_cancelled(source->resource);
149 data_control_source_destroy(source);
150 }
151
152 static const struct wlr_data_source_impl client_source_impl = {
153 .send = client_source_send,
154 .destroy = client_source_destroy,
155 };
156
157
158 struct client_primary_selection_source {
159 struct wlr_primary_selection_source source;
160 struct wl_resource *resource;
161 };
162
163 static const struct wlr_primary_selection_source_impl
164 client_primary_selection_source_impl;
165
166 static struct client_primary_selection_source *
client_primary_selection_source_from_source(struct wlr_primary_selection_source * wlr_source)167 client_primary_selection_source_from_source(
168 struct wlr_primary_selection_source *wlr_source) {
169 assert(wlr_source->impl == &client_primary_selection_source_impl);
170 return (struct client_primary_selection_source *)wlr_source;
171 }
172
client_primary_selection_source_send(struct wlr_primary_selection_source * wlr_source,const char * mime_type,int fd)173 static void client_primary_selection_source_send(
174 struct wlr_primary_selection_source *wlr_source,
175 const char *mime_type, int fd) {
176 struct client_primary_selection_source *source =
177 client_primary_selection_source_from_source(wlr_source);
178 zwlr_data_control_source_v1_send_send(source->resource, mime_type, fd);
179 close(fd);
180 }
181
client_primary_selection_source_destroy(struct wlr_primary_selection_source * wlr_source)182 static void client_primary_selection_source_destroy(
183 struct wlr_primary_selection_source *wlr_source) {
184 struct client_primary_selection_source *client_source =
185 client_primary_selection_source_from_source(wlr_source);
186 struct data_control_source *source =
187 source_from_resource(client_source->resource);
188 free(client_source);
189
190 if (source == NULL) {
191 return;
192 }
193
194 source->active_primary_source = NULL;
195
196 zwlr_data_control_source_v1_send_cancelled(source->resource);
197 data_control_source_destroy(source);
198 }
199
200 static const struct wlr_primary_selection_source_impl
201 client_primary_selection_source_impl = {
202 .send = client_primary_selection_source_send,
203 .destroy = client_primary_selection_source_destroy,
204 };
205
206
207 struct data_offer {
208 struct wl_resource *resource;
209 struct wlr_data_control_device_v1 *device;
210 bool is_primary;
211 };
212
data_offer_destroy(struct data_offer * offer)213 static void data_offer_destroy(struct data_offer *offer) {
214 if (offer == NULL) {
215 return;
216 }
217
218 struct wlr_data_control_device_v1 *device = offer->device;
219 if (device != NULL) {
220 if (offer->is_primary) {
221 device->primary_selection_offer_resource = NULL;
222 } else {
223 device->selection_offer_resource = NULL;
224 }
225 }
226
227 wl_resource_set_user_data(offer->resource, NULL);
228 free(offer);
229 }
230
231 static const struct zwlr_data_control_offer_v1_interface offer_impl;
232
data_offer_from_offer_resource(struct wl_resource * resource)233 static struct data_offer *data_offer_from_offer_resource(
234 struct wl_resource *resource) {
235 assert(wl_resource_instance_of(resource,
236 &zwlr_data_control_offer_v1_interface, &offer_impl));
237 return wl_resource_get_user_data(resource);
238 }
239
offer_handle_receive(struct wl_client * client,struct wl_resource * resource,const char * mime_type,int fd)240 static void offer_handle_receive(struct wl_client *client,
241 struct wl_resource *resource, const char *mime_type, int fd) {
242 struct data_offer *offer = data_offer_from_offer_resource(resource);
243 if (offer == NULL) {
244 close(fd);
245 return;
246 }
247
248 struct wlr_data_control_device_v1 *device = offer->device;
249 if (device == NULL) {
250 close(fd);
251 return;
252 }
253
254 if (offer->is_primary) {
255 if (device->seat->primary_selection_source == NULL) {
256 close(fd);
257 return;
258 }
259 wlr_primary_selection_source_send(
260 device->seat->primary_selection_source,
261 mime_type, fd);
262 } else {
263 if (device->seat->selection_source == NULL) {
264 close(fd);
265 return;
266 }
267 wlr_data_source_send(device->seat->selection_source, mime_type, fd);
268 }
269 }
270
offer_handle_destroy(struct wl_client * client,struct wl_resource * resource)271 static void offer_handle_destroy(struct wl_client *client,
272 struct wl_resource *resource) {
273 wl_resource_destroy(resource);
274 }
275
276 static const struct zwlr_data_control_offer_v1_interface offer_impl = {
277 .receive = offer_handle_receive,
278 .destroy = offer_handle_destroy,
279 };
280
offer_handle_resource_destroy(struct wl_resource * resource)281 static void offer_handle_resource_destroy(struct wl_resource *resource) {
282 struct data_offer *offer = data_offer_from_offer_resource(resource);
283 data_offer_destroy(offer);
284 }
285
create_offer(struct wlr_data_control_device_v1 * device,struct wl_array * mime_types,bool is_primary)286 static struct wl_resource *create_offer(struct wlr_data_control_device_v1 *device,
287 struct wl_array *mime_types, bool is_primary) {
288 struct wl_client *client = wl_resource_get_client(device->resource);
289
290 struct data_offer *offer = calloc(1, sizeof(struct data_offer));
291 if (offer == NULL) {
292 wl_client_post_no_memory(client);
293 return NULL;
294 }
295
296 offer->device = device;
297 offer->is_primary = is_primary;
298
299 uint32_t version = wl_resource_get_version(device->resource);
300 struct wl_resource *resource = wl_resource_create(client,
301 &zwlr_data_control_offer_v1_interface, version, 0);
302 if (resource == NULL) {
303 free(offer);
304 return NULL;
305 }
306
307 offer->resource = resource;
308
309 wl_resource_set_implementation(resource, &offer_impl, offer,
310 offer_handle_resource_destroy);
311
312 zwlr_data_control_device_v1_send_data_offer(device->resource, resource);
313
314 char **p;
315 wl_array_for_each(p, mime_types) {
316 zwlr_data_control_offer_v1_send_offer(resource, *p);
317 }
318
319 return resource;
320 }
321
322
323 static const struct zwlr_data_control_device_v1_interface control_impl;
324
control_from_resource(struct wl_resource * resource)325 static struct wlr_data_control_device_v1 *control_from_resource(
326 struct wl_resource *resource) {
327 assert(wl_resource_instance_of(resource,
328 &zwlr_data_control_device_v1_interface, &control_impl));
329 return wl_resource_get_user_data(resource);
330 }
331
control_handle_set_selection(struct wl_client * client,struct wl_resource * control_resource,struct wl_resource * source_resource)332 static void control_handle_set_selection(struct wl_client *client,
333 struct wl_resource *control_resource,
334 struct wl_resource *source_resource) {
335 struct wlr_data_control_device_v1 *device =
336 control_from_resource(control_resource);
337 if (device == NULL) {
338 return;
339 }
340
341 struct data_control_source *source = NULL;
342 if (source_resource != NULL) {
343 source = source_from_resource(source_resource);
344 }
345
346 if (source == NULL) {
347 wlr_seat_request_set_selection(device->seat, NULL, NULL,
348 wl_display_next_serial(device->seat->display));
349
350 return;
351 }
352
353 if (source->active_source != NULL ||
354 source->active_primary_source != NULL) {
355 wl_resource_post_error(control_resource,
356 ZWLR_DATA_CONTROL_DEVICE_V1_ERROR_USED_SOURCE,
357 "cannot use a data source in set_selection or "
358 "set_primary_selection more than once");
359
360 return;
361 }
362
363 struct client_data_source *client_source =
364 calloc(1, sizeof(struct client_data_source));
365 if (client_source == NULL) {
366 wl_client_post_no_memory(client);
367 return;
368 }
369 client_source->resource = source_resource;
370
371 struct wlr_data_source *wlr_source = &client_source->source;
372 wlr_data_source_init(wlr_source, &client_source_impl);
373 source->active_source = wlr_source;
374
375 wl_array_release(&wlr_source->mime_types);
376 wlr_source->mime_types = source->mime_types;
377 wl_array_init(&source->mime_types);
378
379 source->finalized = true;
380
381 wlr_seat_request_set_selection(device->seat, NULL, wlr_source,
382 wl_display_next_serial(device->seat->display));
383 }
384
control_handle_set_primary_selection(struct wl_client * client,struct wl_resource * control_resource,struct wl_resource * source_resource)385 static void control_handle_set_primary_selection(struct wl_client *client,
386 struct wl_resource *control_resource,
387 struct wl_resource *source_resource) {
388 struct wlr_data_control_device_v1 *device =
389 control_from_resource(control_resource);
390 if (device == NULL) {
391 return;
392 }
393
394 struct data_control_source *source = NULL;
395 if (source_resource != NULL) {
396 source = source_from_resource(source_resource);
397 }
398
399 if (source == NULL) {
400 wlr_seat_request_set_primary_selection(device->seat, NULL, NULL,
401 wl_display_next_serial(device->seat->display));
402
403 return;
404 }
405
406 if (source->active_source != NULL ||
407 source->active_primary_source != NULL) {
408 wl_resource_post_error(control_resource,
409 ZWLR_DATA_CONTROL_DEVICE_V1_ERROR_USED_SOURCE,
410 "cannot use a data source in set_selection or "
411 "set_primary_selection more than once");
412
413 return;
414 }
415
416 struct client_primary_selection_source *client_source =
417 calloc(1, sizeof(struct client_primary_selection_source));
418 if (client_source == NULL) {
419 wl_client_post_no_memory(client);
420 return;
421 }
422 client_source->resource = source_resource;
423
424 struct wlr_primary_selection_source *wlr_source = &client_source->source;
425 wlr_primary_selection_source_init(wlr_source, &client_primary_selection_source_impl);
426 source->active_primary_source = wlr_source;
427
428 wl_array_release(&wlr_source->mime_types);
429 wlr_source->mime_types = source->mime_types;
430 wl_array_init(&source->mime_types);
431
432 source->finalized = true;
433
434 wlr_seat_request_set_primary_selection(device->seat, NULL, wlr_source,
435 wl_display_next_serial(device->seat->display));
436 }
437
control_handle_destroy(struct wl_client * client,struct wl_resource * control_resource)438 static void control_handle_destroy(struct wl_client *client,
439 struct wl_resource *control_resource) {
440 wl_resource_destroy(control_resource);
441 }
442
443 static const struct zwlr_data_control_device_v1_interface control_impl = {
444 .set_selection = control_handle_set_selection,
445 .set_primary_selection = control_handle_set_primary_selection,
446 .destroy = control_handle_destroy,
447 };
448
control_send_selection(struct wlr_data_control_device_v1 * device)449 static void control_send_selection(struct wlr_data_control_device_v1 *device) {
450 struct wlr_data_source *source = device->seat->selection_source;
451
452 if (device->selection_offer_resource != NULL) {
453 // Make the offer inert
454 struct data_offer *offer = data_offer_from_offer_resource(
455 device->selection_offer_resource);
456 data_offer_destroy(offer);
457 }
458
459 device->selection_offer_resource = NULL;
460 if (source != NULL) {
461 device->selection_offer_resource =
462 create_offer(device, &source->mime_types, false);
463 if (device->selection_offer_resource == NULL) {
464 wl_resource_post_no_memory(device->resource);
465 return;
466 }
467 }
468
469 zwlr_data_control_device_v1_send_selection(device->resource,
470 device->selection_offer_resource);
471 }
472
control_send_primary_selection(struct wlr_data_control_device_v1 * device)473 static void control_send_primary_selection(
474 struct wlr_data_control_device_v1 *device) {
475 uint32_t version = wl_resource_get_version(device->resource);
476 if (version < ZWLR_DATA_CONTROL_DEVICE_V1_PRIMARY_SELECTION_SINCE_VERSION) {
477 return;
478 }
479
480 struct wlr_primary_selection_source *source =
481 device->seat->primary_selection_source;
482
483 if (device->primary_selection_offer_resource != NULL) {
484 // Make the offer inert
485 struct data_offer *offer = data_offer_from_offer_resource(
486 device->primary_selection_offer_resource);
487 data_offer_destroy(offer);
488 }
489
490 device->primary_selection_offer_resource = NULL;
491 if (source != NULL) {
492 device->primary_selection_offer_resource =
493 create_offer(device, &source->mime_types, true);
494 if (device->primary_selection_offer_resource == NULL) {
495 wl_resource_post_no_memory(device->resource);
496 return;
497 }
498 }
499
500 zwlr_data_control_device_v1_send_primary_selection(device->resource,
501 device->primary_selection_offer_resource);
502 }
503
control_handle_resource_destroy(struct wl_resource * resource)504 static void control_handle_resource_destroy(struct wl_resource *resource) {
505 struct wlr_data_control_device_v1 *device = control_from_resource(resource);
506 wlr_data_control_device_v1_destroy(device);
507 }
508
control_handle_seat_destroy(struct wl_listener * listener,void * data)509 static void control_handle_seat_destroy(struct wl_listener *listener,
510 void *data) {
511 struct wlr_data_control_device_v1 *device =
512 wl_container_of(listener, device, seat_destroy);
513 wlr_data_control_device_v1_destroy(device);
514 }
515
control_handle_seat_set_selection(struct wl_listener * listener,void * data)516 static void control_handle_seat_set_selection(struct wl_listener *listener,
517 void *data) {
518 struct wlr_data_control_device_v1 *device =
519 wl_container_of(listener, device, seat_set_selection);
520 control_send_selection(device);
521 }
522
control_handle_seat_set_primary_selection(struct wl_listener * listener,void * data)523 static void control_handle_seat_set_primary_selection(
524 struct wl_listener *listener,
525 void *data) {
526 struct wlr_data_control_device_v1 *device =
527 wl_container_of(listener, device, seat_set_primary_selection);
528 control_send_primary_selection(device);
529 }
530
wlr_data_control_device_v1_destroy(struct wlr_data_control_device_v1 * device)531 void wlr_data_control_device_v1_destroy(struct wlr_data_control_device_v1 *device) {
532 if (device == NULL) {
533 return;
534 }
535 zwlr_data_control_device_v1_send_finished(device->resource);
536 // Make the resources inert
537 wl_resource_set_user_data(device->resource, NULL);
538 if (device->selection_offer_resource != NULL) {
539 struct data_offer *offer = data_offer_from_offer_resource(
540 device->selection_offer_resource);
541 data_offer_destroy(offer);
542 }
543 if (device->primary_selection_offer_resource != NULL) {
544 struct data_offer *offer = data_offer_from_offer_resource(
545 device->primary_selection_offer_resource);
546 data_offer_destroy(offer);
547 }
548 wl_list_remove(&device->seat_destroy.link);
549 wl_list_remove(&device->seat_set_selection.link);
550 wl_list_remove(&device->seat_set_primary_selection.link);
551 wl_list_remove(&device->link);
552 free(device);
553 }
554
555
556 static const struct zwlr_data_control_manager_v1_interface manager_impl;
557
manager_from_resource(struct wl_resource * resource)558 static struct wlr_data_control_manager_v1 *manager_from_resource(
559 struct wl_resource *resource) {
560 assert(wl_resource_instance_of(resource,
561 &zwlr_data_control_manager_v1_interface, &manager_impl));
562 return wl_resource_get_user_data(resource);
563 }
564
manager_handle_create_data_source(struct wl_client * client,struct wl_resource * manager_resource,uint32_t id)565 static void manager_handle_create_data_source(struct wl_client *client,
566 struct wl_resource *manager_resource, uint32_t id) {
567 struct data_control_source *source =
568 calloc(1, sizeof(struct data_control_source));
569 if (source == NULL) {
570 wl_resource_post_no_memory(manager_resource);
571 return;
572 }
573
574 wl_array_init(&source->mime_types);
575
576 uint32_t version = wl_resource_get_version(manager_resource);
577 source->resource = wl_resource_create(client,
578 &zwlr_data_control_source_v1_interface, version, id);
579 if (source->resource == NULL) {
580 wl_resource_post_no_memory(manager_resource);
581 wl_array_release(&source->mime_types);
582 free(source);
583 return;
584 }
585 wl_resource_set_implementation(source->resource, &source_impl, source,
586 source_handle_resource_destroy);
587 }
588
manager_handle_get_data_device(struct wl_client * client,struct wl_resource * manager_resource,uint32_t id,struct wl_resource * seat_resource)589 static void manager_handle_get_data_device(struct wl_client *client,
590 struct wl_resource *manager_resource, uint32_t id,
591 struct wl_resource *seat_resource) {
592 struct wlr_data_control_manager_v1 *manager =
593 manager_from_resource(manager_resource);
594 struct wlr_seat_client *seat_client =
595 wlr_seat_client_from_resource(seat_resource);
596
597 struct wlr_data_control_device_v1 *device =
598 calloc(1, sizeof(struct wlr_data_control_device_v1));
599 if (device == NULL) {
600 wl_resource_post_no_memory(manager_resource);
601 return;
602 }
603 device->manager = manager;
604 device->seat = seat_client->seat;
605
606 uint32_t version = wl_resource_get_version(manager_resource);
607 device->resource = wl_resource_create(client,
608 &zwlr_data_control_device_v1_interface, version, id);
609 if (device->resource == NULL) {
610 wl_resource_post_no_memory(manager_resource);
611 free(device);
612 return;
613 }
614 wl_resource_set_implementation(device->resource, &control_impl, device,
615 control_handle_resource_destroy);
616 struct wl_resource *resource = device->resource;
617
618 device->seat_destroy.notify = control_handle_seat_destroy;
619 wl_signal_add(&device->seat->events.destroy, &device->seat_destroy);
620
621 device->seat_set_selection.notify = control_handle_seat_set_selection;
622 wl_signal_add(&device->seat->events.set_selection,
623 &device->seat_set_selection);
624
625 device->seat_set_primary_selection.notify =
626 control_handle_seat_set_primary_selection;
627 wl_signal_add(&device->seat->events.set_primary_selection,
628 &device->seat_set_primary_selection);
629
630 wl_list_insert(&manager->devices, &device->link);
631 wlr_signal_emit_safe(&manager->events.new_device, device);
632
633 // At this point maybe the compositor decided to destroy the device. If
634 // it's the case then the resource will be inert.
635 device = control_from_resource(resource);
636 if (device != NULL) {
637 control_send_selection(device);
638 control_send_primary_selection(device);
639 }
640 }
641
manager_handle_destroy(struct wl_client * client,struct wl_resource * manager_resource)642 static void manager_handle_destroy(struct wl_client *client,
643 struct wl_resource *manager_resource) {
644 wl_resource_destroy(manager_resource);
645 }
646
647 static const struct zwlr_data_control_manager_v1_interface manager_impl = {
648 .create_data_source = manager_handle_create_data_source,
649 .get_data_device = manager_handle_get_data_device,
650 .destroy = manager_handle_destroy,
651 };
652
manager_bind(struct wl_client * client,void * data,uint32_t version,uint32_t id)653 static void manager_bind(struct wl_client *client, void *data, uint32_t version,
654 uint32_t id) {
655 struct wlr_data_control_manager_v1 *manager = data;
656
657 struct wl_resource *resource = wl_resource_create(client,
658 &zwlr_data_control_manager_v1_interface, version, id);
659 if (resource == NULL) {
660 wl_client_post_no_memory(client);
661 return;
662 }
663 wl_resource_set_implementation(resource, &manager_impl, manager, NULL);
664 }
665
handle_display_destroy(struct wl_listener * listener,void * data)666 static void handle_display_destroy(struct wl_listener *listener, void *data) {
667 struct wlr_data_control_manager_v1 *manager =
668 wl_container_of(listener, manager, display_destroy);
669 wlr_signal_emit_safe(&manager->events.destroy, manager);
670 wl_list_remove(&manager->display_destroy.link);
671 wl_global_destroy(manager->global);
672 free(manager);
673 }
674
wlr_data_control_manager_v1_create(struct wl_display * display)675 struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1_create(
676 struct wl_display *display) {
677 struct wlr_data_control_manager_v1 *manager =
678 calloc(1, sizeof(struct wlr_data_control_manager_v1));
679 if (manager == NULL) {
680 return NULL;
681 }
682 wl_list_init(&manager->devices);
683 wl_signal_init(&manager->events.destroy);
684 wl_signal_init(&manager->events.new_device);
685
686 manager->global = wl_global_create(display,
687 &zwlr_data_control_manager_v1_interface,
688 DATA_CONTROL_MANAGER_VERSION, manager, manager_bind);
689 if (manager->global == NULL) {
690 free(manager);
691 return NULL;
692 }
693
694 manager->display_destroy.notify = handle_display_destroy;
695 wl_display_add_destroy_listener(display, &manager->display_destroy);
696
697 return manager;
698 }
699