libweston: Rename weston_surface::configure to ::committed
[platform/upstream/weston.git] / libweston / data-device.c
1 /*
2  * Copyright © 2011 Kristian Høgsberg
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include "config.h"
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <stdint.h>
32 #include <stdio.h>
33 #include <assert.h>
34
35 #include "compositor.h"
36 #include "shared/helpers.h"
37
38 struct weston_drag {
39         struct wl_client *client;
40         struct weston_data_source *data_source;
41         struct wl_listener data_source_listener;
42         struct weston_view *focus;
43         struct wl_resource *focus_resource;
44         struct wl_listener focus_listener;
45         struct weston_view *icon;
46         struct wl_listener icon_destroy_listener;
47         int32_t dx, dy;
48         struct weston_keyboard_grab keyboard_grab;
49 };
50
51 struct weston_pointer_drag {
52         struct weston_drag  base;
53         struct weston_pointer_grab grab;
54 };
55
56 struct weston_touch_drag {
57         struct weston_drag base;
58         struct weston_touch_grab grab;
59 };
60
61 #define ALL_ACTIONS (WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | \
62                      WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE | \
63                      WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
64
65 static void
66 data_offer_accept(struct wl_client *client, struct wl_resource *resource,
67                   uint32_t serial, const char *mime_type)
68 {
69         struct weston_data_offer *offer = wl_resource_get_user_data(resource);
70
71         /* Protect against untimely calls from older data offers */
72         if (!offer->source || offer != offer->source->offer)
73                 return;
74
75         /* FIXME: Check that client is currently focused by the input
76          * device that is currently dragging this data source.  Should
77          * this be a wl_data_device request? */
78
79         offer->source->accept(offer->source, serial, mime_type);
80         offer->source->accepted = mime_type != NULL;
81 }
82
83 static void
84 data_offer_receive(struct wl_client *client, struct wl_resource *resource,
85                    const char *mime_type, int32_t fd)
86 {
87         struct weston_data_offer *offer = wl_resource_get_user_data(resource);
88
89         if (offer->source && offer == offer->source->offer)
90                 offer->source->send(offer->source, mime_type, fd);
91         else
92                 close(fd);
93 }
94
95 static void
96 data_offer_destroy(struct wl_client *client, struct wl_resource *resource)
97 {
98         wl_resource_destroy(resource);
99 }
100
101 static void
102 data_source_notify_finish(struct weston_data_source *source)
103 {
104         if (!source->actions_set)
105                 return;
106
107         if (source->offer->in_ask &&
108             wl_resource_get_version(source->resource) >=
109             WL_DATA_SOURCE_ACTION_SINCE_VERSION) {
110                 wl_data_source_send_action(source->resource,
111                                            source->current_dnd_action);
112         }
113
114         if (wl_resource_get_version(source->resource) >=
115             WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
116                 wl_data_source_send_dnd_finished(source->resource);
117         }
118
119         source->offer = NULL;
120 }
121
122 static uint32_t
123 data_offer_choose_action(struct weston_data_offer *offer)
124 {
125         uint32_t available_actions, preferred_action = 0;
126         uint32_t source_actions, offer_actions;
127
128         if (wl_resource_get_version(offer->resource) >=
129             WL_DATA_OFFER_ACTION_SINCE_VERSION) {
130                 offer_actions = offer->dnd_actions;
131                 preferred_action = offer->preferred_dnd_action;
132         } else {
133                 offer_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
134         }
135
136         if (wl_resource_get_version(offer->source->resource) >=
137             WL_DATA_SOURCE_ACTION_SINCE_VERSION)
138                 source_actions = offer->source->dnd_actions;
139         else
140                 source_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
141
142         available_actions = offer_actions & source_actions;
143
144         if (!available_actions)
145                 return WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
146
147         if (offer->source->seat &&
148             offer->source->compositor_action & available_actions)
149                 return offer->source->compositor_action;
150
151         /* If the dest side has a preferred DnD action, use it */
152         if ((preferred_action & available_actions) != 0)
153                 return preferred_action;
154
155         /* Use the first found action, in bit order */
156         return 1 << (ffs(available_actions) - 1);
157 }
158
159 static void
160 data_offer_update_action(struct weston_data_offer *offer)
161 {
162         uint32_t action;
163
164         if (!offer->source)
165                 return;
166
167         action = data_offer_choose_action(offer);
168
169         if (offer->source->current_dnd_action == action)
170                 return;
171
172         offer->source->current_dnd_action = action;
173
174         if (offer->in_ask)
175                 return;
176
177         if (wl_resource_get_version(offer->source->resource) >=
178             WL_DATA_SOURCE_ACTION_SINCE_VERSION)
179                 wl_data_source_send_action(offer->source->resource, action);
180
181         if (wl_resource_get_version(offer->resource) >=
182             WL_DATA_OFFER_ACTION_SINCE_VERSION)
183                 wl_data_offer_send_action(offer->resource, action);
184 }
185
186 static void
187 data_offer_set_actions(struct wl_client *client,
188                        struct wl_resource *resource,
189                        uint32_t dnd_actions, uint32_t preferred_action)
190 {
191         struct weston_data_offer *offer = wl_resource_get_user_data(resource);
192
193         if (dnd_actions & ~ALL_ACTIONS) {
194                 wl_resource_post_error(offer->resource,
195                                        WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK,
196                                        "invalid action mask %x", dnd_actions);
197                 return;
198         }
199
200         if (preferred_action &&
201             (!(preferred_action & dnd_actions) ||
202              __builtin_popcount(preferred_action) > 1)) {
203                 wl_resource_post_error(offer->resource,
204                                        WL_DATA_OFFER_ERROR_INVALID_ACTION,
205                                        "invalid action %x", preferred_action);
206                 return;
207         }
208
209         offer->dnd_actions = dnd_actions;
210         offer->preferred_dnd_action = preferred_action;
211         data_offer_update_action(offer);
212 }
213
214 static void
215 data_offer_finish(struct wl_client *client, struct wl_resource *resource)
216 {
217         struct weston_data_offer *offer = wl_resource_get_user_data(resource);
218
219         if (!offer->source || offer->source->offer != offer)
220                 return;
221
222         /* Disallow finish while we have a grab driving drag-and-drop, or
223          * if the negotiation is not at the right stage
224          */
225         if (offer->source->seat ||
226             !offer->source->accepted) {
227                 wl_resource_post_error(offer->resource,
228                                        WL_DATA_OFFER_ERROR_INVALID_FINISH,
229                                        "premature finish request");
230                 return;
231         }
232
233         switch (offer->source->current_dnd_action) {
234         case WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE:
235         case WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK:
236                 wl_resource_post_error(offer->resource,
237                                        WL_DATA_OFFER_ERROR_INVALID_OFFER,
238                                        "offer finished with an invalid action");
239                 return;
240         default:
241                 break;
242         }
243
244         data_source_notify_finish(offer->source);
245 }
246
247 static const struct wl_data_offer_interface data_offer_interface = {
248         data_offer_accept,
249         data_offer_receive,
250         data_offer_destroy,
251         data_offer_finish,
252         data_offer_set_actions,
253 };
254
255 static void
256 destroy_data_offer(struct wl_resource *resource)
257 {
258         struct weston_data_offer *offer = wl_resource_get_user_data(resource);
259
260         if (!offer->source)
261                 goto out;
262
263         wl_list_remove(&offer->source_destroy_listener.link);
264
265         if (offer->source->offer != offer)
266                 goto out;
267
268         /* If the drag destination has version < 3, wl_data_offer.finish
269          * won't be called, so do this here as a safety net, because
270          * we still want the version >=3 drag source to be happy.
271          */
272         if (wl_resource_get_version(offer->resource) <
273             WL_DATA_OFFER_ACTION_SINCE_VERSION) {
274                 data_source_notify_finish(offer->source);
275         } else if (offer->source->resource &&
276                    wl_resource_get_version(offer->source->resource) >=
277                    WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
278                 wl_data_source_send_cancelled(offer->source->resource);
279         }
280
281         offer->source->offer = NULL;
282 out:
283         free(offer);
284 }
285
286 static void
287 destroy_offer_data_source(struct wl_listener *listener, void *data)
288 {
289         struct weston_data_offer *offer;
290
291         offer = container_of(listener, struct weston_data_offer,
292                              source_destroy_listener);
293
294         offer->source = NULL;
295 }
296
297 static struct weston_data_offer *
298 weston_data_source_send_offer(struct weston_data_source *source,
299                               struct wl_resource *target)
300 {
301         struct weston_data_offer *offer;
302         char **p;
303
304         offer = malloc(sizeof *offer);
305         if (offer == NULL)
306                 return NULL;
307
308         offer->resource =
309                 wl_resource_create(wl_resource_get_client(target),
310                                    &wl_data_offer_interface,
311                                    wl_resource_get_version(target), 0);
312         if (offer->resource == NULL) {
313                 free(offer);
314                 return NULL;
315         }
316
317         wl_resource_set_implementation(offer->resource, &data_offer_interface,
318                                        offer, destroy_data_offer);
319
320         offer->in_ask = false;
321         offer->dnd_actions = 0;
322         offer->preferred_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
323         offer->source = source;
324         offer->source_destroy_listener.notify = destroy_offer_data_source;
325         wl_signal_add(&source->destroy_signal,
326                       &offer->source_destroy_listener);
327
328         wl_data_device_send_data_offer(target, offer->resource);
329
330         wl_array_for_each(p, &source->mime_types)
331                 wl_data_offer_send_offer(offer->resource, *p);
332
333         source->offer = offer;
334         source->accepted = false;
335
336         return offer;
337 }
338
339 static void
340 data_source_offer(struct wl_client *client,
341                   struct wl_resource *resource,
342                   const char *type)
343 {
344         struct weston_data_source *source =
345                 wl_resource_get_user_data(resource);
346         char **p;
347
348         p = wl_array_add(&source->mime_types, sizeof *p);
349         if (p)
350                 *p = strdup(type);
351         if (!p || !*p)
352                 wl_resource_post_no_memory(resource);
353 }
354
355 static void
356 data_source_destroy(struct wl_client *client, struct wl_resource *resource)
357 {
358         wl_resource_destroy(resource);
359 }
360
361 static void
362 data_source_set_actions(struct wl_client *client,
363                         struct wl_resource *resource,
364                         uint32_t dnd_actions)
365 {
366         struct weston_data_source *source =
367                 wl_resource_get_user_data(resource);
368
369         if (source->actions_set) {
370                 wl_resource_post_error(source->resource,
371                                        WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
372                                        "cannot set actions more than once");
373                 return;
374         }
375
376         if (dnd_actions & ~ALL_ACTIONS) {
377                 wl_resource_post_error(source->resource,
378                                        WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
379                                        "invalid action mask %x", dnd_actions);
380                 return;
381         }
382
383         if (source->seat) {
384                 wl_resource_post_error(source->resource,
385                                        WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK,
386                                        "invalid action change after "
387                                        "wl_data_device.start_drag");
388                 return;
389         }
390
391         source->dnd_actions = dnd_actions;
392         source->actions_set = true;
393 }
394
395 static struct wl_data_source_interface data_source_interface = {
396         data_source_offer,
397         data_source_destroy,
398         data_source_set_actions
399 };
400
401 static void
402 drag_surface_configure(struct weston_drag *drag,
403                        struct weston_pointer *pointer,
404                        struct weston_touch *touch,
405                        struct weston_surface *es,
406                        int32_t sx, int32_t sy)
407 {
408         struct weston_layer_entry *list;
409         float fx, fy;
410
411         assert((pointer != NULL && touch == NULL) ||
412                         (pointer == NULL && touch != NULL));
413
414         if (!weston_surface_is_mapped(es) && es->buffer_ref.buffer) {
415                 if (pointer && pointer->sprite &&
416                         weston_view_is_mapped(pointer->sprite))
417                         list = &pointer->sprite->layer_link;
418                 else
419                         list = &es->compositor->cursor_layer.view_list;
420
421                 weston_layer_entry_remove(&drag->icon->layer_link);
422                 weston_layer_entry_insert(list, &drag->icon->layer_link);
423                 weston_view_update_transform(drag->icon);
424                 pixman_region32_clear(&es->pending.input);
425                 es->is_mapped = true;
426                 drag->icon->is_mapped = true;
427         }
428
429         drag->dx += sx;
430         drag->dy += sy;
431
432         /* init to 0 for avoiding a compile warning */
433         fx = fy = 0;
434         if (pointer) {
435                 fx = wl_fixed_to_double(pointer->x) + drag->dx;
436                 fy = wl_fixed_to_double(pointer->y) + drag->dy;
437         } else if (touch) {
438                 fx = wl_fixed_to_double(touch->grab_x) + drag->dx;
439                 fy = wl_fixed_to_double(touch->grab_y) + drag->dy;
440         }
441         weston_view_set_position(drag->icon, fx, fy);
442 }
443
444 static int
445 pointer_drag_surface_get_label(struct weston_surface *surface,
446                                char *buf, size_t len)
447 {
448         return snprintf(buf, len, "pointer drag icon");
449 }
450
451 static void
452 pointer_drag_surface_committed(struct weston_surface *es,
453                                int32_t sx, int32_t sy)
454 {
455         struct weston_pointer_drag *drag = es->committed_private;
456         struct weston_pointer *pointer = drag->grab.pointer;
457
458         assert(es->committed == pointer_drag_surface_committed);
459
460         drag_surface_configure(&drag->base, pointer, NULL, es, sx, sy);
461 }
462
463 static int
464 touch_drag_surface_get_label(struct weston_surface *surface,
465                              char *buf, size_t len)
466 {
467         return snprintf(buf, len, "touch drag icon");
468 }
469
470 static void
471 touch_drag_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy)
472 {
473         struct weston_touch_drag *drag = es->committed_private;
474         struct weston_touch *touch = drag->grab.touch;
475
476         assert(es->committed == touch_drag_surface_committed);
477
478         drag_surface_configure(&drag->base, NULL, touch, es, sx, sy);
479 }
480
481 static void
482 destroy_drag_focus(struct wl_listener *listener, void *data)
483 {
484         struct weston_drag *drag =
485                 container_of(listener, struct weston_drag, focus_listener);
486
487         drag->focus_resource = NULL;
488 }
489
490 static void
491 weston_drag_set_focus(struct weston_drag *drag,
492                         struct weston_seat *seat,
493                         struct weston_view *view,
494                         wl_fixed_t sx, wl_fixed_t sy)
495 {
496         struct wl_resource *resource, *offer_resource = NULL;
497         struct wl_display *display = seat->compositor->wl_display;
498         struct weston_data_offer *offer;
499         uint32_t serial;
500
501         if (drag->focus && view && drag->focus->surface == view->surface) {
502                 drag->focus = view;
503                 return;
504         }
505
506         if (drag->focus_resource) {
507                 wl_data_device_send_leave(drag->focus_resource);
508                 wl_list_remove(&drag->focus_listener.link);
509                 drag->focus_resource = NULL;
510                 drag->focus = NULL;
511         }
512
513         if (!view || !view->surface->resource)
514                 return;
515
516         if (!drag->data_source &&
517             wl_resource_get_client(view->surface->resource) != drag->client)
518                 return;
519
520         if (drag->data_source &&
521             drag->data_source->offer) {
522                 /* Unlink the offer from the source */
523                 offer = drag->data_source->offer;
524                 offer->source = NULL;
525                 drag->data_source->offer = NULL;
526                 wl_list_remove(&offer->source_destroy_listener.link);
527         }
528
529         resource = wl_resource_find_for_client(&seat->drag_resource_list,
530                                                wl_resource_get_client(view->surface->resource));
531         if (!resource)
532                 return;
533
534         serial = wl_display_next_serial(display);
535
536         if (drag->data_source) {
537                 drag->data_source->accepted = false;
538                 offer = weston_data_source_send_offer(drag->data_source, resource);
539                 if (offer == NULL)
540                         return;
541
542                 data_offer_update_action(offer);
543
544                 offer_resource = offer->resource;
545                 if (wl_resource_get_version (offer_resource) >=
546                     WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION) {
547                         wl_data_offer_send_source_actions (offer_resource,
548                                                            drag->data_source->dnd_actions);
549                 }
550         }
551
552         wl_data_device_send_enter(resource, serial, view->surface->resource,
553                                   sx, sy, offer_resource);
554
555         drag->focus = view;
556         drag->focus_listener.notify = destroy_drag_focus;
557         wl_resource_add_destroy_listener(resource, &drag->focus_listener);
558         drag->focus_resource = resource;
559 }
560
561 static void
562 drag_grab_focus(struct weston_pointer_grab *grab)
563 {
564         struct weston_pointer_drag *drag =
565                 container_of(grab, struct weston_pointer_drag, grab);
566         struct weston_pointer *pointer = grab->pointer;
567         struct weston_view *view;
568         wl_fixed_t sx, sy;
569
570         view = weston_compositor_pick_view(pointer->seat->compositor,
571                                            pointer->x, pointer->y,
572                                            &sx, &sy);
573         if (drag->base.focus != view)
574                 weston_drag_set_focus(&drag->base, pointer->seat, view, sx, sy);
575 }
576
577 static void
578 drag_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
579                  struct weston_pointer_motion_event *event)
580 {
581         struct weston_pointer_drag *drag =
582                 container_of(grab, struct weston_pointer_drag, grab);
583         struct weston_pointer *pointer = drag->grab.pointer;
584         float fx, fy;
585         wl_fixed_t sx, sy;
586
587         weston_pointer_move(pointer, event);
588
589         if (drag->base.icon) {
590                 fx = wl_fixed_to_double(pointer->x) + drag->base.dx;
591                 fy = wl_fixed_to_double(pointer->y) + drag->base.dy;
592                 weston_view_set_position(drag->base.icon, fx, fy);
593                 weston_view_schedule_repaint(drag->base.icon);
594         }
595
596         if (drag->base.focus_resource) {
597                 weston_view_from_global_fixed(drag->base.focus,
598                                               pointer->x, pointer->y,
599                                               &sx, &sy);
600
601                 wl_data_device_send_motion(drag->base.focus_resource, time, sx, sy);
602         }
603 }
604
605 static void
606 data_device_end_drag_grab(struct weston_drag *drag,
607                 struct weston_seat *seat)
608 {
609         if (drag->icon) {
610                 if (weston_view_is_mapped(drag->icon))
611                         weston_view_unmap(drag->icon);
612
613                 drag->icon->surface->committed = NULL;
614                 weston_surface_set_label_func(drag->icon->surface, NULL);
615                 pixman_region32_clear(&drag->icon->surface->pending.input);
616                 wl_list_remove(&drag->icon_destroy_listener.link);
617                 weston_view_destroy(drag->icon);
618         }
619
620         weston_drag_set_focus(drag, seat, NULL, 0, 0);
621 }
622
623 static void
624 data_device_end_pointer_drag_grab(struct weston_pointer_drag *drag)
625 {
626         struct weston_pointer *pointer = drag->grab.pointer;
627         struct weston_keyboard *keyboard = drag->base.keyboard_grab.keyboard;
628
629         data_device_end_drag_grab(&drag->base, pointer->seat);
630         weston_pointer_end_grab(pointer);
631         weston_keyboard_end_grab(keyboard);
632         free(drag);
633 }
634
635 static void
636 drag_grab_button(struct weston_pointer_grab *grab,
637                  uint32_t time, uint32_t button, uint32_t state_w)
638 {
639         struct weston_pointer_drag *drag =
640                 container_of(grab, struct weston_pointer_drag, grab);
641         struct weston_pointer *pointer = drag->grab.pointer;
642         enum wl_pointer_button_state state = state_w;
643         struct weston_data_source *data_source = drag->base.data_source;
644
645         if (data_source &&
646             pointer->grab_button == button &&
647             state == WL_POINTER_BUTTON_STATE_RELEASED) {
648                 if (drag->base.focus_resource &&
649                     data_source->accepted &&
650                     data_source->current_dnd_action) {
651                         wl_data_device_send_drop(drag->base.focus_resource);
652
653                         if (wl_resource_get_version(data_source->resource) >=
654                             WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION)
655                                 wl_data_source_send_dnd_drop_performed(data_source->resource);
656
657                         data_source->offer->in_ask =
658                                 data_source->current_dnd_action ==
659                                 WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK;
660
661                         data_source->seat = NULL;
662                 } else if (wl_resource_get_version(data_source->resource) >=
663                            WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) {
664                         wl_data_source_send_cancelled(data_source->resource);
665                 }
666         }
667
668         if (pointer->button_count == 0 &&
669             state == WL_POINTER_BUTTON_STATE_RELEASED) {
670                 if (drag->base.data_source)
671                         wl_list_remove(&drag->base.data_source_listener.link);
672                 data_device_end_pointer_drag_grab(drag);
673         }
674 }
675
676 static void
677 drag_grab_axis(struct weston_pointer_grab *grab,
678                uint32_t time, struct weston_pointer_axis_event *event)
679 {
680 }
681
682 static void
683 drag_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source)
684 {
685 }
686
687 static void
688 drag_grab_frame(struct weston_pointer_grab *grab)
689 {
690 }
691
692 static void
693 drag_grab_cancel(struct weston_pointer_grab *grab)
694 {
695         struct weston_pointer_drag *drag =
696                 container_of(grab, struct weston_pointer_drag, grab);
697
698         if (drag->base.data_source)
699                 wl_list_remove(&drag->base.data_source_listener.link);
700
701         data_device_end_pointer_drag_grab(drag);
702 }
703
704 static const struct weston_pointer_grab_interface pointer_drag_grab_interface = {
705         drag_grab_focus,
706         drag_grab_motion,
707         drag_grab_button,
708         drag_grab_axis,
709         drag_grab_axis_source,
710         drag_grab_frame,
711         drag_grab_cancel,
712 };
713
714 static void
715 drag_grab_touch_down(struct weston_touch_grab *grab, uint32_t time,
716                 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
717 {
718 }
719
720 static void
721 data_device_end_touch_drag_grab(struct weston_touch_drag *drag)
722 {
723         struct weston_touch *touch = drag->grab.touch;
724         struct weston_keyboard *keyboard = drag->base.keyboard_grab.keyboard;
725
726         data_device_end_drag_grab(&drag->base, touch->seat);
727         weston_touch_end_grab(touch);
728         weston_keyboard_end_grab(keyboard);
729         free(drag);
730 }
731
732 static void
733 drag_grab_touch_up(struct weston_touch_grab *grab,
734                 uint32_t time, int touch_id)
735 {
736         struct weston_touch_drag *touch_drag =
737                 container_of(grab, struct weston_touch_drag, grab);
738         struct weston_touch *touch = grab->touch;
739
740         if (touch_id != touch->grab_touch_id)
741                 return;
742
743         if (touch_drag->base.focus_resource)
744                 wl_data_device_send_drop(touch_drag->base.focus_resource);
745         if (touch_drag->base.data_source)
746                 wl_list_remove(&touch_drag->base.data_source_listener.link);
747         data_device_end_touch_drag_grab(touch_drag);
748 }
749
750 static void
751 drag_grab_touch_focus(struct weston_touch_drag *drag)
752 {
753         struct weston_touch *touch = drag->grab.touch;
754         struct weston_view *view;
755         wl_fixed_t view_x, view_y;
756
757         view = weston_compositor_pick_view(touch->seat->compositor,
758                                 touch->grab_x, touch->grab_y,
759                                 &view_x, &view_y);
760         if (drag->base.focus != view)
761                 weston_drag_set_focus(&drag->base, touch->seat,
762                                 view, view_x, view_y);
763 }
764
765 static void
766 drag_grab_touch_motion(struct weston_touch_grab *grab, uint32_t time,
767                 int touch_id, wl_fixed_t x, wl_fixed_t y)
768 {
769         struct weston_touch_drag *touch_drag =
770                 container_of(grab, struct weston_touch_drag, grab);
771         struct weston_touch *touch = grab->touch;
772         wl_fixed_t view_x, view_y;
773         float fx, fy;
774
775         if (touch_id != touch->grab_touch_id)
776                 return;
777
778         drag_grab_touch_focus(touch_drag);
779         if (touch_drag->base.icon) {
780                 fx = wl_fixed_to_double(touch->grab_x) + touch_drag->base.dx;
781                 fy = wl_fixed_to_double(touch->grab_y) + touch_drag->base.dy;
782                 weston_view_set_position(touch_drag->base.icon, fx, fy);
783                 weston_view_schedule_repaint(touch_drag->base.icon);
784         }
785
786         if (touch_drag->base.focus_resource) {
787                 weston_view_from_global_fixed(touch_drag->base.focus,
788                                         touch->grab_x, touch->grab_y,
789                                         &view_x, &view_y);
790                 wl_data_device_send_motion(touch_drag->base.focus_resource, time,
791                                         view_x, view_y);
792         }
793 }
794
795 static void
796 drag_grab_touch_frame(struct weston_touch_grab *grab)
797 {
798 }
799
800 static void
801 drag_grab_touch_cancel(struct weston_touch_grab *grab)
802 {
803         struct weston_touch_drag *touch_drag =
804                 container_of(grab, struct weston_touch_drag, grab);
805
806         if (touch_drag->base.data_source)
807                 wl_list_remove(&touch_drag->base.data_source_listener.link);
808         data_device_end_touch_drag_grab(touch_drag);
809 }
810
811 static const struct weston_touch_grab_interface touch_drag_grab_interface = {
812         drag_grab_touch_down,
813         drag_grab_touch_up,
814         drag_grab_touch_motion,
815         drag_grab_touch_frame,
816         drag_grab_touch_cancel
817 };
818
819 static void
820 drag_grab_keyboard_key(struct weston_keyboard_grab *grab,
821                        uint32_t time, uint32_t key, uint32_t state)
822 {
823 }
824
825 static void
826 drag_grab_keyboard_modifiers(struct weston_keyboard_grab *grab,
827                              uint32_t serial, uint32_t mods_depressed,
828                              uint32_t mods_latched,
829                              uint32_t mods_locked, uint32_t group)
830 {
831         struct weston_keyboard *keyboard = grab->keyboard;
832         struct weston_drag *drag =
833                 container_of(grab, struct weston_drag, keyboard_grab);
834         uint32_t compositor_action;
835
836         if (mods_depressed & (1 << keyboard->xkb_info->shift_mod))
837                 compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
838         else if (mods_depressed & (1 << keyboard->xkb_info->ctrl_mod))
839                 compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
840         else
841                 compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
842
843         drag->data_source->compositor_action = compositor_action;
844
845         if (drag->data_source->offer)
846                 data_offer_update_action(drag->data_source->offer);
847 }
848
849 static void
850 drag_grab_keyboard_cancel(struct weston_keyboard_grab *grab)
851 {
852         struct weston_drag *drag =
853                 container_of(grab, struct weston_drag, keyboard_grab);
854         struct weston_pointer *pointer = grab->keyboard->seat->pointer_state;
855         struct weston_touch *touch = grab->keyboard->seat->touch_state;
856
857         if (pointer && pointer->grab->interface == &pointer_drag_grab_interface) {
858                 struct weston_touch_drag *touch_drag =
859                         (struct weston_touch_drag *) drag;
860                 drag_grab_touch_cancel(&touch_drag->grab);
861         } else if (touch && touch->grab->interface == &touch_drag_grab_interface) {
862                 struct weston_pointer_drag *pointer_drag =
863                         (struct weston_pointer_drag *) drag;
864                 drag_grab_cancel(&pointer_drag->grab);
865         }
866 }
867
868 static const struct weston_keyboard_grab_interface keyboard_drag_grab_interface = {
869         drag_grab_keyboard_key,
870         drag_grab_keyboard_modifiers,
871         drag_grab_keyboard_cancel
872 };
873
874 static void
875 destroy_pointer_data_device_source(struct wl_listener *listener, void *data)
876 {
877         struct weston_pointer_drag *drag = container_of(listener,
878                         struct weston_pointer_drag, base.data_source_listener);
879
880         data_device_end_pointer_drag_grab(drag);
881 }
882
883 static void
884 handle_drag_icon_destroy(struct wl_listener *listener, void *data)
885 {
886         struct weston_drag *drag = container_of(listener, struct weston_drag,
887                                                 icon_destroy_listener);
888
889         drag->icon = NULL;
890 }
891
892 WL_EXPORT int
893 weston_pointer_start_drag(struct weston_pointer *pointer,
894                        struct weston_data_source *source,
895                        struct weston_surface *icon,
896                        struct wl_client *client)
897 {
898         struct weston_pointer_drag *drag;
899         struct weston_keyboard *keyboard =
900                 weston_seat_get_keyboard(pointer->seat);
901
902         drag = zalloc(sizeof *drag);
903         if (drag == NULL)
904                 return -1;
905
906         drag->grab.interface = &pointer_drag_grab_interface;
907         drag->base.keyboard_grab.interface = &keyboard_drag_grab_interface;
908         drag->base.client = client;
909         drag->base.data_source = source;
910
911         if (icon) {
912                 drag->base.icon = weston_view_create(icon);
913                 if (drag->base.icon == NULL) {
914                         free(drag);
915                         return -1;
916                 }
917
918                 drag->base.icon_destroy_listener.notify = handle_drag_icon_destroy;
919                 wl_signal_add(&icon->destroy_signal,
920                               &drag->base.icon_destroy_listener);
921
922                 icon->committed = pointer_drag_surface_committed;
923                 icon->committed_private = drag;
924                 weston_surface_set_label_func(icon,
925                                         pointer_drag_surface_get_label);
926         } else {
927                 drag->base.icon = NULL;
928         }
929
930         if (source) {
931                 drag->base.data_source_listener.notify = destroy_pointer_data_device_source;
932                 wl_signal_add(&source->destroy_signal,
933                               &drag->base.data_source_listener);
934         }
935
936         weston_pointer_clear_focus(pointer);
937         weston_keyboard_set_focus(keyboard, NULL);
938
939         weston_pointer_start_grab(pointer, &drag->grab);
940         weston_keyboard_start_grab(keyboard, &drag->base.keyboard_grab);
941
942         return 0;
943 }
944
945 static void
946 destroy_touch_data_device_source(struct wl_listener *listener, void *data)
947 {
948         struct weston_touch_drag *drag = container_of(listener,
949                         struct weston_touch_drag, base.data_source_listener);
950
951         data_device_end_touch_drag_grab(drag);
952 }
953
954 WL_EXPORT int
955 weston_touch_start_drag(struct weston_touch *touch,
956                        struct weston_data_source *source,
957                        struct weston_surface *icon,
958                        struct wl_client *client)
959 {
960         struct weston_touch_drag *drag;
961         struct weston_keyboard *keyboard =
962                 weston_seat_get_keyboard(touch->seat);
963
964         drag = zalloc(sizeof *drag);
965         if (drag == NULL)
966                 return -1;
967
968         drag->grab.interface = &touch_drag_grab_interface;
969         drag->base.client = client;
970         drag->base.data_source = source;
971
972         if (icon) {
973                 drag->base.icon = weston_view_create(icon);
974                 if (drag->base.icon == NULL) {
975                         free(drag);
976                         return -1;
977                 }
978
979                 drag->base.icon_destroy_listener.notify = handle_drag_icon_destroy;
980                 wl_signal_add(&icon->destroy_signal,
981                               &drag->base.icon_destroy_listener);
982
983                 icon->committed = touch_drag_surface_committed;
984                 icon->committed_private = drag;
985                 weston_surface_set_label_func(icon,
986                                         touch_drag_surface_get_label);
987         } else {
988                 drag->base.icon = NULL;
989         }
990
991         if (source) {
992                 drag->base.data_source_listener.notify = destroy_touch_data_device_source;
993                 wl_signal_add(&source->destroy_signal,
994                               &drag->base.data_source_listener);
995         }
996
997         weston_keyboard_set_focus(keyboard, NULL);
998
999         weston_touch_start_grab(touch, &drag->grab);
1000         weston_keyboard_start_grab(keyboard, &drag->base.keyboard_grab);
1001
1002         drag_grab_touch_focus(drag);
1003
1004         return 0;
1005 }
1006
1007 static void
1008 data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
1009                        struct wl_resource *source_resource,
1010                        struct wl_resource *origin_resource,
1011                        struct wl_resource *icon_resource, uint32_t serial)
1012 {
1013         struct weston_seat *seat = wl_resource_get_user_data(resource);
1014         struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1015         struct weston_touch *touch = weston_seat_get_touch(seat);
1016         struct weston_surface *origin = wl_resource_get_user_data(origin_resource);
1017         struct weston_data_source *source = NULL;
1018         struct weston_surface *icon = NULL;
1019         int is_pointer_grab, is_touch_grab;
1020         int32_t ret = 0;
1021
1022         is_pointer_grab = pointer &&
1023                           pointer->button_count == 1 &&
1024                           pointer->grab_serial == serial &&
1025                           pointer->focus &&
1026                           pointer->focus->surface == origin;
1027
1028         is_touch_grab = touch &&
1029                         touch->num_tp == 1 &&
1030                         touch->grab_serial == serial &&
1031                         touch->focus &&
1032                         touch->focus->surface == origin;
1033
1034         if (!is_pointer_grab && !is_touch_grab)
1035                 return;
1036
1037         /* FIXME: Check that the data source type array isn't empty. */
1038
1039         if (source_resource)
1040                 source = wl_resource_get_user_data(source_resource);
1041         if (icon_resource)
1042                 icon = wl_resource_get_user_data(icon_resource);
1043
1044         if (icon) {
1045                 if (weston_surface_set_role(icon, "wl_data_device-icon",
1046                                             resource,
1047                                             WL_DATA_DEVICE_ERROR_ROLE) < 0)
1048                         return;
1049         }
1050
1051         if (is_pointer_grab)
1052                 ret = weston_pointer_start_drag(pointer, source, icon, client);
1053         else if (is_touch_grab)
1054                 ret = weston_touch_start_drag(touch, source, icon, client);
1055
1056         if (ret < 0)
1057                 wl_resource_post_no_memory(resource);
1058         else
1059                 source->seat = seat;
1060 }
1061
1062 static void
1063 destroy_selection_data_source(struct wl_listener *listener, void *data)
1064 {
1065         struct weston_seat *seat = container_of(listener, struct weston_seat,
1066                                                 selection_data_source_listener);
1067         struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1068         struct wl_resource *data_device;
1069         struct weston_surface *focus = NULL;
1070
1071         seat->selection_data_source = NULL;
1072
1073         if (keyboard)
1074                 focus = keyboard->focus;
1075         if (focus && focus->resource) {
1076                 data_device = wl_resource_find_for_client(&seat->drag_resource_list,
1077                                                           wl_resource_get_client(focus->resource));
1078                 if (data_device)
1079                         wl_data_device_send_selection(data_device, NULL);
1080         }
1081
1082         wl_signal_emit(&seat->selection_signal, seat);
1083 }
1084
1085 /** \brief Send the selection to the specified client
1086  *
1087  * This function creates a new wl_data_offer if there is a wl_data_source
1088  * currently set as the selection and sends it to the specified client,
1089  * followed by the wl_data_device.selection() event.
1090  * If there is no current selection the wl_data_device.selection() event
1091  * will carry a NULL wl_data_offer.
1092  *
1093  * If the client does not have a wl_data_device for the specified seat
1094  * nothing will be done.
1095  *
1096  * \param seat The seat owning the wl_data_device used to send the events.
1097  * \param client The client to which to send the selection.
1098  */
1099 WL_EXPORT void
1100 weston_seat_send_selection(struct weston_seat *seat, struct wl_client *client)
1101 {
1102         struct weston_data_offer *offer;
1103         struct wl_resource *data_device;
1104
1105         wl_resource_for_each(data_device, &seat->drag_resource_list) {
1106                 if (wl_resource_get_client(data_device) != client)
1107                     continue;
1108
1109                 if (seat->selection_data_source) {
1110                         offer = weston_data_source_send_offer(seat->selection_data_source,
1111                                                               data_device);
1112                         wl_data_device_send_selection(data_device, offer->resource);
1113                 } else {
1114                         wl_data_device_send_selection(data_device, NULL);
1115                 }
1116         }
1117 }
1118
1119 WL_EXPORT void
1120 weston_seat_set_selection(struct weston_seat *seat,
1121                           struct weston_data_source *source, uint32_t serial)
1122 {
1123         struct weston_surface *focus = NULL;
1124         struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1125
1126         if (seat->selection_data_source &&
1127             seat->selection_serial - serial < UINT32_MAX / 2)
1128                 return;
1129
1130         if (seat->selection_data_source) {
1131                 seat->selection_data_source->cancel(seat->selection_data_source);
1132                 wl_list_remove(&seat->selection_data_source_listener.link);
1133                 seat->selection_data_source = NULL;
1134         }
1135
1136         seat->selection_data_source = source;
1137         seat->selection_serial = serial;
1138
1139         if (keyboard)
1140                 focus = keyboard->focus;
1141         if (focus && focus->resource) {
1142                 weston_seat_send_selection(seat, wl_resource_get_client(focus->resource));
1143         }
1144
1145         wl_signal_emit(&seat->selection_signal, seat);
1146
1147         if (source) {
1148                 seat->selection_data_source_listener.notify =
1149                         destroy_selection_data_source;
1150                 wl_signal_add(&source->destroy_signal,
1151                               &seat->selection_data_source_listener);
1152         }
1153 }
1154
1155 static void
1156 data_device_set_selection(struct wl_client *client,
1157                           struct wl_resource *resource,
1158                           struct wl_resource *source_resource, uint32_t serial)
1159 {
1160         struct weston_data_source *source;
1161
1162         if (!source_resource)
1163                 return;
1164
1165         source = wl_resource_get_user_data(source_resource);
1166
1167         if (source->actions_set) {
1168                 wl_resource_post_error(source_resource,
1169                                        WL_DATA_SOURCE_ERROR_INVALID_SOURCE,
1170                                        "cannot set drag-and-drop source as selection");
1171                 return;
1172         }
1173
1174         /* FIXME: Store serial and check against incoming serial here. */
1175         weston_seat_set_selection(wl_resource_get_user_data(resource),
1176                                   source, serial);
1177 }
1178 static void
1179 data_device_release(struct wl_client *client, struct wl_resource *resource)
1180 {
1181         wl_resource_destroy(resource);
1182 }
1183
1184 static const struct wl_data_device_interface data_device_interface = {
1185         data_device_start_drag,
1186         data_device_set_selection,
1187         data_device_release
1188 };
1189
1190 static void
1191 destroy_data_source(struct wl_resource *resource)
1192 {
1193         struct weston_data_source *source =
1194                 wl_resource_get_user_data(resource);
1195         char **p;
1196
1197         wl_signal_emit(&source->destroy_signal, source);
1198
1199         wl_array_for_each(p, &source->mime_types)
1200                 free(*p);
1201
1202         wl_array_release(&source->mime_types);
1203
1204         free(source);
1205 }
1206
1207 static void
1208 client_source_accept(struct weston_data_source *source,
1209                      uint32_t time, const char *mime_type)
1210 {
1211         wl_data_source_send_target(source->resource, mime_type);
1212 }
1213
1214 static void
1215 client_source_send(struct weston_data_source *source,
1216                    const char *mime_type, int32_t fd)
1217 {
1218         wl_data_source_send_send(source->resource, mime_type, fd);
1219         close(fd);
1220 }
1221
1222 static void
1223 client_source_cancel(struct weston_data_source *source)
1224 {
1225         wl_data_source_send_cancelled(source->resource);
1226 }
1227
1228 static void
1229 create_data_source(struct wl_client *client,
1230                    struct wl_resource *resource, uint32_t id)
1231 {
1232         struct weston_data_source *source;
1233
1234         source = malloc(sizeof *source);
1235         if (source == NULL) {
1236                 wl_resource_post_no_memory(resource);
1237                 return;
1238         }
1239
1240         source->resource =
1241                 wl_resource_create(client, &wl_data_source_interface,
1242                                    wl_resource_get_version(resource), id);
1243         if (source->resource == NULL) {
1244                 free(source);
1245                 wl_resource_post_no_memory(resource);
1246                 return;
1247         }
1248
1249         wl_signal_init(&source->destroy_signal);
1250         source->accept = client_source_accept;
1251         source->send = client_source_send;
1252         source->cancel = client_source_cancel;
1253         source->offer = NULL;
1254         source->accepted = false;
1255         source->seat = NULL;
1256         source->actions_set = false;
1257         source->dnd_actions = 0;
1258         source->current_dnd_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
1259         source->compositor_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
1260
1261         wl_array_init(&source->mime_types);
1262
1263         wl_resource_set_implementation(source->resource, &data_source_interface,
1264                                        source, destroy_data_source);
1265 }
1266
1267 static void unbind_data_device(struct wl_resource *resource)
1268 {
1269         wl_list_remove(wl_resource_get_link(resource));
1270 }
1271
1272 static void
1273 get_data_device(struct wl_client *client,
1274                 struct wl_resource *manager_resource,
1275                 uint32_t id, struct wl_resource *seat_resource)
1276 {
1277         struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
1278         struct wl_resource *resource;
1279
1280         resource = wl_resource_create(client,
1281                                       &wl_data_device_interface,
1282                                       wl_resource_get_version(manager_resource),
1283                                       id);
1284         if (resource == NULL) {
1285                 wl_resource_post_no_memory(manager_resource);
1286                 return;
1287         }
1288
1289         wl_list_insert(&seat->drag_resource_list,
1290                        wl_resource_get_link(resource));
1291         wl_resource_set_implementation(resource, &data_device_interface,
1292                                        seat, unbind_data_device);
1293 }
1294
1295 static const struct wl_data_device_manager_interface manager_interface = {
1296         create_data_source,
1297         get_data_device
1298 };
1299
1300 static void
1301 bind_manager(struct wl_client *client,
1302              void *data, uint32_t version, uint32_t id)
1303 {
1304         struct wl_resource *resource;
1305
1306         resource = wl_resource_create(client,
1307                                       &wl_data_device_manager_interface,
1308                                       version, id);
1309         if (resource == NULL) {
1310                 wl_client_post_no_memory(client);
1311                 return;
1312         }
1313
1314         wl_resource_set_implementation(resource, &manager_interface,
1315                                        NULL, NULL);
1316 }
1317
1318 WL_EXPORT void
1319 wl_data_device_set_keyboard_focus(struct weston_seat *seat)
1320 {
1321         struct weston_surface *focus;
1322         struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1323
1324         if (!keyboard)
1325                 return;
1326
1327         focus = keyboard->focus;
1328         if (!focus || !focus->resource)
1329                 return;
1330
1331         weston_seat_send_selection(seat, wl_resource_get_client(focus->resource));
1332 }
1333
1334 WL_EXPORT int
1335 wl_data_device_manager_init(struct wl_display *display)
1336 {
1337         if (wl_global_create(display,
1338                              &wl_data_device_manager_interface, 3,
1339                              NULL, bind_manager) == NULL)
1340                 return -1;
1341
1342         return 0;
1343 }