[PATCH wayland 1/2] add a dnd actions mechanism
Jason Ekstrand
jason at jlekstrand.net
Wed Mar 13 07:28:49 PDT 2013
On Wed, Mar 13, 2013 at 4:59 AM, Giulio Camuffo <giuliocamuffo at gmail.com> wrote:
> When creating a wl_data_source the client must now set certain supported
> actions on the data: COPY, MOVE or LINK. The target client will choose one
> of these (or IGNORE) after receiving the data and will notify the server
> which one it is, with wl_data_source_notify_received(). The wl_data_source
> will receive the wl_data_source_complete() event, with the accepted action,
> which means it must complete any pending task and free itself.
> If the wl_data_offer does not accept any mime type the drop event won't
> be delivered, but wl_data_source_cancelled() will be sent instead.
> ---
> protocol/wayland.xml | 54 +++++++++++++++++++++++++++++++++++++++++++++++++---
> src/data-device.c | 45 ++++++++++++++++++++++++++++++++++++++++---
> src/wayland-server.h | 4 ++++
> 3 files changed, 97 insertions(+), 6 deletions(-)
>
> diff --git a/protocol/wayland.xml b/protocol/wayland.xml
> index 0ce68ef..ee2d83f 100644
> --- a/protocol/wayland.xml
> +++ b/protocol/wayland.xml
> @@ -296,7 +296,7 @@
> </interface>
>
>
> - <interface name="wl_data_offer" version="1">
> + <interface name="wl_data_offer" version="2">
> <description summary="offer to transfer data">
> A wl_data_offer represents a piece of data offered for transfer
> by another client (the source client). It is used by the
> @@ -341,9 +341,36 @@
>
> <arg name="type" type="string"/>
> </event>
> +
> + <!-- Version 2 additions -->
> +
> + <event name="actions" since="2">
> + <description summary="notify the possible actions">
> + This event notifies the offer of the possible action the source
> + client supports. The target client must accept one of them, or else
> + the drop operation will be ignored.
> + </description>
> + <arg name="value" type="uint"/>
> + </event>
> +
> + <enum name="dnd_action" since="2">
> + <entry name="ignore" value="0"/>
> + <entry name="copy" value="1"/>
> + <entry name="move" value="2"/>
> + <entry name="link" value="4"/>
> + </enum>
> +
> + <request name="notify_received" since="2">
> + <description summary="notify that the data has been received">
> + The client must issue this request when it has received the data.
> + It must accept and send a valid action, which must be either one of
> + the actions sent by the source client or the IGNORE action.
> + </description>
> + <arg name="action" type="uint"/>
> + </request>
> </interface>
>
> - <interface name="wl_data_source" version="1">
> + <interface name="wl_data_source" version="2">
> <description summary="offer to transfer data">
> The wl_data_source object is the source side of a wl_data_offer.
> It is created by the source client in a data transfer and
> @@ -387,11 +414,32 @@
>
> <event name="cancelled">
> <description summary="selection was cancelled">
> - This data source has been replaced by another data source.
> + This data source has been replaced by another data source or
> + the drop operation was not accepted by the target client.
> The client should clean up and destroy this data source.
> </description>
> </event>
>
> + <!-- Version 2 additions -->
> +
> + <request name="set_actions" since="2">
> + <description summary="the data has been dropped">
> + Sets the actions the client supports for this operation.
> + The target client will chose one of them and will notify
> + this wl_data_source.
> + </description>
> + <arg name="actions" type="uint"/>
> + </request>
> +
> + <event name="complete" since="2">
> + <description summary="the data has been dropped">
> + This event notifies the source client that it should finish sending
> + the data and any other pending operation and then clean up. It carries
> + the action accepted by the target client.
> + </description>
> + <arg name="action" type="uint"/>
> + </event>
> +
> </interface>
>
> <interface name="wl_data_device" version="1">
> diff --git a/src/data-device.c b/src/data-device.c
> index 4255c13..7156e96 100644
> --- a/src/data-device.c
> +++ b/src/data-device.c
> @@ -55,6 +55,16 @@ data_offer_receive(struct wl_client *client, struct wl_resource *resource,
> }
>
> static void
> +data_offer_notify_received(struct wl_client *client, struct wl_resource *resource,
> + uint32_t action)
> +{
> + struct wl_data_offer *offer = resource->data;
> +
> + if (offer->source)
> + offer->source->complete(offer->source, action);
> +}
> +
> +static void
> data_offer_destroy(struct wl_client *client, struct wl_resource *resource)
> {
> wl_resource_destroy(resource);
> @@ -64,6 +74,7 @@ static const struct wl_data_offer_interface data_offer_interface = {
> data_offer_accept,
> data_offer_receive,
> data_offer_destroy,
> + data_offer_notify_received,
> };
>
> static void
> @@ -117,6 +128,7 @@ wl_data_source_send_offer(struct wl_data_source *source,
>
> wl_array_for_each(p, &source->mime_types)
> wl_data_offer_send_offer(&offer->resource, *p);
> + wl_data_offer_send_actions(&offer->resource, source->possible_actions);
>
> return &offer->resource;
> }
> @@ -142,9 +154,19 @@ 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 actions)
> +{
> + struct wl_data_source *source = resource->data;
> +
> + source->possible_actions = actions;
> +}
> +
> static struct wl_data_source_interface data_source_interface = {
> data_source_offer,
> - data_source_destroy
> + data_source_destroy,
> + data_source_set_actions
> };
>
> static struct wl_resource *
> @@ -253,8 +275,12 @@ drag_grab_button(struct wl_pointer_grab *grab,
>
> if (seat->drag_focus_resource &&
> seat->pointer->grab_button == button &&
> - state == WL_POINTER_BUTTON_STATE_RELEASED)
> - wl_data_device_send_drop(seat->drag_focus_resource);
> + state == WL_POINTER_BUTTON_STATE_RELEASED) {
> + if (seat->drag_data_source->accepted)
> + wl_data_device_send_drop(seat->drag_focus_resource);
> + else
> + seat->drag_data_source->cancel(seat->drag_data_source);
> + }
>
> if (seat->pointer->button_count == 0 &&
> state == WL_POINTER_BUTTON_STATE_RELEASED) {
> @@ -431,6 +457,7 @@ client_source_accept(struct wl_data_source *source,
> uint32_t time, const char *mime_type)
> {
> wl_data_source_send_target(&source->resource, mime_type);
> + source->accepted = mime_type != NULL;
> }
>
> static void
> @@ -448,6 +475,15 @@ client_source_cancel(struct wl_data_source *source)
> }
>
> static void
> +client_source_complete(struct wl_data_source *source, uint32_t action)
> +{
> + if (action & source->possible_actions)
> + wl_data_source_send_complete(&source->resource, action);
> + else
> + wl_data_source_send_complete(&source->resource, WL_DATA_OFFER_DND_ACTION_IGNORE);
> +}
> +
> +static void
> create_data_source(struct wl_client *client,
> struct wl_resource *resource, uint32_t id)
> {
> @@ -470,6 +506,9 @@ create_data_source(struct wl_client *client,
> source->accept = client_source_accept;
> source->send = client_source_send;
> source->cancel = client_source_cancel;
> + source->complete = client_source_complete;
> + source->possible_actions = WL_DATA_OFFER_DND_ACTION_IGNORE;
> + source->accepted = 0;
>
> wl_array_init(&source->mime_types);
> wl_client_add_resource(client, &source->resource);
> diff --git a/src/wayland-server.h b/src/wayland-server.h
> index c7369eb..5b38cae 100644
> --- a/src/wayland-server.h
> +++ b/src/wayland-server.h
> @@ -269,12 +269,16 @@ struct wl_data_offer {
> struct wl_data_source {
> struct wl_resource resource;
> struct wl_array mime_types;
> + uint32_t possible_actions;
> + int32_t accepted;
>
> void (*accept)(struct wl_data_source *source,
> uint32_t serial, const char *mime_type);
> void (*send)(struct wl_data_source *source,
> const char *mime_type, int32_t fd);
> void (*cancel)(struct wl_data_source *source);
> + void (*complete)(struct wl_data_source *source,
> + uint32_t action);
> };
>
> struct wl_pointer {
> --
> 1.8.1.5
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
In general, I like it and we've already talked about it some. I still
have two questions regarding the actions:
1. What exactly does the IGNORE action mean? I think it's probably
ok, but needs better documentation.
2. What actions do other toolkits (besides Qt) support? With that,
how should we expect toolkits that only support a subset of those
actions (or others not in that list) to handle actions? For example,
a quick scan through android d&d seems to indicate that they don't
really have actions at all. What actions should an android app
accept? what actions should it offer?
>From a quick scan of the GTK documentation, it looks like theirs is
similar, but they have a few more actions. Do we want to handle tese
as well?
https://developer.gnome.org/gdk/unstable/gdk-Drag-and-Drop.html#GdkDragAction
Really, I think what you've done so far is fantastic. I'm just trying
to bring this up now so that we can plan for the future a bit before
it gets codified in the wayland protocol.
Thanks,
--Jason Ekstrand
More information about the wayland-devel
mailing list