diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2010-08-27 20:29:56 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2010-08-27 20:30:26 -0400 |
commit | 4eb536091af7983847cef482072f053f1ab9d8b2 (patch) | |
tree | cb03daeeed0b48859c899e4a7bd821689fdb3fcf /clients/dnd.c | |
parent | aebeee0bbfc0229f3a393b54df8c98a2722b3068 (diff) |
Update drag protocol to use fd passing for data transfer
Diffstat (limited to 'clients/dnd.c')
-rw-r--r-- | clients/dnd.c | 77 |
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 |