[PATCH wayland] data-device: implement drags with no data source for self-dnd
Kristian Høgsberg
hoegsberg at gmail.com
Tue May 29 07:01:28 PDT 2012
On Tue, May 29, 2012 at 10:58:26AM +0300, Ander Conselvan de Oliveira wrote:
> Properly handle a drag with no data source, i.e., don't crash and send
> events only to the client that initiated the drag. This way a client can
> do self drag and drop without offering anything to other clients.
Oh, very nice, thanks for wrapping that up and adding the test case.
Wayland and Weston patches both committed.
Kristian
> ---
> TODO | 4 ---
> protocol/wayland.xml | 26 ++++++++++++++-------
> src/data-device.c | 58 +++++++++++++++++++++++++++++++------------------
> src/wayland-server.h | 1 +
> 4 files changed, 55 insertions(+), 34 deletions(-)
>
> diff --git a/TODO b/TODO
> index abdab31..12f22a7 100644
> --- a/TODO
> +++ b/TODO
> @@ -78,10 +78,6 @@ EWMH
>
> - window move and resize functionality for kb and touch.
>
> - - dnd loose ends: self-dnd: initiate dnd with a null data-source,
> - compositor will not offer to other clients, client has to know
> - internally what's offered and how to transfer data. no fd passing.
> -
> - Protocol for specifying title bar rectangle (for moving
> unresponsive apps). Rectangle for close button, so we can popup
> force-close dialog if application doesn't respond to ping event
> diff --git a/protocol/wayland.xml b/protocol/wayland.xml
> index 8f5f6af..3979d97 100644
> --- a/protocol/wayland.xml
> +++ b/protocol/wayland.xml
> @@ -317,15 +317,23 @@
> <request name="start_drag">
> <description summary="start drag and drop operation">
> This request asks the compositor to start a drag and drop
> - operation on behalf of the client. The source argument is the
> - data source that provides the data for the eventual data
> - transfer. The origin surface is the surface where the drag
> - originates and the client must have an active implicit grab
> - that matches the serial. The icon surface is an optional
> - (can be nil) surface that provides an icon to be moved around
> - with the cursor. Initially, the top-left corner of the icon
> - surface is placed at the cursor hotspot, but subsequent
> - surface.attach request can move the relative position.
> + operation on behalf of the client.
> +
> + The source argument is the data source that provides the data
> + for the eventual data transfer. If source is NULL, enter, leave
> + and motion events are sent only to the client that initiated the
> + drag and the client is expected to handle the data passing
> + internally.
> +
> + The origin surface is the surface where the drag originates and
> + the client must have an active implicit grab that matches the
> + serial.
> +
> + The icon surface is an optional (can be nil) surface that
> + provides an icon to be moved around with the cursor. Initially,
> + the top-left corner of the icon surface is placed at the cursor
> + hotspot, but subsequent surface.attach request can move the
> + relative position.
> </description>
> <arg name="source" type="object" interface="wl_data_source"/>
> <arg name="origin" type="object" interface="wl_surface"/>
> diff --git a/src/data-device.c b/src/data-device.c
> index a7fc6d2..a6d465f 100644
> --- a/src/data-device.c
> +++ b/src/data-device.c
> @@ -180,7 +180,7 @@ drag_grab_focus(struct wl_pointer_grab *grab,
> struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
> {
> struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
> - struct wl_resource *resource, *offer;
> + struct wl_resource *resource, *offer = NULL;
> struct wl_display *display;
> uint32_t serial;
>
> @@ -191,26 +191,34 @@ drag_grab_focus(struct wl_pointer_grab *grab,
> seat->drag_focus = NULL;
> }
>
> - if (surface)
> - resource = find_resource(&seat->drag_resource_list,
> - surface->resource.client);
> - if (surface && resource) {
> - display = wl_client_get_display(resource->client);
> - serial = wl_display_next_serial(display);
> + if (!surface)
> + return;
> +
> + if (!seat->drag_data_source &&
> + surface->resource.client != seat->drag_client)
> + return;
> +
> + resource = find_resource(&seat->drag_resource_list,
> + surface->resource.client);
> + if (!resource)
> + return;
>
> + display = wl_client_get_display(resource->client);
> + serial = wl_display_next_serial(display);
> +
> + if (seat->drag_data_source)
> offer = wl_data_source_send_offer(seat->drag_data_source,
> resource);
>
> - wl_data_device_send_enter(resource, serial, &surface->resource,
> - x, y, offer);
> + wl_data_device_send_enter(resource, serial, &surface->resource,
> + x, y, offer);
>
> - seat->drag_focus = surface;
> - seat->drag_focus_listener.notify = destroy_drag_focus;
> - wl_signal_add(&resource->destroy_signal,
> - &seat->drag_focus_listener);
> - seat->drag_focus_resource = resource;
> - grab->focus = surface;
> - }
> + seat->drag_focus = surface;
> + seat->drag_focus_listener.notify = destroy_drag_focus;
> + wl_signal_add(&resource->destroy_signal,
> + &seat->drag_focus_listener);
> + seat->drag_focus_resource = resource;
> + grab->focus = surface;
> }
>
> static void
> @@ -247,6 +255,7 @@ data_device_end_drag_grab(struct wl_seat *seat)
>
> seat->drag_data_source = NULL;
> seat->drag_surface = NULL;
> + seat->drag_client = NULL;
> }
>
> static void
> @@ -261,7 +270,8 @@ drag_grab_button(struct wl_pointer_grab *grab,
>
> if (seat->pointer->button_count == 0 && state == 0) {
> data_device_end_drag_grab(seat);
> - wl_list_remove(&seat->drag_data_source_listener.link);
> + if (seat->drag_data_source)
> + wl_list_remove(&seat->drag_data_source_listener.link);
> }
> }
>
> @@ -304,10 +314,16 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
>
> seat->drag_grab.interface = &drag_grab_interface;
>
> - seat->drag_data_source = source_resource->data;
> - seat->drag_data_source_listener.notify = destroy_data_device_source;
> - wl_signal_add(&source_resource->destroy_signal,
> - &seat->drag_data_source_listener);
> + seat->drag_client = client;
> + seat->drag_data_source = NULL;
> +
> + if (source_resource) {
> + seat->drag_data_source = source_resource->data;
> + seat->drag_data_source_listener.notify =
> + destroy_data_device_source;
> + wl_signal_add(&source_resource->destroy_signal,
> + &seat->drag_data_source_listener);
> + }
>
> if (icon_resource) {
> seat->drag_surface = icon_resource->data;
> diff --git a/src/wayland-server.h b/src/wayland-server.h
> index 31f6fe5..731be00 100644
> --- a/src/wayland-server.h
> +++ b/src/wayland-server.h
> @@ -297,6 +297,7 @@ struct wl_seat {
> struct wl_signal selection_signal;
>
> struct wl_list drag_resource_list;
> + struct wl_client *drag_client;
> struct wl_data_source *drag_data_source;
> struct wl_listener drag_data_source_listener;
> struct wl_surface *drag_focus;
> --
> 1.7.4.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list