2 * Copyright © 2011 Kristian Høgsberg
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.
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
28 #include "wayland-private.h"
29 #include "wayland-server.h"
32 data_offer_accept(struct wl_client *client, struct wl_resource *resource,
33 uint32_t serial, const char *mime_type)
35 struct wl_data_offer *offer = resource->data;
37 /* FIXME: Check that client is currently focused by the input
38 * device that is currently dragging this data source. Should
39 * this be a wl_data_device request? */
42 offer->source->accept(offer->source, serial, mime_type);
46 data_offer_receive(struct wl_client *client, struct wl_resource *resource,
47 const char *mime_type, int32_t fd)
49 struct wl_data_offer *offer = resource->data;
52 offer->source->send(offer->source, mime_type, fd);
58 data_offer_destroy(struct wl_client *client, struct wl_resource *resource)
60 wl_resource_destroy(resource);
63 static const struct wl_data_offer_interface data_offer_interface = {
70 destroy_data_offer(struct wl_resource *resource)
72 struct wl_data_offer *offer = resource->data;
75 wl_list_remove(&offer->source_destroy_listener.link);
80 destroy_offer_data_source(struct wl_listener *listener, void *data)
82 struct wl_data_offer *offer;
84 offer = container_of(listener, struct wl_data_offer,
85 source_destroy_listener);
90 static struct wl_resource *
91 wl_data_source_send_offer(struct wl_data_source *source,
92 struct wl_resource *target)
94 struct wl_data_offer *offer;
97 offer = malloc(sizeof *offer);
101 offer->resource.destroy = destroy_data_offer;
102 offer->resource.object.id = 0;
103 offer->resource.object.interface = &wl_data_offer_interface;
104 offer->resource.object.implementation =
105 (void (**)(void)) &data_offer_interface;
106 offer->resource.data = offer;
107 wl_signal_init(&offer->resource.destroy_signal);
109 offer->source = source;
110 offer->source_destroy_listener.notify = destroy_offer_data_source;
111 wl_signal_add(&source->resource.destroy_signal,
112 &offer->source_destroy_listener);
114 wl_client_add_resource(target->client, &offer->resource);
116 wl_data_device_send_data_offer(target, &offer->resource);
118 wl_array_for_each(p, &source->mime_types)
119 wl_data_offer_send_offer(&offer->resource, *p);
121 return &offer->resource;
125 data_source_offer(struct wl_client *client,
126 struct wl_resource *resource,
129 struct wl_data_source *source = resource->data;
132 p = wl_array_add(&source->mime_types, sizeof *p);
136 wl_resource_post_no_memory(resource);
140 data_source_destroy(struct wl_client *client, struct wl_resource *resource)
142 wl_resource_destroy(resource);
145 static struct wl_data_source_interface data_source_interface = {
150 static struct wl_resource *
151 find_resource(struct wl_list *list, struct wl_client *client)
153 struct wl_resource *r;
155 wl_list_for_each(r, list, link) {
156 if (r->client == client)
164 destroy_drag_focus(struct wl_listener *listener, void *data)
166 struct wl_seat *seat =
167 container_of(listener, struct wl_seat, drag_focus_listener);
169 seat->drag_focus_resource = NULL;
173 drag_grab_focus(struct wl_pointer_grab *grab,
174 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
176 struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
177 struct wl_resource *resource, *offer = NULL;
178 struct wl_display *display;
181 if (seat->drag_focus_resource) {
182 wl_data_device_send_leave(seat->drag_focus_resource);
183 wl_list_remove(&seat->drag_focus_listener.link);
184 seat->drag_focus_resource = NULL;
185 seat->drag_focus = NULL;
191 if (!seat->drag_data_source &&
192 surface->resource.client != seat->drag_client)
195 resource = find_resource(&seat->drag_resource_list,
196 surface->resource.client);
200 display = wl_client_get_display(resource->client);
201 serial = wl_display_next_serial(display);
203 if (seat->drag_data_source)
204 offer = wl_data_source_send_offer(seat->drag_data_source,
207 wl_data_device_send_enter(resource, serial, &surface->resource,
210 seat->drag_focus = surface;
211 seat->drag_focus_listener.notify = destroy_drag_focus;
212 wl_signal_add(&resource->destroy_signal,
213 &seat->drag_focus_listener);
214 seat->drag_focus_resource = resource;
215 grab->focus = surface;
219 drag_grab_motion(struct wl_pointer_grab *grab,
220 uint32_t time, wl_fixed_t x, wl_fixed_t y)
222 struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
224 if (seat->drag_focus_resource)
225 wl_data_device_send_motion(seat->drag_focus_resource,
230 data_device_end_drag_grab(struct wl_seat *seat)
232 if (seat->drag_surface) {
233 seat->drag_surface = NULL;
234 wl_signal_emit(&seat->drag_icon_signal, NULL);
235 wl_list_remove(&seat->drag_icon_listener.link);
238 drag_grab_focus(&seat->drag_grab, NULL,
239 wl_fixed_from_int(0), wl_fixed_from_int(0));
241 wl_pointer_end_grab(seat->pointer);
243 seat->drag_data_source = NULL;
244 seat->drag_client = NULL;
248 drag_grab_button(struct wl_pointer_grab *grab,
249 uint32_t time, uint32_t button, uint32_t state_w)
251 struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
252 enum wl_pointer_button_state state = state_w;
254 if (seat->drag_focus_resource &&
255 seat->pointer->grab_button == button &&
256 state == WL_POINTER_BUTTON_STATE_RELEASED)
257 wl_data_device_send_drop(seat->drag_focus_resource);
259 if (seat->pointer->button_count == 0 &&
260 state == WL_POINTER_BUTTON_STATE_RELEASED) {
261 if (seat->drag_data_source)
262 wl_list_remove(&seat->drag_data_source_listener.link);
263 data_device_end_drag_grab(seat);
267 static const struct wl_pointer_grab_interface drag_grab_interface = {
274 destroy_data_device_source(struct wl_listener *listener, void *data)
276 struct wl_seat *seat = container_of(listener, struct wl_seat,
277 drag_data_source_listener);
279 data_device_end_drag_grab(seat);
283 destroy_data_device_icon(struct wl_listener *listener, void *data)
285 struct wl_seat *seat = container_of(listener, struct wl_seat,
288 seat->drag_surface = NULL;
292 data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
293 struct wl_resource *source_resource,
294 struct wl_resource *origin_resource,
295 struct wl_resource *icon_resource, uint32_t serial)
297 struct wl_seat *seat = resource->data;
299 /* FIXME: Check that client has implicit grab on the origin
300 * surface that matches the given time. */
302 /* FIXME: Check that the data source type array isn't empty. */
304 seat->drag_grab.interface = &drag_grab_interface;
306 seat->drag_client = client;
307 seat->drag_data_source = NULL;
309 if (source_resource) {
310 seat->drag_data_source = source_resource->data;
311 seat->drag_data_source_listener.notify =
312 destroy_data_device_source;
313 wl_signal_add(&source_resource->destroy_signal,
314 &seat->drag_data_source_listener);
318 seat->drag_surface = icon_resource->data;
319 seat->drag_icon_listener.notify = destroy_data_device_icon;
320 wl_signal_add(&icon_resource->destroy_signal,
321 &seat->drag_icon_listener);
322 wl_signal_emit(&seat->drag_icon_signal, icon_resource);
325 wl_pointer_set_focus(seat->pointer, NULL,
326 wl_fixed_from_int(0), wl_fixed_from_int(0));
327 wl_pointer_start_grab(seat->pointer, &seat->drag_grab);
331 destroy_selection_data_source(struct wl_listener *listener, void *data)
333 struct wl_seat *seat = container_of(listener, struct wl_seat,
334 selection_data_source_listener);
335 struct wl_resource *data_device;
336 struct wl_resource *focus = NULL;
338 seat->selection_data_source = NULL;
341 focus = seat->keyboard->focus_resource;
343 data_device = find_resource(&seat->drag_resource_list,
346 wl_data_device_send_selection(data_device, NULL);
349 wl_signal_emit(&seat->selection_signal, seat);
353 wl_seat_set_selection(struct wl_seat *seat, struct wl_data_source *source,
356 struct wl_resource *data_device, *offer;
357 struct wl_resource *focus = NULL;
359 if (seat->selection_data_source &&
360 seat->selection_serial - serial < UINT32_MAX / 2)
363 if (seat->selection_data_source) {
364 seat->selection_data_source->cancel(seat->selection_data_source);
365 wl_list_remove(&seat->selection_data_source_listener.link);
366 seat->selection_data_source = NULL;
369 seat->selection_data_source = source;
370 seat->selection_serial = serial;
373 focus = seat->keyboard->focus_resource;
375 data_device = find_resource(&seat->drag_resource_list,
377 if (data_device && source) {
378 offer = wl_data_source_send_offer(seat->selection_data_source,
380 wl_data_device_send_selection(data_device, offer);
381 } else if (data_device) {
382 wl_data_device_send_selection(data_device, NULL);
386 wl_signal_emit(&seat->selection_signal, seat);
389 seat->selection_data_source_listener.notify =
390 destroy_selection_data_source;
391 wl_signal_add(&source->resource.destroy_signal,
392 &seat->selection_data_source_listener);
397 data_device_set_selection(struct wl_client *client,
398 struct wl_resource *resource,
399 struct wl_resource *source_resource, uint32_t serial)
401 if (!source_resource)
404 /* FIXME: Store serial and check against incoming serial here. */
405 wl_seat_set_selection(resource->data, source_resource->data,
409 static const struct wl_data_device_interface data_device_interface = {
410 data_device_start_drag,
411 data_device_set_selection,
415 destroy_data_source(struct wl_resource *resource)
417 struct wl_data_source *source =
418 container_of(resource, struct wl_data_source, resource);
421 wl_array_for_each(p, &source->mime_types)
424 wl_array_release(&source->mime_types);
426 source->resource.object.id = 0;
430 client_source_accept(struct wl_data_source *source,
431 uint32_t time, const char *mime_type)
433 wl_data_source_send_target(&source->resource, mime_type);
437 client_source_send(struct wl_data_source *source,
438 const char *mime_type, int32_t fd)
440 wl_data_source_send_send(&source->resource, mime_type, fd);
445 client_source_cancel(struct wl_data_source *source)
447 wl_data_source_send_cancelled(&source->resource);
451 create_data_source(struct wl_client *client,
452 struct wl_resource *resource, uint32_t id)
454 struct wl_data_source *source;
456 source = malloc(sizeof *source);
457 if (source == NULL) {
458 wl_resource_post_no_memory(resource);
462 source->resource.destroy = destroy_data_source;
463 source->resource.object.id = id;
464 source->resource.object.interface = &wl_data_source_interface;
465 source->resource.object.implementation =
466 (void (**)(void)) &data_source_interface;
467 source->resource.data = source;
468 wl_signal_init(&source->resource.destroy_signal);
470 source->accept = client_source_accept;
471 source->send = client_source_send;
472 source->cancel = client_source_cancel;
474 wl_array_init(&source->mime_types);
475 wl_client_add_resource(client, &source->resource);
478 static void unbind_data_device(struct wl_resource *resource)
480 wl_list_remove(&resource->link);
485 get_data_device(struct wl_client *client,
486 struct wl_resource *manager_resource,
487 uint32_t id, struct wl_resource *seat_resource)
489 struct wl_seat *seat = seat_resource->data;
490 struct wl_resource *resource;
492 resource = wl_client_add_object(client, &wl_data_device_interface,
493 &data_device_interface, id,
496 wl_list_insert(&seat->drag_resource_list, &resource->link);
497 resource->destroy = unbind_data_device;
500 static const struct wl_data_device_manager_interface manager_interface = {
506 bind_manager(struct wl_client *client,
507 void *data, uint32_t version, uint32_t id)
509 wl_client_add_object(client, &wl_data_device_manager_interface,
510 &manager_interface, id, NULL);
514 wl_data_device_set_keyboard_focus(struct wl_seat *seat)
516 struct wl_resource *data_device, *focus, *offer;
517 struct wl_data_source *source;
522 focus = seat->keyboard->focus_resource;
526 data_device = find_resource(&seat->drag_resource_list,
531 source = seat->selection_data_source;
533 offer = wl_data_source_send_offer(source, data_device);
534 wl_data_device_send_selection(data_device, offer);
539 wl_data_device_manager_init(struct wl_display *display)
541 if (wl_display_add_global(display,
542 &wl_data_device_manager_interface,
543 NULL, bind_manager) == NULL)