On Mon, Feb 16, 2015 at 04:37:35PM +0100, Carlos Garnacho wrote: > The policy in weston in order to determine the chosen DnD action is > deliberately simple, and is probably the minimals that any compositor > should be doing here. > > Besides honoring the notify_actions requests on both wl_data_source > and wl_data_offer, weston now emits the newly added events notifying > both source and dest sides of the chosen action and operation progress. > > The "dnd" client has been updated too (although minimally), so it > notifies the compositor of a "move" action on both sides. > > Signed-off-by: Carlos Garnacho <carl...@gnome.org>
Seems like a reasonable implementation of the proposed protocol. Reviewed-by: Bryce Harrington <br...@osg.samsung.com> > --- > clients/dnd.c | 26 +++++++++++++++- > clients/window.c | 17 ++++++++++- > src/compositor.h | 5 +++ > src/data-device.c | 91 > ++++++++++++++++++++++++++++++++++++++++++++++++++----- > 4 files changed, 130 insertions(+), 9 deletions(-) > > diff --git a/clients/dnd.c b/clients/dnd.c > index e893d36..c9da1d0 100644 > --- a/clients/dnd.c > +++ b/clients/dnd.c > @@ -70,6 +70,7 @@ struct dnd_drag { > struct item *item; > int x_offset, y_offset; > int width, height; > + uint32_t dnd_action; > const char *mime_type; > > struct wl_surface *drag_surface; > @@ -337,10 +338,31 @@ data_source_cancelled(void *data, struct wl_data_source > *source) > free(dnd_drag); > } > > +static void > +data_source_action(void *data, struct wl_data_source *source, uint32_t > dnd_action) > +{ > + struct dnd_drag *dnd_drag = data; > + > + dnd_drag->dnd_action = dnd_action; > +} > + > +static void > +data_source_drop_performed(void *data, struct wl_data_source *source) > +{ > +} > + > +static void > +data_source_finished(void *data, struct wl_data_source *source) > +{ > +} > + > static const struct wl_data_source_listener data_source_listener = { > data_source_target, > data_source_send, > - data_source_cancelled > + data_source_cancelled, > + data_source_action, > + data_source_drop_performed, > + data_source_finished > }; > > static cairo_surface_t * > @@ -436,6 +458,8 @@ create_drag_source(struct dnd *dnd, > window_get_wl_surface(dnd->window), > dnd_drag->drag_surface, > serial); > + wl_data_source_notify_actions (dnd_drag->data_source, > + > WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE); > > dnd_drag->opaque = > create_drag_icon(dnd_drag, item, x, y, 1); > diff --git a/clients/window.c b/clients/window.c > index c5082ba..fa654df 100644 > --- a/clients/window.c > +++ b/clients/window.c > @@ -3320,6 +3320,7 @@ struct data_offer { > int fd; > data_func_t func; > int32_t x, y; > + uint32_t dnd_action; > void *user_data; > }; > > @@ -3333,8 +3334,17 @@ data_offer_offer(void *data, struct wl_data_offer > *wl_data_offer, const char *ty > *p = strdup(type); > } > > +static void > +data_offer_action(void *data, struct wl_data_offer *wl_data_offer, uint32_t > dnd_action) > +{ > + struct data_offer *offer = data; > + > + offer->dnd_action = dnd_action; > +} > + > static const struct wl_data_offer_listener data_offer_listener = { > data_offer_offer, > + data_offer_action > }; > > static void > @@ -3398,6 +3408,11 @@ data_device_enter(void *data, struct wl_data_device > *data_device, > *p = NULL; > > types_data = input->drag_offer->types.data; > + wl_data_offer_notify_actions (offer, > + > WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY | > + > WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE, > + > WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY); > + > } else { > input->drag_offer = NULL; > types_data = NULL; > @@ -5277,7 +5292,7 @@ registry_handle_global(void *data, struct wl_registry > *registry, uint32_t id, > d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); > wl_shm_add_listener(d->shm, &shm_listener, d); > } else if (strcmp(interface, "wl_data_device_manager") == 0) { > - d->data_device_manager_version = MIN(version, 2); > + d->data_device_manager_version = MIN(version, 3); > d->data_device_manager = > wl_registry_bind(registry, id, > &wl_data_device_manager_interface, > diff --git a/src/compositor.h b/src/compositor.h > index 5c0ea74..0adcde6 100644 > --- a/src/compositor.h > +++ b/src/compositor.h > @@ -298,12 +298,17 @@ struct weston_data_offer { > struct wl_resource *resource; > struct weston_data_source *source; > struct wl_listener source_destroy_listener; > + uint32_t dnd_actions; > + uint32_t preferred_dnd_action; > }; > > struct weston_data_source { > struct wl_resource *resource; > struct wl_signal destroy_signal; > struct wl_array mime_types; > + struct weston_data_offer *offer; > + uint32_t dnd_actions; > + uint32_t current_dnd_action; > > void (*accept)(struct weston_data_source *source, > uint32_t serial, const char *mime_type); > diff --git a/src/data-device.c b/src/data-device.c > index a0913a2..e5fa128 100644 > --- a/src/data-device.c > +++ b/src/data-device.c > @@ -84,10 +84,57 @@ data_offer_destroy(struct wl_client *client, struct > wl_resource *resource) > wl_resource_destroy(resource); > } > > +static uint32_t > +data_offer_choose_action (struct weston_data_offer *offer) > +{ > + uint32_t available_actions; > + > + available_actions = offer->dnd_actions & offer->source->dnd_actions; > + > + if (!available_actions) > + return 0; > + > + /* If the dest side has a preferred DnD action, use it */ > + if ((offer->preferred_dnd_action & available_actions) != 0) > + return offer->preferred_dnd_action; > + > + /* Use the first found action, in bit order */ > + return 1 << (ffs (available_actions) - 1); > +} > + > +static void > +data_offer_update_action (struct weston_data_offer *offer) > +{ > + uint32_t action; > + > + action = data_offer_choose_action (offer); > + > + if (offer->source->current_dnd_action == action) > + return; > + > + offer->source->current_dnd_action = action; > + wl_data_source_send_action (offer->source->resource, action); > + wl_data_offer_send_action (offer->resource, action); > +} > + > +static void > +data_offer_notify_actions (struct wl_client *client, > + struct wl_resource *resource, > + uint32_t dnd_actions, > + uint32_t preferred_action) > +{ > + struct weston_data_offer *offer = wl_resource_get_user_data(resource); > + > + offer->dnd_actions = dnd_actions; > + offer->preferred_dnd_action = preferred_action; > + data_offer_update_action (offer); > +} > + > static const struct wl_data_offer_interface data_offer_interface = { > data_offer_accept, > data_offer_receive, > data_offer_destroy, > + data_offer_notify_actions > }; > > static void > @@ -95,8 +142,14 @@ destroy_data_offer(struct wl_resource *resource) > { > struct weston_data_offer *offer = wl_resource_get_user_data(resource); > > - if (offer->source) > + if (offer->source) { > + if (offer->source->offer == offer) { > + wl_data_source_send_finished(offer->source->resource); > + offer->source->offer = NULL; > + } > + > wl_list_remove(&offer->source_destroy_listener.link); > + } > free(offer); > } > > @@ -124,7 +177,7 @@ weston_data_source_send_offer(struct weston_data_source > *source, > > offer->resource = > wl_resource_create(wl_resource_get_client(target), > - &wl_data_offer_interface, 1, 0); > + &wl_data_offer_interface, 3, 0); > if (offer->resource == NULL) { > free(offer); > return NULL; > @@ -143,6 +196,9 @@ weston_data_source_send_offer(struct weston_data_source > *source, > wl_array_for_each(p, &source->mime_types) > wl_data_offer_send_offer(offer->resource, *p); > > + data_offer_update_action (offer); > + source->offer = offer; > + > return offer->resource; > } > > @@ -168,9 +224,24 @@ data_source_destroy(struct wl_client *client, struct > wl_resource *resource) > wl_resource_destroy(resource); > } > > +static void > +data_source_notify_actions (struct wl_client *client, > + struct wl_resource *resource, > + uint32_t dnd_actions) > +{ > + struct weston_data_source *source = > + wl_resource_get_user_data(resource); > + > + source->dnd_actions = dnd_actions; > + > + if (source->offer) > + data_offer_update_action (source->offer); > +} > + > static struct wl_data_source_interface data_source_interface = { > data_source_offer, > - data_source_destroy > + data_source_destroy, > + data_source_notify_actions > }; > > static void > @@ -395,8 +466,14 @@ drag_grab_button(struct weston_pointer_grab *grab, > > if (drag->base.focus_resource && > pointer->grab_button == button && > - state == WL_POINTER_BUTTON_STATE_RELEASED) > - wl_data_device_send_drop(drag->base.focus_resource); > + state == WL_POINTER_BUTTON_STATE_RELEASED) { > + if (drag->base.data_source->current_dnd_action) { > + wl_data_device_send_drop(drag->base.focus_resource); > + > wl_data_source_send_drop_performed(drag->base.data_source->resource); > + } else if (drag->base.data_source) { > + > wl_data_source_send_cancelled(drag->base.data_source->resource); > + } > + } > > if (pointer->button_count == 0 && > state == WL_POINTER_BUTTON_STATE_RELEASED) { > @@ -851,7 +928,7 @@ create_data_source(struct wl_client *client, > wl_array_init(&source->mime_types); > > source->resource = > - wl_resource_create(client, &wl_data_source_interface, 1, id); > + wl_resource_create(client, &wl_data_source_interface, 3, id); > wl_resource_set_implementation(source->resource, &data_source_interface, > source, destroy_data_source); > } > @@ -937,7 +1014,7 @@ WL_EXPORT int > wl_data_device_manager_init(struct wl_display *display) > { > if (wl_global_create(display, > - &wl_data_device_manager_interface, 2, > + &wl_data_device_manager_interface, 3, > NULL, bind_manager) == NULL) > return -1; > > -- > 2.1.0 > > _______________________________________________ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel