clients: support ivi-application.xml for clients/window.c
[profile/ivi/weston-ivi-shell.git] / xwayland / selection.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29
30 #include "xwayland.h"
31
32 static int
33 writable_callback(int fd, uint32_t mask, void *data)
34 {
35         struct weston_wm *wm = data;
36         unsigned char *property;
37         int len, remainder;
38
39         property = xcb_get_property_value(wm->property_reply);
40         remainder = xcb_get_property_value_length(wm->property_reply) -
41                 wm->property_start;
42
43         len = write(fd, property + wm->property_start, remainder);
44         if (len == -1) {
45                 free(wm->property_reply);
46                 wm->property_reply = NULL;
47                 if (wm->property_source)
48                         wl_event_source_remove(wm->property_source);
49                 close(fd);
50                 weston_log("write error to target fd: %m\n");
51                 return 1;
52         }
53
54         weston_log("wrote %d (chunk size %d) of %d bytes\n",
55                 wm->property_start + len,
56                 len, xcb_get_property_value_length(wm->property_reply));
57
58         wm->property_start += len;
59         if (len == remainder) {
60                 free(wm->property_reply);
61                 wm->property_reply = NULL;
62                 if (wm->property_source)
63                         wl_event_source_remove(wm->property_source);
64
65                 if (wm->incr) {
66                         xcb_delete_property(wm->conn,
67                                             wm->selection_window,
68                                             wm->atom.wl_selection);
69                 } else {
70                         weston_log("transfer complete\n");
71                         close(fd);
72                 }
73         }
74
75         return 1;
76 }
77
78 static void
79 weston_wm_write_property(struct weston_wm *wm, xcb_get_property_reply_t *reply)
80 {
81         wm->property_start = 0;
82         wm->property_reply = reply;
83         writable_callback(wm->data_source_fd, WL_EVENT_WRITABLE, wm);
84
85         if (wm->property_reply)
86                 wm->property_source =
87                         wl_event_loop_add_fd(wm->server->loop,
88                                              wm->data_source_fd,
89                                              WL_EVENT_WRITABLE,
90                                              writable_callback, wm);
91 }
92
93 static void
94 weston_wm_get_incr_chunk(struct weston_wm *wm)
95 {
96         xcb_get_property_cookie_t cookie;
97         xcb_get_property_reply_t *reply;
98
99         cookie = xcb_get_property(wm->conn,
100                                   0, /* delete */
101                                   wm->selection_window,
102                                   wm->atom.wl_selection,
103                                   XCB_GET_PROPERTY_TYPE_ANY,
104                                   0, /* offset */
105                                   0x1fffffff /* length */);
106
107         reply = xcb_get_property_reply(wm->conn, cookie, NULL);
108
109         dump_property(wm, wm->atom.wl_selection, reply);
110
111         if (xcb_get_property_value_length(reply) > 0) {
112                 weston_wm_write_property(wm, reply);
113         } else {
114                 weston_log("transfer complete\n");
115                 close(wm->data_source_fd);
116                 free(reply);
117         }
118 }
119
120 struct x11_data_source {
121         struct weston_data_source base;
122         struct weston_wm *wm;
123 };
124
125 static void
126 data_source_accept(struct weston_data_source *source,
127                    uint32_t time, const char *mime_type)
128 {
129 }
130
131 static void
132 data_source_send(struct weston_data_source *base,
133                  const char *mime_type, int32_t fd)
134 {
135         struct x11_data_source *source = (struct x11_data_source *) base;
136         struct weston_wm *wm = source->wm;
137
138         if (strcmp(mime_type, "text/plain;charset=utf-8") == 0) {
139                 /* Get data for the utf8_string target */
140                 xcb_convert_selection(wm->conn,
141                                       wm->selection_window,
142                                       wm->atom.clipboard,
143                                       wm->atom.utf8_string,
144                                       wm->atom.wl_selection,
145                                       XCB_TIME_CURRENT_TIME);
146
147                 xcb_flush(wm->conn);
148
149                 fcntl(fd, F_SETFL, O_WRONLY | O_NONBLOCK);
150                 wm->data_source_fd = fd;
151         }
152 }
153
154 static void
155 data_source_cancel(struct weston_data_source *source)
156 {
157 }
158
159 static void
160 weston_wm_get_selection_targets(struct weston_wm *wm)
161 {
162         struct x11_data_source *source;
163         struct weston_compositor *compositor;
164         struct weston_seat *seat = weston_wm_pick_seat(wm);
165         xcb_get_property_cookie_t cookie;
166         xcb_get_property_reply_t *reply;
167         xcb_atom_t *value;
168         char **p;
169         uint32_t i;
170
171         cookie = xcb_get_property(wm->conn,
172                                   1, /* delete */
173                                   wm->selection_window,
174                                   wm->atom.wl_selection,
175                                   XCB_GET_PROPERTY_TYPE_ANY,
176                                   0, /* offset */
177                                   4096 /* length */);
178
179         reply = xcb_get_property_reply(wm->conn, cookie, NULL);
180
181         dump_property(wm, wm->atom.wl_selection, reply);
182
183         if (reply->type != XCB_ATOM_ATOM) {
184                 free(reply);
185                 return;
186         }
187
188         source = malloc(sizeof *source);
189         if (source == NULL)
190                 return;
191
192         wl_signal_init(&source->base.destroy_signal);
193         source->base.accept = data_source_accept;
194         source->base.send = data_source_send;
195         source->base.cancel = data_source_cancel;
196         source->wm = wm;
197
198         wl_array_init(&source->base.mime_types);
199         value = xcb_get_property_value(reply);
200         for (i = 0; i < reply->value_len; i++) {
201                 if (value[i] == wm->atom.utf8_string) {
202                         p = wl_array_add(&source->base.mime_types, sizeof *p);
203                         if (p)
204                                 *p = strdup("text/plain;charset=utf-8");
205                 }
206         }
207
208         compositor = wm->server->compositor;
209         weston_seat_set_selection(seat, &source->base,
210                                   wl_display_next_serial(compositor->wl_display));
211
212         free(reply);
213 }
214
215 static void
216 weston_wm_get_selection_data(struct weston_wm *wm)
217 {
218         xcb_get_property_cookie_t cookie;
219         xcb_get_property_reply_t *reply;
220
221         cookie = xcb_get_property(wm->conn,
222                                   1, /* delete */
223                                   wm->selection_window,
224                                   wm->atom.wl_selection,
225                                   XCB_GET_PROPERTY_TYPE_ANY,
226                                   0, /* offset */
227                                   0x1fffffff /* length */);
228
229         reply = xcb_get_property_reply(wm->conn, cookie, NULL);
230
231         if (reply->type == wm->atom.incr) {
232                 dump_property(wm, wm->atom.wl_selection, reply);
233                 wm->incr = 1;
234                 free(reply);
235         } else {
236                 dump_property(wm, wm->atom.wl_selection, reply);
237                 wm->incr = 0;
238                 weston_wm_write_property(wm, reply);
239         }
240 }
241
242 static void
243 weston_wm_handle_selection_notify(struct weston_wm *wm,
244                                 xcb_generic_event_t *event)
245 {
246         xcb_selection_notify_event_t *selection_notify =
247                 (xcb_selection_notify_event_t *) event;
248
249         if (selection_notify->property == XCB_ATOM_NONE) {
250                 /* convert selection failed */
251         } else if (selection_notify->target == wm->atom.targets) {
252                 weston_wm_get_selection_targets(wm);
253         } else {
254                 weston_wm_get_selection_data(wm);
255         }
256 }
257
258 static const size_t incr_chunk_size = 64 * 1024;
259
260 static void
261 weston_wm_send_selection_notify(struct weston_wm *wm, xcb_atom_t property)
262 {
263         xcb_selection_notify_event_t selection_notify;
264
265         memset(&selection_notify, 0, sizeof selection_notify);
266         selection_notify.response_type = XCB_SELECTION_NOTIFY;
267         selection_notify.sequence = 0;
268         selection_notify.time = wm->selection_request.time;
269         selection_notify.requestor = wm->selection_request.requestor;
270         selection_notify.selection = wm->selection_request.selection;
271         selection_notify.target = wm->selection_request.target;
272         selection_notify.property = property;
273
274         xcb_send_event(wm->conn, 0, /* propagate */
275                        wm->selection_request.requestor,
276                        XCB_EVENT_MASK_NO_EVENT, (char *) &selection_notify);
277 }
278
279 static void
280 weston_wm_send_targets(struct weston_wm *wm)
281 {
282         xcb_atom_t targets[] = {
283                 wm->atom.timestamp,
284                 wm->atom.targets,
285                 wm->atom.utf8_string,
286                 /* wm->atom.compound_text, */
287                 wm->atom.text,
288                 /* wm->atom.string */
289         };
290
291         xcb_change_property(wm->conn,
292                             XCB_PROP_MODE_REPLACE,
293                             wm->selection_request.requestor,
294                             wm->selection_request.property,
295                             XCB_ATOM_ATOM,
296                             32, /* format */
297                             ARRAY_LENGTH(targets), targets);
298
299         weston_wm_send_selection_notify(wm, wm->selection_request.property);
300 }
301
302 static void
303 weston_wm_send_timestamp(struct weston_wm *wm)
304 {
305         xcb_change_property(wm->conn,
306                             XCB_PROP_MODE_REPLACE,
307                             wm->selection_request.requestor,
308                             wm->selection_request.property,
309                             XCB_ATOM_INTEGER,
310                             32, /* format */
311                             1, &wm->selection_timestamp);
312
313         weston_wm_send_selection_notify(wm, wm->selection_request.property);
314 }
315
316 static int
317 weston_wm_flush_source_data(struct weston_wm *wm)
318 {
319         int length;
320
321         xcb_change_property(wm->conn,
322                             XCB_PROP_MODE_REPLACE,
323                             wm->selection_request.requestor,
324                             wm->selection_request.property,
325                             wm->selection_target,
326                             8, /* format */
327                             wm->source_data.size,
328                             wm->source_data.data);
329         wm->selection_property_set = 1;
330         length = wm->source_data.size;
331         wm->source_data.size = 0;
332
333         return length;
334 }
335
336 static int
337 weston_wm_read_data_source(int fd, uint32_t mask, void *data)
338 {
339         struct weston_wm *wm = data;
340         int len, current, available;
341         void *p;
342
343         current = wm->source_data.size;
344         if (wm->source_data.size < incr_chunk_size)
345                 p = wl_array_add(&wm->source_data, incr_chunk_size);
346         else
347                 p = (char *) wm->source_data.data + wm->source_data.size;
348         available = wm->source_data.alloc - current;
349
350         len = read(fd, p, available);
351         if (len == -1) {
352                 weston_log("read error from data source: %m\n");
353                 weston_wm_send_selection_notify(wm, XCB_ATOM_NONE);
354                 wl_event_source_remove(wm->property_source);
355                 close(fd);
356                 wl_array_release(&wm->source_data);
357         }
358
359         weston_log("read %d (available %d, mask 0x%x) bytes: \"%.*s\"\n",
360                 len, available, mask, len, (char *) p);
361
362         wm->source_data.size = current + len;
363         if (wm->source_data.size >= incr_chunk_size) {
364                 if (!wm->incr) {
365                         weston_log("got %zu bytes, starting incr\n",
366                                 wm->source_data.size);
367                         wm->incr = 1;
368                         xcb_change_property(wm->conn,
369                                             XCB_PROP_MODE_REPLACE,
370                                             wm->selection_request.requestor,
371                                             wm->selection_request.property,
372                                             wm->atom.incr,
373                                             32, /* format */
374                                             1, &incr_chunk_size);
375                         wm->selection_property_set = 1;
376                         wm->flush_property_on_delete = 1;
377                         wl_event_source_remove(wm->property_source);
378                         weston_wm_send_selection_notify(wm, wm->selection_request.property);
379                 } else if (wm->selection_property_set) {
380                         weston_log("got %zu bytes, waiting for "
381                                 "property delete\n", wm->source_data.size);
382
383                         wm->flush_property_on_delete = 1;
384                         wl_event_source_remove(wm->property_source);
385                 } else {
386                         weston_log("got %zu bytes, "
387                                 "property deleted, seting new property\n",
388                                 wm->source_data.size);
389                         weston_wm_flush_source_data(wm);
390                 }
391         } else if (len == 0 && !wm->incr) {
392                 weston_log("non-incr transfer complete\n");
393                 /* Non-incr transfer all done. */
394                 weston_wm_flush_source_data(wm);
395                 weston_wm_send_selection_notify(wm, wm->selection_request.property);
396                 xcb_flush(wm->conn);
397                 wl_event_source_remove(wm->property_source);
398                 close(fd);
399                 wl_array_release(&wm->source_data);
400                 wm->selection_request.requestor = XCB_NONE;
401         } else if (len == 0 && wm->incr) {
402                 weston_log("incr transfer complete\n");
403
404                 wm->flush_property_on_delete = 1;
405                 if (wm->selection_property_set) {
406                         weston_log("got %zu bytes, waiting for "
407                                 "property delete\n", wm->source_data.size);
408                 } else {
409                         weston_log("got %zu bytes, "
410                                 "property deleted, seting new property\n",
411                                 wm->source_data.size);
412                         weston_wm_flush_source_data(wm);
413                 }
414                 xcb_flush(wm->conn);
415                 wl_event_source_remove(wm->property_source);
416                 close(wm->data_source_fd);
417                 wm->data_source_fd = -1;
418                 close(fd);
419         } else {
420                 weston_log("nothing happened, buffered the bytes\n");
421         }
422
423         return 1;
424 }
425
426 static void
427 weston_wm_send_data(struct weston_wm *wm, xcb_atom_t target, const char *mime_type)
428 {
429         struct weston_data_source *source;
430         struct weston_seat *seat = weston_wm_pick_seat(wm);
431         int p[2];
432
433         if (pipe2(p, O_CLOEXEC | O_NONBLOCK) == -1) {
434                 weston_log("pipe2 failed: %m\n");
435                 weston_wm_send_selection_notify(wm, XCB_ATOM_NONE);
436                 return;
437         }
438
439         wl_array_init(&wm->source_data);
440         wm->selection_target = target;
441         wm->data_source_fd = p[0];
442         wm->property_source = wl_event_loop_add_fd(wm->server->loop,
443                                                    wm->data_source_fd,
444                                                    WL_EVENT_READABLE,
445                                                    weston_wm_read_data_source,
446                                                    wm);
447
448         source = seat->selection_data_source;
449         source->send(source, mime_type, p[1]);
450         close(p[1]);
451 }
452
453 static void
454 weston_wm_send_incr_chunk(struct weston_wm *wm)
455 {
456         int length;
457
458         weston_log("property deleted\n");
459
460         wm->selection_property_set = 0;
461         if (wm->flush_property_on_delete) {
462                 weston_log("setting new property, %zu bytes\n",
463                         wm->source_data.size);
464                 wm->flush_property_on_delete = 0;
465                 length = weston_wm_flush_source_data(wm);
466
467                 if (wm->data_source_fd >= 0) {
468                         wm->property_source =
469                                 wl_event_loop_add_fd(wm->server->loop,
470                                                      wm->data_source_fd,
471                                                      WL_EVENT_READABLE,
472                                                      weston_wm_read_data_source,
473                                                      wm);
474                 } else if (length > 0) {
475                         /* Transfer is all done, but queue a flush for
476                          * the delete of the last chunk so we can set
477                          * the 0 sized propert to signal the end of
478                          * the transfer. */
479                         wm->flush_property_on_delete = 1;
480                         wl_array_release(&wm->source_data);
481                 } else {
482                         wm->selection_request.requestor = XCB_NONE;
483                 }
484         }
485 }
486
487 static int
488 weston_wm_handle_selection_property_notify(struct weston_wm *wm,
489                                            xcb_generic_event_t *event)
490 {
491         xcb_property_notify_event_t *property_notify =
492                 (xcb_property_notify_event_t *) event;
493
494         if (property_notify->window == wm->selection_window) {
495                 if (property_notify->state == XCB_PROPERTY_NEW_VALUE &&
496                     property_notify->atom == wm->atom.wl_selection &&
497                     wm->incr)
498                         weston_wm_get_incr_chunk(wm);
499                 return 1;
500         } else if (property_notify->window == wm->selection_request.requestor) {
501                 if (property_notify->state == XCB_PROPERTY_DELETE &&
502                     property_notify->atom == wm->selection_request.property &&
503                     wm->incr)
504                         weston_wm_send_incr_chunk(wm);
505                 return 1;
506         }
507
508         return 0;
509 }
510
511 static void
512 weston_wm_handle_selection_request(struct weston_wm *wm,
513                                  xcb_generic_event_t *event)
514 {
515         xcb_selection_request_event_t *selection_request =
516                 (xcb_selection_request_event_t *) event;
517
518         weston_log("selection request, %s, ",
519                 get_atom_name(wm->conn, selection_request->selection));
520         weston_log_continue("target %s, ",
521                 get_atom_name(wm->conn, selection_request->target));
522         weston_log_continue("property %s\n",
523                 get_atom_name(wm->conn, selection_request->property));
524
525         wm->selection_request = *selection_request;
526         wm->incr = 0;
527         wm->flush_property_on_delete = 0;
528
529         if (selection_request->selection == wm->atom.clipboard_manager) {
530                 /* The weston clipboard should already have grabbed
531                  * the first target, so just send selection notify
532                  * now.  This isn't synchronized with the clipboard
533                  * finishing getting the data, so there's a race here. */
534                 weston_wm_send_selection_notify(wm, wm->selection_request.property);
535                 return;
536         }
537
538         if (selection_request->target == wm->atom.targets) {
539                 weston_wm_send_targets(wm);
540         } else if (selection_request->target == wm->atom.timestamp) {
541                 weston_wm_send_timestamp(wm);
542         } else if (selection_request->target == wm->atom.utf8_string ||
543                    selection_request->target == wm->atom.text) {
544                 weston_wm_send_data(wm, wm->atom.utf8_string,
545                                   "text/plain;charset=utf-8");
546         } else {
547                 weston_log("can only handle UTF8_STRING targets...\n");
548                 weston_wm_send_selection_notify(wm, XCB_ATOM_NONE);
549         }
550 }
551
552 static int
553 weston_wm_handle_xfixes_selection_notify(struct weston_wm *wm,
554                                        xcb_generic_event_t *event)
555 {
556         xcb_xfixes_selection_notify_event_t *xfixes_selection_notify =
557                 (xcb_xfixes_selection_notify_event_t *) event;
558         struct weston_compositor *compositor;
559         struct weston_seat *seat = weston_wm_pick_seat(wm);
560         uint32_t serial;
561
562         if (xfixes_selection_notify->selection != wm->atom.clipboard)
563                 return 0;
564
565         weston_log("xfixes selection notify event: owner %d\n",
566                xfixes_selection_notify->owner);
567
568         if (xfixes_selection_notify->owner == XCB_WINDOW_NONE) {
569                 if (wm->selection_owner != wm->selection_window) {
570                         /* A real X client selection went away, not our
571                          * proxy selection.  Clear the wayland selection. */
572                         compositor = wm->server->compositor;
573                         serial = wl_display_next_serial(compositor->wl_display);
574                         weston_seat_set_selection(seat, NULL, serial);
575                 }
576
577                 wm->selection_owner = XCB_WINDOW_NONE;
578
579                 return 1;
580         }
581
582         wm->selection_owner = xfixes_selection_notify->owner;
583
584         /* We have to use XCB_TIME_CURRENT_TIME when we claim the
585          * selection, so grab the actual timestamp here so we can
586          * answer TIMESTAMP conversion requests correctly. */
587         if (xfixes_selection_notify->owner == wm->selection_window) {
588                 wm->selection_timestamp = xfixes_selection_notify->timestamp;
589                 weston_log("our window, skipping\n");
590                 return 1;
591         }
592
593         wm->incr = 0;
594         xcb_convert_selection(wm->conn, wm->selection_window,
595                               wm->atom.clipboard,
596                               wm->atom.targets,
597                               wm->atom.wl_selection,
598                               xfixes_selection_notify->timestamp);
599
600         xcb_flush(wm->conn);
601
602         return 1;
603 }
604
605 int
606 weston_wm_handle_selection_event(struct weston_wm *wm,
607                                  xcb_generic_event_t *event)
608 {
609         switch (event->response_type & ~0x80) {
610         case XCB_SELECTION_NOTIFY:
611                 weston_wm_handle_selection_notify(wm, event);
612                 return 1;
613         case XCB_PROPERTY_NOTIFY:
614                 return weston_wm_handle_selection_property_notify(wm, event);
615         case XCB_SELECTION_REQUEST:
616                 weston_wm_handle_selection_request(wm, event);
617                 return 1;
618         }
619
620         switch (event->response_type - wm->xfixes->first_event) {
621         case XCB_XFIXES_SELECTION_NOTIFY:
622                 return weston_wm_handle_xfixes_selection_notify(wm, event);
623         }
624
625         return 0;
626 }
627
628 static void
629 weston_wm_set_selection(struct wl_listener *listener, void *data)
630 {
631         struct weston_seat *seat = data;
632         struct weston_wm *wm =
633                 container_of(listener, struct weston_wm, selection_listener);
634         struct weston_data_source *source = seat->selection_data_source;
635         const char **p, **end;
636         int has_text_plain = 0;
637
638         if (source == NULL) {
639                 if (wm->selection_owner == wm->selection_window)
640                         xcb_set_selection_owner(wm->conn,
641                                                 XCB_ATOM_NONE,
642                                                 wm->atom.clipboard,
643                                                 wm->selection_timestamp);
644                 return;
645         }
646
647         if (source->send == data_source_send)
648                 return;
649
650         p = source->mime_types.data;
651         end = (const char **)
652                 ((char *) source->mime_types.data + source->mime_types.size);
653         while (p < end) {
654                 weston_log("  %s\n", *p);
655                 if (strcmp(*p, "text/plain") == 0 ||
656                     strcmp(*p, "text/plain;charset=utf-8") == 0)
657                         has_text_plain = 1;
658                 p++;
659         }
660
661         if (has_text_plain) {
662                 xcb_set_selection_owner(wm->conn,
663                                         wm->selection_window,
664                                         wm->atom.clipboard,
665                                         XCB_TIME_CURRENT_TIME);
666         } else {
667                 xcb_set_selection_owner(wm->conn,
668                                         XCB_ATOM_NONE,
669                                         wm->atom.clipboard,
670                                         XCB_TIME_CURRENT_TIME);
671         }
672 }
673
674 void
675 weston_wm_selection_init(struct weston_wm *wm)
676 {
677         struct weston_seat *seat;
678         uint32_t values[1], mask;
679
680         wm->selection_request.requestor = XCB_NONE;
681
682         values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE;
683         wm->selection_window = xcb_generate_id(wm->conn);
684         xcb_create_window(wm->conn,
685                           XCB_COPY_FROM_PARENT,
686                           wm->selection_window,
687                           wm->screen->root,
688                           0, 0,
689                           10, 10,
690                           0,
691                           XCB_WINDOW_CLASS_INPUT_OUTPUT,
692                           wm->screen->root_visual,
693                           XCB_CW_EVENT_MASK, values);
694
695         xcb_set_selection_owner(wm->conn,
696                                 wm->selection_window,
697                                 wm->atom.clipboard_manager,
698                                 XCB_TIME_CURRENT_TIME);
699
700         mask =
701                 XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
702                 XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
703                 XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
704         xcb_xfixes_select_selection_input(wm->conn, wm->selection_window,
705                                           wm->atom.clipboard, mask);
706
707         seat = weston_wm_pick_seat(wm);
708         wm->selection_listener.notify = weston_wm_set_selection;
709         wl_signal_add(&seat->selection_signal, &wm->selection_listener);
710
711         weston_wm_set_selection(&wm->selection_listener, seat);
712 }