Commit 75a5f747 authored by Ander Conselvan de Oliveira's avatar Ander Conselvan de Oliveira Committed by Kristian Høgsberg
Browse files

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.
parent d422a733
......@@ -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
......
......@@ -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"/>
......
......@@ -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;
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment