- DnD issues:
- How to roboustly handle failing drag, ie the case where an
- application gets a button event, tries to activate a drag, but when
- the server gets the drag request, the button has already been
- released and the grab is no longer active. What's the concern:
-
- - Application may set a drag cursor that doesn't revert back,
- since a failed drag doesn't result in a pointer_focus event to
- give focus back to the surface. We could just do that: if the
- pointer_focus is the same surface as we tried to start a grab
- for, just remove and give back pointer_focus.
-
- Alternatively, set drag cursors only in response to drag events,
- like drag focus. But drag_focus and drag_motion are sent to the
- drag target, so the source surface won't always get those. We
- may also end up setting the cursor after the drag ends, but in
- this case the drag started and ended and we'll get a
- pointer_focus event, which will make the application reset the
- pointer image. Could introduce a drag start event that
- indicates that the drag active.
-
How to handle drop decline (accept with type=NULL)
- Targets must send a NULL type in accept if they don't accept a
struct display *display;
uint32_t key;
struct item *items[16];
+
+ struct wl_buffer *buffer;
+ int hotspot_x, hotspot_y;
};
struct item {
drag_target(void *data,
struct wl_drag *drag, const char *mime_type)
{
+ struct dnd *dnd = 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 void
drag_data(void *data,
struct wl_drag *drag, struct wl_array *contents)
{
- fprintf(stderr, "drag drop, data %s\n", contents->data);
+ fprintf(stderr, "drag drop, data %s\n", (char *) contents->data);
}
static const struct wl_drag_listener drag_listener = {
int32_t x, y, hotspot_x, hotspot_y, pointer_width, pointer_height;
struct rectangle rectangle;
struct item *item;
- struct wl_buffer *buffer;
cairo_surface_t *surface, *pointer;
cairo_t *cr;
cairo_paint(cr);
cairo_destroy(cr);
- buffer = display_get_buffer_for_surface(dnd->display,
- surface);
- window_start_drag(window, input, time,
- buffer,
- pointer_width + x - item->x,
- pointer_height + y - item->y);
+ dnd->buffer = display_get_buffer_for_surface(dnd->display,
+ surface);
+ dnd->hotspot_x = pointer_width + x - item->x;
+ dnd->hotspot_y = pointer_height + y - item->y;
+
+ window_start_drag(window, input, time);
/* FIXME: We leak the surface because we can't free it
* until the server has referenced it. */
rectangle.height = 4 * (item_height + item_padding) + item_padding;
window_set_child_size(dnd->window, &rectangle);
+ display_add_drag_listener(display, &drag_listener, dnd);
+
dnd_draw(dnd);
return dnd;
d = display_create(&argc, &argv, option_entries);
- display_add_drag_listener(d, &drag_listener, d);
-
dnd = dnd_create (d);
display_run(d);
set_pointer_image(input, pointer);
}
-static void window_handle_button(void *data,
- struct wl_input_device *input_device,
- uint32_t time, uint32_t button, uint32_t state)
+static void
+window_handle_button(void *data,
+ struct wl_input_device *input_device,
+ uint32_t time, uint32_t button, uint32_t state)
{
struct input *input = data;
struct window *window = input->pointer_focus;
*y = input->sy;
}
+struct wl_input_device *
+input_get_input_device(struct input *input)
+{
+ return input->input_device;
+}
+
void
display_add_drag_listener(struct display *display,
const struct wl_drag_listener *drag_listener,
}
void
-window_start_drag(struct window *window, struct input *input, uint32_t time,
- struct wl_buffer *buffer, int32_t x, int32_t y)
+window_start_drag(struct window *window, struct input *input, uint32_t time)
{
cairo_device_flush (window->display->device);
- wl_drag_prepare(input->drag, window->surface, time, buffer, x, y);
+ wl_drag_prepare(input->drag, window->surface, time);
wl_drag_offer(input->drag, "text/plain");
wl_drag_activate(input->drag);
}
window_frame_handler_t handler);
void
-window_start_drag(struct window *window, struct input *input, uint32_t time,
- struct wl_buffer *buffer, int32_t x, int32_t y);
+window_start_drag(struct window *window, struct input *input, uint32_t time);
void
input_get_position(struct input *input, int32_t *x, int32_t *y);
+struct wl_input_device *
+input_get_input_device(struct input *input);
+
#endif
(struct wlsc_input_device *) device_base;
struct wlsc_buffer *buffer = (struct wlsc_buffer *) buffer_base;
- if (device->pointer_focus == NULL ||
- device->pointer_focus->base.client != client)
+ if (device->pointer_focus == NULL)
+ return;
+ if (device->pointer_focus->base.client != client &&
+ !(&device->pointer_focus->base == &wl_grab_surface &&
+ device->grab_surface->base.client == client))
return;
if (buffer == NULL) {
static void
drag_prepare(struct wl_client *client,
- struct wl_drag *drag, struct wl_surface *surface, uint32_t time,
- struct wl_buffer *buffer, int32_t hotspot_x, int32_t hotspot_y)
+ struct wl_drag *drag, struct wl_surface *surface, uint32_t time)
{
struct wlsc_input_device *device =
(struct wlsc_input_device *) drag->input_device;
wl_drag_reset(drag);
drag->source = surface;
drag->time = time;
- drag->buffer = buffer;
- drag->hotspot_x = hotspot_x;
- drag->hotspot_y = hotspot_y;
}
static void
wlsc_input_device_start_grab(device, drag->time,
WLSC_DEVICE_GRAB_DRAG);
- wlsc_input_device_attach(device, (struct wlsc_buffer *) drag->buffer,
- drag->hotspot_x, drag->hotspot_y);
surface = pick_surface(device, &sx, &sy);
wl_drag_set_pointer_focus(&device->drag, surface, drag->time,
grab started by the button click at time -->
<arg name="surface" type="object" interface="surface"/>
<arg name="time" type="uint"/>
- <arg name="buffer" type="object" interface="buffer"/>
- <arg name="hotspot_x" type="int"/>
- <arg name="hotspot_y" type="int"/>
</request>
<!-- Add an offered mime type. Can be called several times to
struct wl_array types;
const char *type;
uint32_t time;
-
- struct wl_buffer *buffer;
- int32_t hotspot_x;
- int32_t hotspot_y;
};
void