data-device: implement drags with no data source for self-dnd

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.
This commit is contained in:
Ander Conselvan de Oliveira 2012-05-29 10:58:26 +03:00 committed by Kristian Høgsberg
parent d422a733b4
commit 75a5f7476a
4 changed files with 55 additions and 34 deletions

4
TODO
View file

@ -78,10 +78,6 @@ EWMH
- window move and resize functionality for kb and touch. - 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 - Protocol for specifying title bar rectangle (for moving
unresponsive apps). Rectangle for close button, so we can popup unresponsive apps). Rectangle for close button, so we can popup
force-close dialog if application doesn't respond to ping event force-close dialog if application doesn't respond to ping event

View file

@ -317,15 +317,23 @@
<request name="start_drag"> <request name="start_drag">
<description summary="start drag and drop operation"> <description summary="start drag and drop operation">
This request asks the compositor to start a drag and drop This request asks the compositor to start a drag and drop
operation on behalf of the client. The source argument is the operation on behalf of the client.
data source that provides the data for the eventual data
transfer. The origin surface is the surface where the drag The source argument is the data source that provides the data
originates and the client must have an active implicit grab for the eventual data transfer. If source is NULL, enter, leave
that matches the serial. The icon surface is an optional and motion events are sent only to the client that initiated the
(can be nil) surface that provides an icon to be moved around drag and the client is expected to handle the data passing
with the cursor. Initially, the top-left corner of the icon internally.
surface is placed at the cursor hotspot, but subsequent
surface.attach request can move the relative position. 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> </description>
<arg name="source" type="object" interface="wl_data_source"/> <arg name="source" type="object" interface="wl_data_source"/>
<arg name="origin" type="object" interface="wl_surface"/> <arg name="origin" type="object" interface="wl_surface"/>

View file

@ -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_surface *surface, wl_fixed_t x, wl_fixed_t y)
{ {
struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab); 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; struct wl_display *display;
uint32_t serial; uint32_t serial;
@ -191,13 +191,22 @@ drag_grab_focus(struct wl_pointer_grab *grab,
seat->drag_focus = NULL; seat->drag_focus = NULL;
} }
if (surface) if (!surface)
return;
if (!seat->drag_data_source &&
surface->resource.client != seat->drag_client)
return;
resource = find_resource(&seat->drag_resource_list, resource = find_resource(&seat->drag_resource_list,
surface->resource.client); surface->resource.client);
if (surface && resource) { if (!resource)
return;
display = wl_client_get_display(resource->client); display = wl_client_get_display(resource->client);
serial = wl_display_next_serial(display); serial = wl_display_next_serial(display);
if (seat->drag_data_source)
offer = wl_data_source_send_offer(seat->drag_data_source, offer = wl_data_source_send_offer(seat->drag_data_source,
resource); resource);
@ -211,7 +220,6 @@ drag_grab_focus(struct wl_pointer_grab *grab,
seat->drag_focus_resource = resource; seat->drag_focus_resource = resource;
grab->focus = surface; grab->focus = surface;
} }
}
static void static void
drag_grab_motion(struct wl_pointer_grab *grab, drag_grab_motion(struct wl_pointer_grab *grab,
@ -247,6 +255,7 @@ data_device_end_drag_grab(struct wl_seat *seat)
seat->drag_data_source = NULL; seat->drag_data_source = NULL;
seat->drag_surface = NULL; seat->drag_surface = NULL;
seat->drag_client = NULL;
} }
static void static void
@ -261,6 +270,7 @@ drag_grab_button(struct wl_pointer_grab *grab,
if (seat->pointer->button_count == 0 && state == 0) { if (seat->pointer->button_count == 0 && state == 0) {
data_device_end_drag_grab(seat); data_device_end_drag_grab(seat);
if (seat->drag_data_source)
wl_list_remove(&seat->drag_data_source_listener.link); 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_grab.interface = &drag_grab_interface;
seat->drag_client = client;
seat->drag_data_source = NULL;
if (source_resource) {
seat->drag_data_source = source_resource->data; seat->drag_data_source = source_resource->data;
seat->drag_data_source_listener.notify = destroy_data_device_source; seat->drag_data_source_listener.notify =
destroy_data_device_source;
wl_signal_add(&source_resource->destroy_signal, wl_signal_add(&source_resource->destroy_signal,
&seat->drag_data_source_listener); &seat->drag_data_source_listener);
}
if (icon_resource) { if (icon_resource) {
seat->drag_surface = icon_resource->data; seat->drag_surface = icon_resource->data;

View file

@ -297,6 +297,7 @@ struct wl_seat {
struct wl_signal selection_signal; struct wl_signal selection_signal;
struct wl_list drag_resource_list; struct wl_list drag_resource_list;
struct wl_client *drag_client;
struct wl_data_source *drag_data_source; struct wl_data_source *drag_data_source;
struct wl_listener drag_data_source_listener; struct wl_listener drag_data_source_listener;
struct wl_surface *drag_focus; struct wl_surface *drag_focus;