Reviewed-by: Michael Catanzaro <mcatanzaro at igalia.com>
On Wed, 2015-09-30 at 22:50 +0200, 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 set_actions requests on both wl_data_source and > wl_data_offer, weston now will emit the newly added "action" events > notifying both source and dest of the chosen action. > > The "dnd" client has been updated too (although minimally), so it > notifies the compositor of a "move" action on both sides. > > Changes since v2: > - Split from DnD progress notification changes. > > Changes since v1: > - Updated to v2 of DnD actions protocol changes, implement > wl_data_offer.source_actions. > - Fixed coding style issues. > > Signed-off-by: Carlos Garnacho <carl...@gnome.org> > --- > clients/dnd.c | 12 +++++++++ > clients/window.c | 25 +++++++++++++++++++ > src/compositor.h | 4 +++ > src/data-device.c | 75 > ++++++++++++++++++++++++++++++++++++++++++++++++++++--- > 4 files changed, 113 insertions(+), 3 deletions(-) > > diff --git a/clients/dnd.c b/clients/dnd.c > index 6c2ed57..75a14f1 100644 > --- a/clients/dnd.c > +++ b/clients/dnd.c > @@ -72,6 +72,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; > @@ -360,12 +361,21 @@ data_source_drag_finished(void *data, struct > wl_data_source *source) > destroy_dnd_drag(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 const struct wl_data_source_listener data_source_listener = { > data_source_target, > data_source_send, > data_source_cancelled, > data_source_drop_performed, > data_source_drag_finished, > + data_source_action, > }; > > static cairo_surface_t * > @@ -461,6 +471,8 @@ create_drag_source(struct dnd *dnd, > window_get_wl_surface(dnd > ->window), > dnd_drag->drag_surface, > serial); > + wl_data_source_set_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 feb9515..97c3679 100644 > --- a/clients/window.c > +++ b/clients/window.c > @@ -3350,6 +3350,8 @@ struct data_offer { > int fd; > data_func_t func; > int32_t x, y; > + uint32_t dnd_action; > + uint32_t source_actions; > void *user_data; > }; > > @@ -3363,8 +3365,26 @@ data_offer_offer(void *data, struct > wl_data_offer *wl_data_offer, const char *ty > *p = strdup(type); > } > > +static void > +data_offer_source_actions(void *data, struct wl_data_offer > *wl_data_offer, uint32_t source_actions) > +{ > + struct data_offer *offer = data; > + > + offer->source_actions = source_actions; > +} > + > +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_source_actions, > + data_offer_action > }; > > static void > @@ -3428,6 +3448,11 @@ data_device_enter(void *data, struct > wl_data_device *data_device, > *p = NULL; > > types_data = input->drag_offer->types.data; > + wl_data_offer_set_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; > diff --git a/src/compositor.h b/src/compositor.h > index 40c02c2..969b9fe 100644 > --- a/src/compositor.h > +++ b/src/compositor.h > @@ -300,6 +300,8 @@ 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 { > @@ -308,6 +310,8 @@ struct weston_data_source { > struct wl_array mime_types; > struct weston_data_offer *offer; > int accepted; > + 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 c5aac55..a6a7085 100644 > --- a/src/data-device.c > +++ b/src/data-device.c > @@ -98,10 +98,56 @@ 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_set_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_set_actions > }; > > static void > @@ -144,7 +190,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; > @@ -165,6 +211,7 @@ weston_data_source_send_offer(struct > weston_data_source *source, > > source->offer = offer; > source->accepted = 0; > + data_offer_update_action(offer); > > return offer->resource; > } > @@ -191,9 +238,30 @@ data_source_destroy(struct wl_client *client, > struct wl_resource *resource) > wl_resource_destroy(resource); > } > > +static void > +data_source_set_actions(struct wl_client *client, > + struct wl_resource *resource, > + uint32_t dnd_actions) > +{ > + struct weston_data_source *source = > + wl_resource_get_user_data(resource); > + > + if (source->dnd_actions == dnd_actions) > + return; > + > + source->dnd_actions = dnd_actions; > + > + if (source->offer) { > + wl_data_offer_send_source_actions(source->offer > ->resource, > + dnd_actions); > + 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_set_actions > }; > > static void > @@ -421,7 +489,8 @@ drag_grab_button(struct weston_pointer_grab > *grab, > drag->base.data_source && > pointer->grab_button == button && > state == WL_POINTER_BUTTON_STATE_RELEASED) { > - if (drag->base.data_source->accepted) { > + if (drag->base.data_source->accepted && > + 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 { _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel