Update drag protocol to use fd passing for data transfer

dev
Kristian Høgsberg 14 years ago
parent aebeee0bbf
commit 4eb536091a
  1. 77
      clients/dnd.c
  2. 9
      clients/window.c
  3. 32
      compositor.c
  4. 39
      protocol.xml

@ -47,6 +47,8 @@ struct dnd {
struct wl_buffer *buffer;
int hotspot_x, hotspot_y;
uint32_t tag;
const char *drag_type;
};
struct item {
@ -221,9 +223,20 @@ drag_pointer_focus(void *data,
uint32_t time, struct wl_surface *surface,
int32_t x, int32_t y, int32_t surface_x, int32_t surface_y)
{
struct dnd *dnd = data;
/* FIXME: We need the offered types before we get the
* pointer_focus event so we know which one we want and can
* send the accept request back. */
fprintf(stderr, "drag pointer focus %p\n", surface);
wl_drag_accept(drag, "text/plain");
if (surface) {
wl_drag_accept(drag, "text/plain");
dnd->drag_type = "text/plain";
} else {
dnd->drag_type = NULL;
}
}
static void
@ -239,13 +252,14 @@ drag_motion(void *data,
uint32_t time,
int32_t x, int32_t y, int32_t surface_x, int32_t surface_y)
{
fprintf(stderr, "drag motion %d,%d\n", surface_x, surface_y);
struct dnd *dnd = data;
/* FIXME: Need to correlate this with the offer event.
* Problem is, we don't know when we've seen that last offer
* event, and we might need to look at all of them before we
* can decide which one to go with. */
wl_drag_accept(drag, "text/plain");
dnd->drag_type = "text/plain";
}
static void
@ -256,32 +270,63 @@ drag_target(void *data,
struct input *input;
struct wl_input_device *device;
fprintf(stderr, "target %s\n", mime_type);
input = wl_drag_get_user_data(drag);
device = input_get_input_device(input);
wl_input_device_attach(device, dnd->buffer,
dnd->hotspot_x, dnd->hotspot_y);
}
static gboolean
drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
{
struct dnd *dnd = data;
char buffer[256];
int fd;
unsigned int len;
GError *err = NULL;
g_io_channel_read_chars(source, buffer, sizeof buffer, &len, &err);
fprintf(stderr, "read %d bytes: %s\n", len, buffer);
fd = g_io_channel_unix_get_fd(source);
close(fd);
g_source_remove(dnd->tag);
g_io_channel_unref(source);
return TRUE;
}
static void
drag_finish(void *data, struct wl_drag *drag)
drag_drop(void *data, struct wl_drag *drag)
{
fprintf(stderr, "drag finish\n");
struct wl_array a;
char text[] = "[drop data]";
struct dnd *dnd = data;
int p[2];
GIOChannel *channel;
a.data = text;
a.size = sizeof text;
if (!dnd->drag_type) {
fprintf(stderr, "got 'drop', but no target\n");
return;
}
wl_drag_send(drag, &a);
fprintf(stderr, "got 'drop', sending write end of pipe\n");
pipe(p);
wl_drag_receive(drag, p[1]);
close(p[1]);
channel = g_io_channel_unix_new(p[0]);
dnd->tag = g_io_add_watch(channel, G_IO_IN, drop_io_func, dnd);
}
static void
drag_data(void *data,
struct wl_drag *drag, struct wl_array *contents)
drag_finish(void *data, struct wl_drag *drag, int fd)
{
fprintf(stderr, "drag drop, data %s\n", (char *) contents->data);
char text[] = "[drop data]";
fprintf(stderr, "got 'finish', fd %d, sending message\n", fd);
write(fd, text, sizeof text);
close(fd);
}
static const struct wl_drag_listener drag_listener = {
@ -290,8 +335,8 @@ static const struct wl_drag_listener drag_listener = {
drag_offer,
drag_motion,
drag_target,
drag_finish,
drag_data
drag_drop,
drag_finish
};
static void

@ -1120,13 +1120,12 @@ drag_target(void *data,
}
static void
drag_finish(void *data, struct wl_drag *drag)
drag_drop(void *data, struct wl_drag *drag)
{
}
static void
drag_data(void *data,
struct wl_drag *drag, struct wl_array *contents)
drag_finish(void *data, struct wl_drag *drag, int fd)
{
}
@ -1136,8 +1135,8 @@ static const struct wl_drag_listener drag_listener = {
drag_offer,
drag_motion,
drag_target,
drag_finish,
drag_data
drag_drop,
drag_finish
};
static void

@ -823,9 +823,10 @@ wlsc_input_device_end_grab(struct wlsc_input_device *device, uint32_t time)
switch (device->grab) {
case WLSC_DEVICE_GRAB_DRAG:
if (drag->target)
wl_client_post_event(drag->target,
&drag->base, WL_DRAG_DROP);
wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
wl_surface_post_event(drag->source, &drag->base,
WL_DRAG_FINISH);
wl_drag_reset(drag);
break;
default:
@ -1030,6 +1031,7 @@ wl_drag_set_pointer_focus(struct wl_drag *drag,
drag->pointer_focus = &surface->base;
drag->target = NULL;
}
static void
@ -1043,12 +1045,12 @@ wl_drag_reset(struct wl_drag *drag)
wl_array_release(&drag->types);
wl_array_init(&drag->types);
drag->source = NULL;
/* FIXME: We need to reset drag->target too, but can't right
* now because we need it for send/drop.
*
* drag->target = NULL; */
* drag->target = NULL;
* drag->source = NULL;
*/
drag->time = 0;
drag->pointer_focus = NULL;
}
@ -1131,14 +1133,6 @@ drag_cancel(struct wl_client *client, struct wl_drag *drag)
wlsc_input_device_end_grab(device, get_time());
}
static void
drag_send(struct wl_client *client,
struct wl_drag *drag, struct wl_array *contents)
{
wl_client_post_event(drag->target,
&drag->base, WL_DRAG_DROP, contents);
}
static void
drag_accept(struct wl_client *client,
struct wl_drag *drag, const char *type)
@ -1181,13 +1175,21 @@ drag_accept(struct wl_client *client,
WL_DRAG_TARGET, drag->type);
}
static void
drag_receive(struct wl_client *client,
struct wl_drag *drag, int fd)
{
wl_surface_post_event(drag->source, &drag->base, WL_DRAG_FINISH, fd);
close(fd);
}
static const struct wl_drag_interface drag_interface = {
drag_prepare,
drag_offer,
drag_activate,
drag_cancel,
drag_send,
drag_accept
drag_accept,
drag_receive
};
static void

