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 "compositor.h"
31 data_offer_accept(struct wl_client *client, struct wl_resource *resource,
32 uint32_t serial, const char *mime_type)
34 struct wl_data_offer *offer = resource->data;
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? */
41 offer->source->accept(offer->source, serial, mime_type);
45 data_offer_receive(struct wl_client *client, struct wl_resource *resource,
46 const char *mime_type, int32_t fd)
48 struct wl_data_offer *offer = resource->data;
51 offer->source->send(offer->source, mime_type, fd);
57 data_offer_destroy(struct wl_client *client, struct wl_resource *resource)
59 wl_resource_destroy(resource);
62 static const struct wl_data_offer_interface data_offer_interface = {
69 destroy_data_offer(struct wl_resource *resource)
71 struct wl_data_offer *offer = resource->data;
74 wl_list_remove(&offer->source_destroy_listener.link);
79 destroy_offer_data_source(struct wl_listener *listener, void *data)
81 struct wl_data_offer *offer;
83 offer = container_of(listener, struct wl_data_offer,
84 source_destroy_listener);
89 static struct wl_resource *
90 wl_data_source_send_offer(struct wl_data_source *source,
91 struct wl_resource *target)
93 struct wl_data_offer *offer;
96 offer = malloc(sizeof *offer);
100 wl_resource_init(&offer->resource, &wl_data_offer_interface,
101 &data_offer_interface, 0, offer);
102 offer->resource.destroy = destroy_data_offer;
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);
109 wl_client_add_resource(target->client, &offer->resource);
111 wl_data_device_send_data_offer(target, &offer->resource);
113 wl_array_for_each(p, &source->mime_types)
114 wl_data_offer_send_offer(&offer->resource, *p);
116 return &offer->resource;
120 data_source_offer(struct wl_client *client,
121 struct wl_resource *resource,
124 struct wl_data_source *source = resource->data;
127 p = wl_array_add(&source->mime_types, sizeof *p);
131 wl_resource_post_no_memory(resource);
135 data_source_destroy(struct wl_client *client, struct wl_resource *resource)
137 wl_resource_destroy(resource);
140 static struct wl_data_source_interface data_source_interface = {
145 static struct wl_resource *
146 find_resource(struct wl_list *list, struct wl_client *client)
148 struct wl_resource *r;
150 wl_list_for_each(r, list, link) {
151 if (r->client == client)
159 destroy_drag_focus(struct wl_listener *listener, void *data)
161 struct wl_seat *seat =
162 container_of(listener, struct wl_seat, drag_focus_listener);
164 seat->drag_focus_resource = NULL;
168 drag_grab_focus(struct weston_pointer_grab *grab,
169 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
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;
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;
186 if (!seat->drag_data_source &&
187 surface->resource.client != seat->drag_client)
190 resource = find_resource(&seat->drag_resource_list,
191 surface->resource.client);
195 display = wl_client_get_display(resource->client);
196 serial = wl_display_next_serial(display);
198 if (seat->drag_data_source)
199 offer = wl_data_source_send_offer(seat->drag_data_source,
202 wl_data_device_send_enter(resource, serial, &surface->resource,
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;
214 drag_grab_motion(struct weston_pointer_grab *grab,
215 uint32_t time, wl_fixed_t x, wl_fixed_t y)
217 struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
219 if (seat->drag_focus_resource)
220 wl_data_device_send_motion(seat->drag_focus_resource,
225 data_device_end_drag_grab(struct wl_seat *seat)
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);
233 drag_grab_focus(&seat->drag_grab, NULL,
234 wl_fixed_from_int(0), wl_fixed_from_int(0));
236 weston_pointer_end_grab(seat->pointer);
238 seat->drag_data_source = NULL;
239 seat->drag_client = NULL;
243 drag_grab_button(struct weston_pointer_grab *grab,
244 uint32_t time, uint32_t button, uint32_t state_w)
246 struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
247 enum wl_pointer_button_state state = state_w;
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);
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);
262 static const struct weston_pointer_grab_interface drag_grab_interface = {
269 destroy_data_device_source(struct wl_listener *listener, void *data)
271 struct wl_seat *seat = container_of(listener, struct wl_seat,
272 drag_data_source_listener);
274 data_device_end_drag_grab(seat);
278 destroy_data_device_icon(struct wl_listener *listener, void *data)
280 struct wl_seat *seat = container_of(listener, struct wl_seat,
283 seat->drag_surface = NULL;
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)
292 struct wl_seat *seat = resource->data;
294 /* FIXME: Check that client has implicit grab on the origin
295 * surface that matches the given time. */
297 /* FIXME: Check that the data source type array isn't empty. */
299 seat->drag_grab.interface = &drag_grab_interface;
301 seat->drag_client = client;
302 seat->drag_data_source = NULL;
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);
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);
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);
326 destroy_selection_data_source(struct wl_listener *listener, void *data)
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;
333 seat->selection_data_source = NULL;
336 focus = seat->keyboard->focus_resource;
338 data_device = find_resource(&seat->drag_resource_list,
341 wl_data_device_send_selection(data_device, NULL);
344 wl_signal_emit(&seat->selection_signal, seat);
348 wl_seat_set_selection(struct wl_seat *seat, struct wl_data_source *source,
351 struct wl_resource *data_device, *offer;
352 struct wl_resource *focus = NULL;
354 if (seat->selection_data_source &&
355 seat->selection_serial - serial < UINT32_MAX / 2)
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;
364 seat->selection_data_source = source;
365 seat->selection_serial = serial;
368 focus = seat->keyboard->focus_resource;
370 data_device = find_resource(&seat->drag_resource_list,
372 if (data_device && source) {
373 offer = wl_data_source_send_offer(seat->selection_data_source,
375 wl_data_device_send_selection(data_device, offer);
376 } else if (data_device) {
377 wl_data_device_send_selection(data_device, NULL);
381 wl_signal_emit(&seat->selection_signal, seat);
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);
392 data_device_set_selection(struct wl_client *client,
393 struct wl_resource *resource,
394 struct wl_resource *source_resource, uint32_t serial)
396 if (!source_resource)
399 /* FIXME: Store serial and check against incoming serial here. */
400 wl_seat_set_selection(resource->data, source_resource->data,
404 static const struct wl_data_device_interface data_device_interface = {
405 data_device_start_drag,
406 data_device_set_selection,
410 destroy_data_source(struct wl_resource *resource)
412 struct wl_data_source *source =
413 container_of(resource, struct wl_data_source, resource);
416 wl_array_for_each(p, &source->mime_types)
419 wl_array_release(&source->mime_types);
421 source->resource.object.id = 0;
425 client_source_accept(struct wl_data_source *source,
426 uint32_t time, const char *mime_type)
428 wl_data_source_send_target(&source->resource, mime_type);
432 client_source_send(struct wl_data_source *source,
433 const char *mime_type, int32_t fd)
435 wl_data_source_send_send(&source->resource, mime_type, fd);
440 client_source_cancel(struct wl_data_source *source)
442 wl_data_source_send_cancelled(&source->resource);
446 create_data_source(struct wl_client *client,
447 struct wl_resource *resource, uint32_t id)
449 struct wl_data_source *source;
451 source = malloc(sizeof *source);
452 if (source == NULL) {
453 wl_resource_post_no_memory(resource);
457 wl_resource_init(&source->resource, &wl_data_source_interface,
458 &data_source_interface, id, source);
459 source->resource.destroy = destroy_data_source;
461 source->accept = client_source_accept;
462 source->send = client_source_send;
463 source->cancel = client_source_cancel;
465 wl_array_init(&source->mime_types);
466 wl_client_add_resource(client, &source->resource);
469 static void unbind_data_device(struct wl_resource *resource)
471 wl_list_remove(&resource->link);
476 get_data_device(struct wl_client *client,
477 struct wl_resource *manager_resource,
478 uint32_t id, struct wl_resource *seat_resource)
480 struct wl_seat *seat = seat_resource->data;
481 struct wl_resource *resource;
483 resource = wl_client_add_object(client, &wl_data_device_interface,
484 &data_device_interface, id,
487 wl_list_insert(&seat->drag_resource_list, &resource->link);
488 resource->destroy = unbind_data_device;
491 static const struct wl_data_device_manager_interface manager_interface = {
497 bind_manager(struct wl_client *client,
498 void *data, uint32_t version, uint32_t id)
500 wl_client_add_object(client, &wl_data_device_manager_interface,
501 &manager_interface, id, NULL);
505 wl_data_device_set_keyboard_focus(struct wl_seat *seat)
507 struct wl_resource *data_device, *focus, *offer;
508 struct wl_data_source *source;
513 focus = seat->keyboard->focus_resource;
517 data_device = find_resource(&seat->drag_resource_list,
522 source = seat->selection_data_source;
524 offer = wl_data_source_send_offer(source, data_device);
525 wl_data_device_send_selection(data_device, offer);
530 wl_data_device_manager_init(struct wl_display *display)
532 if (wl_display_add_global(display,
533 &wl_data_device_manager_interface,
534 NULL, bind_manager) == NULL)