mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-21 06:59:46 -05:00
Update drag protocol to use fd passing for data transfer
This commit is contained in:
parent
aebeee0bbf
commit
4eb536091a
4 changed files with 105 additions and 52 deletions
|
|
@ -47,6 +47,8 @@ struct dnd {
|
||||||
|
|
||||||
struct wl_buffer *buffer;
|
struct wl_buffer *buffer;
|
||||||
int hotspot_x, hotspot_y;
|
int hotspot_x, hotspot_y;
|
||||||
|
uint32_t tag;
|
||||||
|
const char *drag_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct item {
|
struct item {
|
||||||
|
|
@ -221,9 +223,20 @@ drag_pointer_focus(void *data,
|
||||||
uint32_t time, struct wl_surface *surface,
|
uint32_t time, struct wl_surface *surface,
|
||||||
int32_t x, int32_t y, int32_t surface_x, int32_t surface_y)
|
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);
|
fprintf(stderr, "drag pointer focus %p\n", surface);
|
||||||
|
|
||||||
|
if (surface) {
|
||||||
wl_drag_accept(drag, "text/plain");
|
wl_drag_accept(drag, "text/plain");
|
||||||
|
dnd->drag_type = "text/plain";
|
||||||
|
} else {
|
||||||
|
dnd->drag_type = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -239,13 +252,14 @@ drag_motion(void *data,
|
||||||
uint32_t time,
|
uint32_t time,
|
||||||
int32_t x, int32_t y, int32_t surface_x, int32_t surface_y)
|
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.
|
/* FIXME: Need to correlate this with the offer event.
|
||||||
* Problem is, we don't know when we've seen that last offer
|
* 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
|
* event, and we might need to look at all of them before we
|
||||||
* can decide which one to go with. */
|
* can decide which one to go with. */
|
||||||
wl_drag_accept(drag, "text/plain");
|
wl_drag_accept(drag, "text/plain");
|
||||||
|
dnd->drag_type = "text/plain";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -256,32 +270,63 @@ drag_target(void *data,
|
||||||
struct input *input;
|
struct input *input;
|
||||||
struct wl_input_device *device;
|
struct wl_input_device *device;
|
||||||
|
|
||||||
fprintf(stderr, "target %s\n", mime_type);
|
|
||||||
|
|
||||||
input = wl_drag_get_user_data(drag);
|
input = wl_drag_get_user_data(drag);
|
||||||
device = input_get_input_device(input);
|
device = input_get_input_device(input);
|
||||||
wl_input_device_attach(device, dnd->buffer,
|
wl_input_device_attach(device, dnd->buffer,
|
||||||
dnd->hotspot_x, dnd->hotspot_y);
|
dnd->hotspot_x, dnd->hotspot_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
drag_finish(void *data, struct wl_drag *drag)
|
drop_io_func(GIOChannel *source, GIOCondition condition, gpointer data)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "drag finish\n");
|
struct dnd *dnd = data;
|
||||||
struct wl_array a;
|
char buffer[256];
|
||||||
char text[] = "[drop data]";
|
int fd;
|
||||||
|
unsigned int len;
|
||||||
|
GError *err = NULL;
|
||||||
|
|
||||||
a.data = text;
|
g_io_channel_read_chars(source, buffer, sizeof buffer, &len, &err);
|
||||||
a.size = sizeof text;
|
fprintf(stderr, "read %d bytes: %s\n", len, buffer);
|
||||||
|
fd = g_io_channel_unix_get_fd(source);
|
||||||
|
close(fd);
|
||||||
|
g_source_remove(dnd->tag);
|
||||||
|
|
||||||
wl_drag_send(drag, &a);
|
g_io_channel_unref(source);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drag_data(void *data,
|
drag_drop(void *data, struct wl_drag *drag)
|
||||||
struct wl_drag *drag, struct wl_array *contents)
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "drag drop, data %s\n", (char *) contents->data);
|
struct dnd *dnd = data;
|
||||||
|
int p[2];
|
||||||
|
GIOChannel *channel;
|
||||||
|
|
||||||
|
if (!dnd->drag_type) {
|
||||||
|
fprintf(stderr, "got 'drop', but no target\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_finish(void *data, struct wl_drag *drag, int fd)
|
||||||
|
{
|
||||||
|
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 = {
|
static const struct wl_drag_listener drag_listener = {
|
||||||
|
|
@ -290,8 +335,8 @@ static const struct wl_drag_listener drag_listener = {
|
||||||
drag_offer,
|
drag_offer,
|
||||||
drag_motion,
|
drag_motion,
|
||||||
drag_target,
|
drag_target,
|
||||||
drag_finish,
|
drag_drop,
|
||||||
drag_data
|
drag_finish
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -1120,13 +1120,12 @@ drag_target(void *data,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drag_finish(void *data, struct wl_drag *drag)
|
drag_drop(void *data, struct wl_drag *drag)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
drag_data(void *data,
|
drag_finish(void *data, struct wl_drag *drag, int fd)
|
||||||
struct wl_drag *drag, struct wl_array *contents)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1136,8 +1135,8 @@ static const struct wl_drag_listener drag_listener = {
|
||||||
drag_offer,
|
drag_offer,
|
||||||
drag_motion,
|
drag_motion,
|
||||||
drag_target,
|
drag_target,
|
||||||
drag_finish,
|
drag_drop,
|
||||||
drag_data
|
drag_finish
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
32
compositor.c
32
compositor.c
|
|
@ -823,9 +823,10 @@ wlsc_input_device_end_grab(struct wlsc_input_device *device, uint32_t time)
|
||||||
|
|
||||||
switch (device->grab) {
|
switch (device->grab) {
|
||||||
case WLSC_DEVICE_GRAB_DRAG:
|
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_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);
|
wl_drag_reset(drag);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
@ -1030,6 +1031,7 @@ wl_drag_set_pointer_focus(struct wl_drag *drag,
|
||||||
|
|
||||||
|
|
||||||
drag->pointer_focus = &surface->base;
|
drag->pointer_focus = &surface->base;
|
||||||
|
drag->target = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1043,12 +1045,12 @@ wl_drag_reset(struct wl_drag *drag)
|
||||||
wl_array_release(&drag->types);
|
wl_array_release(&drag->types);
|
||||||
wl_array_init(&drag->types);
|
wl_array_init(&drag->types);
|
||||||
|
|
||||||
drag->source = NULL;
|
|
||||||
|
|
||||||
/* FIXME: We need to reset drag->target too, but can't right
|
/* FIXME: We need to reset drag->target too, but can't right
|
||||||
* now because we need it for send/drop.
|
* now because we need it for send/drop.
|
||||||
*
|
*
|
||||||
* drag->target = NULL; */
|
* drag->target = NULL;
|
||||||
|
* drag->source = NULL;
|
||||||
|
*/
|
||||||
drag->time = 0;
|
drag->time = 0;
|
||||||
drag->pointer_focus = NULL;
|
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());
|
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
|
static void
|
||||||
drag_accept(struct wl_client *client,
|
drag_accept(struct wl_client *client,
|
||||||
struct wl_drag *drag, const char *type)
|
struct wl_drag *drag, const char *type)
|
||||||
|
|
@ -1181,13 +1175,21 @@ drag_accept(struct wl_client *client,
|
||||||
WL_DRAG_TARGET, drag->type);
|
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 = {
|
static const struct wl_drag_interface drag_interface = {
|
||||||
drag_prepare,
|
drag_prepare,
|
||||||
drag_offer,
|
drag_offer,
|
||||||
drag_activate,
|
drag_activate,
|
||||||
drag_cancel,
|
drag_cancel,
|
||||||
drag_send,
|
drag_accept,
|
||||||
drag_accept
|
drag_receive
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
37
protocol.xml
37
protocol.xml
|
|
@ -115,17 +115,19 @@
|
||||||
<!-- Cancel the drag. -->
|
<!-- Cancel the drag. -->
|
||||||
<request name="cancel"/>
|
<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
|
<!-- Called by the drag target to accept the offer of the given
|
||||||
type -->
|
type -->
|
||||||
<request name="accept">
|
<request name="accept">
|
||||||
<arg name="type" type="string"/>
|
<arg name="type" type="string"/>
|
||||||
</request>
|
</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 -->
|
<!-- Sent at connect time to announce the association -->
|
||||||
<event name="device">
|
<event name="device">
|
||||||
<arg name="device" type="object" interface="input_device"/>
|
<arg name="device" type="object" interface="input_device"/>
|
||||||
|
|
@ -167,18 +169,23 @@
|
||||||
<arg name="mime_type" type="string"/>
|
<arg name="mime_type" type="string"/>
|
||||||
</event>
|
</event>
|
||||||
|
|
||||||
<!-- Sent to drag originator when the drag is finished. It's also
|
<!-- Sent to target, to indicate that the drag is finishing. The
|
||||||
sent in case an originator tries to activate a drag after the
|
last motion/pointer_focus event gives the location of the
|
||||||
grab was released. If the originator didn't receive a
|
drop. Target must respond with the 'receive' request, which
|
||||||
'target' event before receiving the 'finish' event, no drag
|
sends an fd to the source for writing the drag data. -->
|
||||||
target was found and the originator should not send data. -->
|
<event name="drop"/>
|
||||||
<event name="finish"/>
|
|
||||||
|
|
||||||
<!-- Sent to target, contains dragged data. Ends transaction on
|
<!-- Sent to drag source when the drag is finished. The final
|
||||||
the target side. -->
|
mime type is that of the last target event. If that was
|
||||||
<event name="drop">
|
NULL, no drag target was valid when the drag finished, fd is
|
||||||
<arg name="contents" type="array"/>
|
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>
|
</event>
|
||||||
|
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="surface" version="1">
|
<interface name="surface" version="1">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue