with the surface ref-count feature a surface may live on after its
resource was destroyed. so listen for the resource destroy signal
and set the focus to NULL.
---
 src/compositor.c |  4 ++++
 src/compositor.h |  3 +++
 src/input.c      | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 58 insertions(+), 1 deletion(-)

diff --git a/src/compositor.c b/src/compositor.c
index 9757a75..6b38e38 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1148,6 +1148,10 @@ destroy_surface(struct wl_resource *resource)
 {
        struct weston_surface *surface = wl_resource_get_user_data(resource);
 
+       /* Set the resource to NULL, since we don't want to leave a
+        * dangling pointer if the surface was refcounted and survives
+        * the weston_surface_destroy() call. */
+       surface->resource = NULL;
        weston_surface_destroy(surface);
 }
 
diff --git a/src/compositor.h b/src/compositor.h
index 5257356..1408110 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -312,6 +312,7 @@ struct weston_pointer {
        struct wl_list resource_list;
        struct wl_list focus_resource_list;
        struct weston_surface *focus;
+       struct wl_listener focus_listener;
        uint32_t focus_serial;
        struct wl_signal focus_signal;
 
@@ -337,6 +338,7 @@ struct weston_touch {
        struct wl_list resource_list;
        struct wl_list focus_resource_list;
        struct weston_surface *focus;
+       struct wl_listener focus_listener;
        uint32_t focus_serial;
        struct wl_signal focus_signal;
 
@@ -431,6 +433,7 @@ struct weston_keyboard {
        struct wl_list resource_list;
        struct wl_list focus_resource_list;
        struct weston_surface *focus;
+       struct wl_listener focus_listener;
        uint32_t focus_serial;
        struct wl_signal focus_signal;
 
diff --git a/src/input.c b/src/input.c
index 1313b52..644f30a 100644
--- a/src/input.c
+++ b/src/input.c
@@ -71,6 +71,33 @@ weston_compositor_idle_release(struct weston_compositor 
*compositor)
 }
 
 static void
+lose_pointer_focus(struct wl_listener *listener, void *data)
+{
+       struct weston_pointer *pointer =
+               container_of(listener, struct weston_pointer, focus_listener);
+
+       weston_pointer_set_focus(pointer, NULL, 0, 0);
+}
+
+static void
+lose_keyboard_focus(struct wl_listener *listener, void *data)
+{
+       struct weston_keyboard *keyboard =
+               container_of(listener, struct weston_keyboard, focus_listener);
+
+       weston_keyboard_set_focus(keyboard, NULL);
+}
+
+static void
+lose_touch_focus(struct wl_listener *listener, void *data)
+{
+       struct weston_touch *touch =
+               container_of(listener, struct weston_touch, focus_listener);
+
+       weston_touch_set_focus(touch->seat, NULL);
+}
+
+static void
 move_resources(struct wl_list *destination, struct wl_list *source)
 {
        wl_list_insert_list(destination, source);
@@ -360,6 +387,8 @@ weston_pointer_create(void)
 
        wl_list_init(&pointer->resource_list);
        wl_list_init(&pointer->focus_resource_list);
+       wl_list_init(&pointer->focus_listener.link);
+       pointer->focus_listener.notify = lose_pointer_focus;
        pointer->default_grab.interface = &default_pointer_grab_interface;
        pointer->default_grab.pointer = pointer;
        pointer->grab = &pointer->default_grab;
@@ -381,7 +410,7 @@ weston_pointer_destroy(struct weston_pointer *pointer)
                pointer_unmap_sprite(pointer);
 
        /* XXX: What about pointer->resource_list? */
-
+       wl_list_remove(&pointer->focus_listener.link);
        free(pointer);
 }
 
@@ -396,6 +425,8 @@ weston_keyboard_create(void)
 
        wl_list_init(&keyboard->resource_list);
        wl_list_init(&keyboard->focus_resource_list);
+       wl_list_init(&keyboard->focus_listener.link);
+       keyboard->focus_listener.notify = lose_keyboard_focus;
        wl_array_init(&keyboard->keys);
        keyboard->default_grab.interface = &default_keyboard_grab_interface;
        keyboard->default_grab.keyboard = keyboard;
@@ -411,6 +442,7 @@ weston_keyboard_destroy(struct weston_keyboard *keyboard)
        /* XXX: What about keyboard->resource_list? */
 
        wl_array_release(&keyboard->keys);
+       wl_list_remove(&keyboard->focus_listener.link);
        free(keyboard);
 }
 
@@ -425,6 +457,8 @@ weston_touch_create(void)
 
        wl_list_init(&touch->resource_list);
        wl_list_init(&touch->focus_resource_list);
+       wl_list_init(&touch->focus_listener.link);
+       touch->focus_listener.notify = lose_touch_focus;
        touch->default_grab.interface = &default_touch_grab_interface;
        touch->default_grab.touch = touch;
        touch->grab = &touch->default_grab;
@@ -438,6 +472,7 @@ weston_touch_destroy(struct weston_touch *touch)
 {
        /* XXX: What about touch->resource_list? */
 
+       wl_list_remove(&touch->focus_listener.link);
        free(touch);
 }
 
@@ -479,6 +514,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
                                              pointer->focus->resource);
                }
 
+               wl_list_remove(&pointer->focus_listener.link);
+               wl_list_init(&pointer->focus_listener.link);
                move_resources(&pointer->resource_list, focus_resource_list);
        }
 
@@ -501,6 +538,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
                }
 
                pointer->focus_serial = serial;
+               wl_resource_add_destroy_listener(surface->resource,
+                                                &pointer->focus_listener);
        }
 
        if (kbd && surface && surface->resource && kbd->focus != 
pointer->focus) {
@@ -549,6 +588,8 @@ weston_keyboard_set_focus(struct weston_keyboard *keyboard,
                        wl_keyboard_send_leave(resource, serial,
                                        keyboard->focus->resource);
                }
+               wl_list_remove(&keyboard->focus_listener.link);
+               wl_list_init(&keyboard->focus_listener.link);
                move_resources(&keyboard->resource_list, focus_resource_list);
        }
 
@@ -567,6 +608,8 @@ weston_keyboard_set_focus(struct weston_keyboard *keyboard,
                                            surface,
                                            serial);
                keyboard->focus_serial = serial;
+               wl_resource_add_destroy_listener(surface->resource,
+                                                &keyboard->focus_listener);
        }
 
        keyboard->focus = surface;
@@ -1059,6 +1102,11 @@ weston_touch_set_focus(struct weston_seat *seat, struct 
weston_surface *surface)
        if (seat->touch->focus == surface)
                return;
 
+       if (seat->touch->focus) {
+               wl_list_remove(&seat->touch->focus_listener.link);
+               wl_list_init(&seat->touch->focus_listener.link);
+       }
+
        if (!wl_list_empty(focus_resource_list)) {
                move_resources(&seat->touch->resource_list,
                               focus_resource_list);
@@ -1070,6 +1118,8 @@ weston_touch_set_focus(struct weston_seat *seat, struct 
weston_surface *surface)
                move_resources_for_client(focus_resource_list,
                                          &seat->touch->resource_list,
                                          surface_client);
+               wl_resource_add_destroy_listener(surface->resource,
+                                                &seat->touch->focus_listener);
        }
        seat->touch->focus = surface;
 }
-- 
1.8.4

_______________________________________________
wayland-devel mailing list
wayland-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to