input: Rename wl_pointer to weston_pointer
[platform/upstream/weston.git] / src / data-device.c
1 /*
2  * Copyright © 2011 Kristian Høgsberg
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <stdio.h>
27
28 #include "compositor.h"
29
30 static void
31 data_offer_accept(struct wl_client *client, struct wl_resource *resource,
32                   uint32_t serial, const char *mime_type)
33 {
34         struct wl_data_offer *offer = resource->data;
35
36         /* FIXME: Check that client is currently focused by the input
37          * device that is currently dragging this data source.  Should
38          * this be a wl_data_device request? */
39
40         if (offer->source)
41                 offer->source->accept(offer->source, serial, mime_type);
42 }
43
44 static void
45 data_offer_receive(struct wl_client *client, struct wl_resource *resource,
46                    const char *mime_type, int32_t fd)
47 {
48         struct wl_data_offer *offer = resource->data;
49
50         if (offer->source)
51                 offer->source->send(offer->source, mime_type, fd);
52         else
53                 close(fd);
54 }
55
56 static void
57 data_offer_destroy(struct wl_client *client, struct wl_resource *resource)
58 {
59         wl_resource_destroy(resource);
60 }
61
62 static const struct wl_data_offer_interface data_offer_interface = {
63         data_offer_accept,
64         data_offer_receive,
65         data_offer_destroy,
66 };
67
68 static void
69 destroy_data_offer(struct wl_resource *resource)
70 {
71         struct wl_data_offer *offer = resource->data;
72
73         if (offer->source)
74                 wl_list_remove(&offer->source_destroy_listener.link);
75         free(offer);
76 }
77
78 static void
79 destroy_offer_data_source(struct wl_listener *listener, void *data)
80 {
81         struct wl_data_offer *offer;
82
83         offer = container_of(listener, struct wl_data_offer,
84                              source_destroy_listener);
85
86         offer->source = NULL;
87 }
88
89 static struct wl_resource *
90 wl_data_source_send_offer(struct wl_data_source *source,
91                           struct wl_resource *target)
92 {
93         struct wl_data_offer *offer;
94         char **p;
95
96         offer = malloc(sizeof *offer);
97         if (offer == NULL)
98                 return NULL;
99
100         wl_resource_init(&offer->resource, &wl_data_offer_interface,
101                          &data_offer_interface, 0, offer);
102         offer->resource.destroy = destroy_data_offer;
103
104         offer->source = source;
105         offer->source_destroy_listener.notify = destroy_offer_data_source;
106         wl_signal_add(&source->resource.destroy_signal,
107                       &offer->source_destroy_listener);
108
109         wl_client_add_resource(target->client, &offer->resource);
110
111         wl_data_device_send_data_offer(target, &offer->resource);
112
113         wl_array_for_each(p, &source->mime_types)
114                 wl_data_offer_send_offer(&offer->resource, *p);
115
116         return &offer->resource;
117 }
118
119 static void
120 data_source_offer(struct wl_client *client,
121                   struct wl_resource *resource,
122                   const char *type)
123 {
124         struct wl_data_source *source = resource->data;
125         char **p;
126
127         p = wl_array_add(&source->mime_types, sizeof *p);
128         if (p)
129                 *p = strdup(type);
130         if (!p || !*p)
131                 wl_resource_post_no_memory(resource);
132 }
133
134 static void
135 data_source_destroy(struct wl_client *client, struct wl_resource *resource)
136 {
137         wl_resource_destroy(resource);
138 }
139
140 static struct wl_data_source_interface data_source_interface = {
141         data_source_offer,
142         data_source_destroy
143 };
144
145 static struct wl_resource *
146 find_resource(struct wl_list *list, struct wl_client *client)
147 {
148         struct wl_resource *r;
149
150         wl_list_for_each(r, list, link) {
151                 if (r->client == client)
152                         return r;
153         }
154
155         return NULL;
156 }
157
158 static void
159 destroy_drag_focus(struct wl_listener *listener, void *data)
160 {
161         struct wl_seat *seat =
162                 container_of(listener, struct wl_seat, drag_focus_listener);
163
164         seat->drag_focus_resource = NULL;
165 }
166
167 static void
168 drag_grab_focus(struct weston_pointer_grab *grab,
169                 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
170 {
171         struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
172         struct wl_resource *resource, *offer = NULL;
173         struct wl_display *display;
174         uint32_t serial;
175
176         if (seat->drag_focus_resource) {
177                 wl_data_device_send_leave(seat->drag_focus_resource);
178                 wl_list_remove(&seat->drag_focus_listener.link);
179                 seat->drag_focus_resource = NULL;
180                 seat->drag_focus = NULL;
181         }
182
183         if (!surface)
184                 return;
185
186         if (!seat->drag_data_source &&
187             surface->resource.client != seat->drag_client)
188                 return;
189
190         resource = find_resource(&seat->drag_resource_list,
191                                  surface->resource.client);
192         if (!resource)
193                 return;
194
195         display = wl_client_get_display(resource->client);
196         serial = wl_display_next_serial(display);
197
198         if (seat->drag_data_source)
199                 offer = wl_data_source_send_offer(seat->drag_data_source,
200                                                   resource);
201
202         wl_data_device_send_enter(resource, serial, &surface->resource,
203                                   x, y, offer);
204
205         seat->drag_focus = surface;
206         seat->drag_focus_listener.notify = destroy_drag_focus;
207         wl_signal_add(&resource->destroy_signal,
208                       &seat->drag_focus_listener);
209         seat->drag_focus_resource = resource;
210         grab->focus = surface;
211 }
212
213 static void
214 drag_grab_motion(struct weston_pointer_grab *grab,
215                  uint32_t time, wl_fixed_t x, wl_fixed_t y)
216 {
217         struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
218
219         if (seat->drag_focus_resource)
220                 wl_data_device_send_motion(seat->drag_focus_resource,
221                                            time, x, y);
222 }
223
224 static void
225 data_device_end_drag_grab(struct wl_seat *seat)
226 {
227         if (seat->drag_surface) {
228                 seat->drag_surface = NULL;
229                 wl_signal_emit(&seat->drag_icon_signal, NULL);
230                 wl_list_remove(&seat->drag_icon_listener.link);
231         }
232
233         drag_grab_focus(&seat->drag_grab, NULL,
234                         wl_fixed_from_int(0), wl_fixed_from_int(0));
235
236         weston_pointer_end_grab(seat->pointer);
237
238         seat->drag_data_source = NULL;
239         seat->drag_client = NULL;
240 }
241
242 static void
243 drag_grab_button(struct weston_pointer_grab *grab,
244                  uint32_t time, uint32_t button, uint32_t state_w)
245 {
246         struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
247         enum wl_pointer_button_state state = state_w;
248
249         if (seat->drag_focus_resource &&
250             seat->pointer->grab_button == button &&
251             state == WL_POINTER_BUTTON_STATE_RELEASED)
252                 wl_data_device_send_drop(seat->drag_focus_resource);
253
254         if (seat->pointer->button_count == 0 &&
255             state == WL_POINTER_BUTTON_STATE_RELEASED) {
256                 if (seat->drag_data_source)
257                         wl_list_remove(&seat->drag_data_source_listener.link);
258                 data_device_end_drag_grab(seat);
259         }
260 }
261
262 static const struct weston_pointer_grab_interface drag_grab_interface = {
263         drag_grab_focus,
264         drag_grab_motion,
265         drag_grab_button,
266 };
267
268 static void
269 destroy_data_device_source(struct wl_listener *listener, void *data)
270 {
271         struct wl_seat *seat = container_of(listener, struct wl_seat,
272                                             drag_data_source_listener);
273
274         data_device_end_drag_grab(seat);
275 }
276
277 static void
278 destroy_data_device_icon(struct wl_listener *listener, void *data)
279 {
280         struct wl_seat *seat = container_of(listener, struct wl_seat,
281                                             drag_icon_listener);
282
283         seat->drag_surface = NULL;
284 }
285
286 static void
287 data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
288                        struct wl_resource *source_resource,
289                        struct wl_resource *origin_resource,
290                        struct wl_resource *icon_resource, uint32_t serial)
291 {
292         struct wl_seat *seat = resource->data;
293
294         /* FIXME: Check that client has implicit grab on the origin
295          * surface that matches the given time. */
296
297         /* FIXME: Check that the data source type array isn't empty. */
298
299         seat->drag_grab.interface = &drag_grab_interface;
300
301         seat->drag_client = client;
302         seat->drag_data_source = NULL;
303
304         if (source_resource) {
305                 seat->drag_data_source = source_resource->data;
306                 seat->drag_data_source_listener.notify =
307                         destroy_data_device_source;
308                 wl_signal_add(&source_resource->destroy_signal,
309                               &seat->drag_data_source_listener);
310         }
311
312         if (icon_resource) {
313                 seat->drag_surface = icon_resource->data;
314                 seat->drag_icon_listener.notify = destroy_data_device_icon;
315                 wl_signal_add(&icon_resource->destroy_signal,
316                               &seat->drag_icon_listener);
317                 wl_signal_emit(&seat->drag_icon_signal, icon_resource);
318         }
319
320         weston_pointer_set_focus(seat->pointer, NULL,
321                                  wl_fixed_from_int(0), wl_fixed_from_int(0));
322         weston_pointer_start_grab(seat->pointer, &seat->drag_grab);
323 }
324
325 static void
326 destroy_selection_data_source(struct wl_listener *listener, void *data)
327 {
328         struct wl_seat *seat = container_of(listener, struct wl_seat,
329                                             selection_data_source_listener);
330         struct wl_resource *data_device;
331         struct wl_resource *focus = NULL;
332
333         seat->selection_data_source = NULL;
334
335         if (seat->keyboard)
336                 focus = seat->keyboard->focus_resource;
337         if (focus) {
338                 data_device = find_resource(&seat->drag_resource_list,
339                                             focus->client);
340                 if (data_device)
341                         wl_data_device_send_selection(data_device, NULL);
342         }
343
344         wl_signal_emit(&seat->selection_signal, seat);
345 }
346
347 WL_EXPORT void
348 wl_seat_set_selection(struct wl_seat *seat, struct wl_data_source *source,
349                       uint32_t serial)
350 {
351         struct wl_resource *data_device, *offer;
352         struct wl_resource *focus = NULL;
353
354         if (seat->selection_data_source &&
355             seat->selection_serial - serial < UINT32_MAX / 2)
356                 return;
357
358         if (seat->selection_data_source) {
359                 seat->selection_data_source->cancel(seat->selection_data_source);
360                 wl_list_remove(&seat->selection_data_source_listener.link);
361                 seat->selection_data_source = NULL;
362         }
363
364         seat->selection_data_source = source;
365         seat->selection_serial = serial;
366
367         if (seat->keyboard)
368                 focus = seat->keyboard->focus_resource;
369         if (focus) {
370                 data_device = find_resource(&seat->drag_resource_list,
371                                             focus->client);
372                 if (data_device && source) {
373                         offer = wl_data_source_send_offer(seat->selection_data_source,
374                                                           data_device);
375                         wl_data_device_send_selection(data_device, offer);
376                 } else if (data_device) {
377                         wl_data_device_send_selection(data_device, NULL);
378                 }
379         }
380
381         wl_signal_emit(&seat->selection_signal, seat);
382
383         if (source) {
384                 seat->selection_data_source_listener.notify =
385                         destroy_selection_data_source;
386                 wl_signal_add(&source->resource.destroy_signal,
387                               &seat->selection_data_source_listener);
388         }
389 }
390
391 static void
392 data_device_set_selection(struct wl_client *client,
393                           struct wl_resource *resource,
394                           struct wl_resource *source_resource, uint32_t serial)
395 {
396         if (!source_resource)
397                 return;
398
399         /* FIXME: Store serial and check against incoming serial here. */
400         wl_seat_set_selection(resource->data, source_resource->data,
401                               serial);
402 }
403
404 static const struct wl_data_device_interface data_device_interface = {
405         data_device_start_drag,
406         data_device_set_selection,
407 };
408
409 static void
410 destroy_data_source(struct wl_resource *resource)
411 {
412         struct wl_data_source *source =
413                 container_of(resource, struct wl_data_source, resource);
414         char **p;
415
416         wl_array_for_each(p, &source->mime_types)
417                 free(*p);
418
419         wl_array_release(&source->mime_types);
420
421         source->resource.object.id = 0;
422 }
423
424 static void
425 client_source_accept(struct wl_data_source *source,
426                      uint32_t time, const char *mime_type)
427 {
428         wl_data_source_send_target(&source->resource, mime_type);
429 }
430
431 static void
432 client_source_send(struct wl_data_source *source,
433                    const char *mime_type, int32_t fd)
434 {
435         wl_data_source_send_send(&source->resource, mime_type, fd);
436         close(fd);
437 }
438
439 static void
440 client_source_cancel(struct wl_data_source *source)
441 {
442         wl_data_source_send_cancelled(&source->resource);
443 }
444
445 static void
446 create_data_source(struct wl_client *client,
447                    struct wl_resource *resource, uint32_t id)
448 {
449         struct wl_data_source *source;
450
451         source = malloc(sizeof *source);
452         if (source == NULL) {
453                 wl_resource_post_no_memory(resource);
454                 return;
455         }
456
457         wl_resource_init(&source->resource, &wl_data_source_interface,
458                          &data_source_interface, id, source);
459         source->resource.destroy = destroy_data_source;
460
461         source->accept = client_source_accept;
462         source->send = client_source_send;
463         source->cancel = client_source_cancel;
464
465         wl_array_init(&source->mime_types);
466         wl_client_add_resource(client, &source->resource);
467 }
468
469 static void unbind_data_device(struct wl_resource *resource)
470 {
471         wl_list_remove(&resource->link);
472         free(resource);
473 }
474
475 static void
476 get_data_device(struct wl_client *client,
477                 struct wl_resource *manager_resource,
478                 uint32_t id, struct wl_resource *seat_resource)
479 {
480         struct wl_seat *seat = seat_resource->data;
481         struct wl_resource *resource;
482
483         resource = wl_client_add_object(client, &wl_data_device_interface,
484                                         &data_device_interface, id,
485                                         seat);
486
487         wl_list_insert(&seat->drag_resource_list, &resource->link);
488         resource->destroy = unbind_data_device;
489 }
490
491 static const struct wl_data_device_manager_interface manager_interface = {
492         create_data_source,
493         get_data_device
494 };
495
496 static void
497 bind_manager(struct wl_client *client,
498              void *data, uint32_t version, uint32_t id)
499 {
500         wl_client_add_object(client, &wl_data_device_manager_interface,
501                              &manager_interface, id, NULL);
502 }
503
504 WL_EXPORT void
505 wl_data_device_set_keyboard_focus(struct wl_seat *seat)
506 {
507         struct wl_resource *data_device, *focus, *offer;
508         struct wl_data_source *source;
509
510         if (!seat->keyboard)
511                 return;
512
513         focus = seat->keyboard->focus_resource;
514         if (!focus)
515                 return;
516
517         data_device = find_resource(&seat->drag_resource_list,
518                                     focus->client);
519         if (!data_device)
520                 return;
521
522         source = seat->selection_data_source;
523         if (source) {
524                 offer = wl_data_source_send_offer(source, data_device);
525                 wl_data_device_send_selection(data_device, offer);
526         }
527 }
528
529 WL_EXPORT int
530 wl_data_device_manager_init(struct wl_display *display)
531 {
532         if (wl_display_add_global(display,
533                                   &wl_data_device_manager_interface,
534                                   NULL, bind_manager) == NULL)
535                 return -1;
536
537         return 0;
538 }