Set pointer image only in response to 'target' event
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 25 Aug 2010 20:34:05 +0000 (16:34 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 25 Aug 2010 20:34:05 +0000 (16:34 -0400)
TODO
clients/dnd.c
clients/window.c
clients/window.h
compositor.c
protocol.xml
wayland-server.h

diff --git a/TODO b/TODO
index 7c58898..3fe9b99 100644 (file)
--- a/TODO
+++ b/TODO
@@ -16,26 +16,6 @@ Core wayland protocol
 
  - 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
index 0557ed9..3df1202 100644 (file)
@@ -44,6 +44,9 @@ struct dnd {
        struct display *display;
        uint32_t key;
        struct item *items[16];
+
+       struct wl_buffer *buffer;
+       int hotspot_x, hotspot_y;
 };
 
 struct item {
@@ -249,7 +252,16 @@ static void
 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
@@ -269,7 +281,7 @@ 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 = {
@@ -291,7 +303,6 @@ dnd_button_handler(struct window *window,
        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;
 
@@ -334,12 +345,12 @@ dnd_button_handler(struct window *window,
                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. */
@@ -407,6 +418,8 @@ dnd_create(struct display *display)
        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;
@@ -428,8 +441,6 @@ main(int argc, char *argv[])
 
        d = display_create(&argc, &argv, option_entries);
 
-       display_add_drag_listener(d, &drag_listener, d);
-
        dnd = dnd_create (d);
 
        display_run(d);
index 2b88e09..7c2579d 100644 (file)
@@ -561,9 +561,10 @@ window_handle_motion(void *data, struct wl_input_device *input_device,
        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;
@@ -717,6 +718,12 @@ input_get_position(struct input *input, int32_t *x, int32_t *y)
        *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,
@@ -729,12 +736,11 @@ display_add_drag_listener(struct display *display,
 }
 
 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);
 }
index 2c0b49b..a1f58e9 100644 (file)
@@ -188,10 +188,12 @@ window_set_frame_handler(struct window *window,
                         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
index 2155d42..09c77ca 100644 (file)
@@ -952,8 +952,11 @@ input_device_attach(struct wl_client *client,
                (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) {
@@ -1052,8 +1055,7 @@ wl_drag_reset(struct wl_drag *drag)
 
 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;
@@ -1065,9 +1067,6 @@ drag_prepare(struct wl_client *client,
        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
@@ -1112,8 +1111,6 @@ drag_activate(struct wl_client *client,
 
        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,
index 9abeffa..01d8a73 100644 (file)
           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
index 9b7cef3..acfe791 100644 (file)
@@ -134,10 +134,6 @@ struct wl_drag {
        struct wl_array types;
        const char *type;
        uint32_t time;
-
-       struct wl_buffer *buffer;
-       int32_t hotspot_x;
-       int32_t hotspot_y;
 };
 
 void