summaryrefslogtreecommitdiff
path: root/clients/dnd.c
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2010-08-27 20:29:56 -0400
committerKristian Høgsberg <krh@bitplanet.net>2010-08-27 20:30:26 -0400
commit4eb536091af7983847cef482072f053f1ab9d8b2 (patch)
treecb03daeeed0b48859c899e4a7bd821689fdb3fcf /clients/dnd.c
parentaebeee0bbfc0229f3a393b54df8c98a2722b3068 (diff)
Update drag protocol to use fd passing for data transfer
Diffstat (limited to 'clients/dnd.c')
-rw-r--r--clients/dnd.c77
1 files changed, 61 insertions, 16 deletions
diff --git a/clients/dnd.c b/clients/dnd.c
index 3df1202..07b8053 100644
--- a/clients/dnd.c
+++ b/clients/dnd.c
@@ -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