[PATCH wayland 1/2] add a dnd actions mechanism
Giulio Camuffo
giuliocamuffo at gmail.com
Wed Mar 13 02:59:32 PDT 2013
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
More information about the wayland-devel
mailing list