compositor: fix crash when a drag surface is destroyed during the drag
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>
Thu, 1 Mar 2012 12:09:44 +0000 (14:09 +0200)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 1 Mar 2012 22:33:51 +0000 (17:33 -0500)
This can happen for instance if the client that started the drag
crashes. Weston would crash because of the invalid surface pointed by
device->drag_surface.

Fix this by reseting the drag surface to nil on a destroy listener.

src/compositor.c
src/compositor.h

index 95513da..fe94523 100644 (file)
@@ -1832,6 +1832,18 @@ const static struct wl_input_device_interface input_device_interface = {
        input_device_attach,
 };
 
+static void
+handle_drag_surface_destroy(struct wl_listener *listener,
+                           struct wl_resource *resource, uint32_t time)
+{
+       struct weston_input_device *device;
+
+       device = container_of(listener, struct weston_input_device,
+                             drag_surface_destroy_listener);
+
+       device->drag_surface = NULL;
+}
+
 static void unbind_input_device(struct wl_resource *resource)
 {
        wl_list_remove(&resource->link);
@@ -1868,6 +1880,8 @@ weston_input_device_init(struct weston_input_device *device,
        device->modifier_state = 0;
        device->num_tp = 0;
 
+       device->drag_surface_destroy_listener.func = handle_drag_surface_destroy;
+
        wl_list_insert(ec->input_device_list.prev, &device->link);
 }
 
@@ -1902,6 +1916,7 @@ weston_input_update_drag_surface(struct wl_input_device *input_device,
 
        if (!input_device->drag_surface || surface_changed) {
                undef_region(&device->drag_surface->input);
+               wl_list_remove(&device->drag_surface_destroy_listener.link);
                device->drag_surface = NULL;
                if (!surface_changed)
                        return;
@@ -1913,6 +1928,8 @@ weston_input_update_drag_surface(struct wl_input_device *input_device,
 
                weston_surface_set_position(device->drag_surface,
                                            input_device->x, input_device->y);
+               wl_list_insert(device->drag_surface->surface.resource.destroy_listener_list.prev,
+                              &device->drag_surface_destroy_listener.link);
        }
 
        if (device->drag_surface->output == NULL &&
index d0b7206..6f46249 100644 (file)
@@ -107,6 +107,7 @@ struct weston_input_device {
        struct weston_compositor *compositor;
        struct weston_surface *sprite;
        struct weston_surface *drag_surface;
+       struct wl_listener drag_surface_destroy_listener;
        int32_t hotspot_x, hotspot_y;
        struct wl_list link;
        uint32_t modifier_state;