input: set the focus to NULL when the focus's resource is destroyed
authorGiulio Camuffo <giuliocamuffo@gmail.com>
Wed, 20 Nov 2013 17:00:24 +0000 (18:00 +0100)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 21 Nov 2013 00:59:00 +0000 (16:59 -0800)
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.

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
src/compositor.h
src/input.c

index b84289a..526f3d1 100644 (file)
@@ -308,7 +308,8 @@ struct weston_pointer {
        struct wl_list focus_resource_list;
        struct weston_view *focus;
        uint32_t focus_serial;
-       struct wl_listener focus_listener;
+       struct wl_listener focus_view_listener;
+       struct wl_listener focus_resource_listener;
        struct wl_signal focus_signal;
        struct wl_signal motion_signal;
 
@@ -334,6 +335,8 @@ struct weston_touch {
        struct wl_list resource_list;
        struct wl_list focus_resource_list;
        struct weston_view *focus;
+       struct wl_listener focus_view_listener;
+       struct wl_listener focus_resource_listener;
        uint32_t focus_serial;
        struct wl_signal focus_signal;
 
@@ -435,6 +438,7 @@ struct weston_keyboard {
        struct wl_list resource_list;
        struct wl_list focus_resource_list;
        struct weston_surface *focus;
+       struct wl_listener focus_resource_listener;
        uint32_t focus_serial;
        struct wl_signal focus_signal;
 
index e285c59..06a3c2e 100644 (file)
@@ -71,6 +71,56 @@ weston_compositor_idle_release(struct weston_compositor *compositor)
 }
 
 static void
+pointer_focus_view_destroyed(struct wl_listener *listener, void *data)
+{
+       struct weston_pointer *pointer =
+               container_of(listener, struct weston_pointer,
+                            focus_view_listener);
+
+       weston_pointer_set_focus(pointer, NULL, 0, 0);
+}
+
+static void
+pointer_focus_resource_destroyed(struct wl_listener *listener, void *data)
+{
+       struct weston_pointer *pointer =
+               container_of(listener, struct weston_pointer,
+                            focus_resource_listener);
+
+       weston_pointer_set_focus(pointer, NULL, 0, 0);
+}
+
+static void
+keyboard_focus_resource_destroyed(struct wl_listener *listener, void *data)
+{
+       struct weston_keyboard *keyboard =
+               container_of(listener, struct weston_keyboard,
+                            focus_resource_listener);
+
+       weston_keyboard_set_focus(keyboard, NULL);
+}
+
+static void
+touch_focus_view_destroyed(struct wl_listener *listener, void *data)
+{
+       struct weston_touch *touch =
+               container_of(listener, struct weston_touch,
+                            focus_view_listener);
+
+       weston_touch_set_focus(touch->seat, NULL);
+}
+
+static void
+touch_focus_resource_destroyed(struct wl_listener *listener, void *data)
+{
+       struct weston_touch *touch =
+               container_of(listener, struct weston_touch,
+                            focus_resource_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);
@@ -394,11 +444,13 @@ weston_pointer_create(struct weston_seat *seat)
        wl_list_init(&pointer->focus_resource_list);
        weston_pointer_set_default_grab(pointer,
                                        seat->compositor->default_pointer_grab);
+       wl_list_init(&pointer->focus_resource_listener.link);
+       pointer->focus_resource_listener.notify = pointer_focus_resource_destroyed;
        pointer->default_grab.pointer = pointer;
        pointer->grab = &pointer->default_grab;
        wl_signal_init(&pointer->motion_signal);
        wl_signal_init(&pointer->focus_signal);
-       wl_list_init(&pointer->focus_listener.link);
+       wl_list_init(&pointer->focus_view_listener.link);
 
        pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy;
 
@@ -417,6 +469,8 @@ weston_pointer_destroy(struct weston_pointer *pointer)
 
        /* XXX: What about pointer->resource_list? */
 
+       wl_list_remove(&pointer->focus_resource_listener.link);
+       wl_list_remove(&pointer->focus_view_listener.link);
        free(pointer);
 }
 
@@ -442,6 +496,8 @@ weston_keyboard_create(void)
 
        wl_list_init(&keyboard->resource_list);
        wl_list_init(&keyboard->focus_resource_list);
+       wl_list_init(&keyboard->focus_resource_listener.link);
+       keyboard->focus_resource_listener.notify = keyboard_focus_resource_destroyed;
        wl_array_init(&keyboard->keys);
        keyboard->default_grab.interface = &default_keyboard_grab_interface;
        keyboard->default_grab.keyboard = keyboard;
@@ -457,6 +513,7 @@ weston_keyboard_destroy(struct weston_keyboard *keyboard)
        /* XXX: What about keyboard->resource_list? */
 
        wl_array_release(&keyboard->keys);
+       wl_list_remove(&keyboard->focus_resource_listener.link);
        free(keyboard);
 }
 
@@ -471,6 +528,10 @@ weston_touch_create(void)
 
        wl_list_init(&touch->resource_list);
        wl_list_init(&touch->focus_resource_list);
+       wl_list_init(&touch->focus_view_listener.link);
+       touch->focus_view_listener.notify = touch_focus_view_destroyed;
+       wl_list_init(&touch->focus_resource_listener.link);
+       touch->focus_resource_listener.notify = touch_focus_resource_destroyed;
        touch->default_grab.interface = &default_touch_grab_interface;
        touch->default_grab.touch = touch;
        touch->grab = &touch->default_grab;
@@ -484,6 +545,8 @@ weston_touch_destroy(struct weston_touch *touch)
 {
        /* XXX: What about touch->resource_list? */
 
+       wl_list_remove(&touch->focus_view_listener.link);
+       wl_list_remove(&touch->focus_resource_listener.link);
        free(touch);
 }
 
@@ -505,23 +568,6 @@ seat_send_updated_caps(struct weston_seat *seat)
        }
 }
 