@ -115,17 +115,19 @@
<!-- Cancel the drag. -->
<request name="cancel"/>
<!-- Send the data to the target that accepted the offer -->
<request name="send">
<arg name="contents" type="array"/>
</request>
<!-- Called by the drag target to accept the offer of the given
type -->
<request name="accept">
<arg name="type" type="string"/>
</request>
<!-- Called by the drag target to initiate the drag finish
sequence. Send the pipe fd to the compositor, which forwards
it to the source in the 'finish' event -->
<request name="receive">
<arg name="fd" type="fd"/>
</request>
<!-- Sent at connect time to announce the association -->
<event name="device">
<arg name="device" type="object" interface="input_device"/>
@ -167,18 +169,23 @@
<arg name="mime_type" type="string"/>
</event>
<!-- Sent to drag originator when the drag is finished. It's also
sent in case an originator tries to activate a drag after the
grab was released. If the originator didn't receive a
'target' event before receiving the 'finish' event, no drag
target was found and the originator should not send data. -->
<event name="finish"/>
<!-- Sent to target, contains dragged data. Ends transaction on
the target side. -->
<event name="drop">
<arg name="contents" type="array"/>
<!-- Sent to target, to indicate that the drag is finishing. The
last motion/pointer_focus event gives the location of the
drop. Target must respond with the 'receive' request, which
sends an fd to the source for writing the drag data. -->
<event name="drop"/>
<!-- Sent to drag source when the drag is finished. The final
mime type is that of the last target event. If that was
NULL, no drag target was valid when the drag finished, fd is
undefined and the source should not send data. The event is
also sent in case a drag source tries to activate a drag
after the grab was released, in which case mime_type will
also be NULL. -->
<event name="finish">
<arg name="fd" type="fd"/>
</event>
</interface>
<interface name="surface" version="1">

Loading…
Cancel
Save