[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