-static void
-destroy_pointer_focus(struct wl_listener *listener, void *data)
-{
-       struct weston_pointer *pointer;
-
-       pointer = container_of(listener, struct weston_pointer,
-                              focus_listener);
-
-       pointer->focus = NULL;
-       move_resources(&pointer->resource_list, &pointer->focus_resource_list);
-
-       wl_list_remove(&pointer->focus_listener.link);
-       wl_list_init(&pointer->focus_listener.link);
-
-       wl_signal_emit(&pointer->focus_signal, pointer);
-}
-
 WL_EXPORT void
 weston_pointer_set_focus(struct weston_pointer *pointer,
                         struct weston_view *view,
@@ -548,6 +594,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
                                              pointer->focus->surface->resource);
                }
 
+               wl_list_remove(&pointer->focus_resource_listener.link);
+               wl_list_init(&pointer->focus_resource_listener.link);
                move_resources(&pointer->resource_list, focus_resource_list);
        }
 
@@ -576,16 +624,18 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
                }
 
                pointer->focus_serial = serial;
+               wl_resource_add_destroy_listener(view->surface->resource,
+                                                &pointer->focus_resource_listener);
        }
 
-       if (!wl_list_empty(&pointer->focus_listener.link)) {
-               wl_list_remove(&pointer->focus_listener.link);
-               wl_list_init(&pointer->focus_listener.link);
+       if (!wl_list_empty(&pointer->focus_view_listener.link)) {
+               wl_list_remove(&pointer->focus_view_listener.link);
+               wl_list_init(&pointer->focus_view_listener.link);
        }
        pointer->focus = view;
-       pointer->focus_listener.notify = destroy_pointer_focus;
+       pointer->focus_view_listener.notify = pointer_focus_view_destroyed;
        if (view)
-               wl_signal_add(&view->destroy_signal, &pointer->focus_listener);
+               wl_signal_add(&view->destroy_signal, &pointer->focus_view_listener);
        wl_signal_emit(&pointer->focus_signal, pointer);
 }
 
@@ -622,6 +672,8 @@ weston_keyboard_set_focus(struct weston_keyboard *keyboard,
                        wl_keyboard_send_leave(resource, serial,
                                        keyboard->focus->resource);
                }
+               wl_list_remove(&keyboard->focus_resource_listener.link);
+               wl_list_init(&keyboard->focus_resource_listener.link);
                move_resources(&keyboard->resource_list, focus_resource_list);
        }
 
@@ -640,6 +692,8 @@ weston_keyboard_set_focus(struct weston_keyboard *keyboard,
                                            surface,
                                            serial);
                keyboard->focus_serial = serial;
+               wl_resource_add_destroy_listener(surface->resource,
+                                                &keyboard->focus_resource_listener);
        }
 
        keyboard->focus = surface;
@@ -1258,6 +1312,11 @@ weston_touch_set_focus(struct weston_seat *seat, struct weston_view *view)
                return;
        }
 
+       wl_list_remove(&seat->touch->focus_resource_listener.link);
+       wl_list_init(&seat->touch->focus_resource_listener.link);
+       wl_list_remove(&seat->touch->focus_view_listener.link);
+       wl_list_init(&seat->touch->focus_view_listener.link);
+
        if (!wl_list_empty(focus_resource_list)) {
                move_resources(&seat->touch->resource_list,
                               focus_resource_list);
@@ -1269,6 +1328,9 @@ weston_touch_set_focus(struct weston_seat *seat, struct weston_view *view)
                move_resources_for_client(focus_resource_list,
                                          &seat->touch->resource_list,
                                          surface_client);
+               wl_resource_add_destroy_listener(view->surface->resource,
+                                                &seat->touch->focus_resource_listener);
+               wl_signal_add(&view->destroy_signal, &seat->touch->focus_view_listener);
        }
        seat->touch->focus = view;
 }