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