From aa7a4761f609201a5970e95ffdf772b0bd9b75fe Mon Sep 17 00:00:00 2001 From: Emilio Pozuelo Monfort Date: Tue, 19 Nov 2013 11:37:15 +0100 Subject: [PATCH] input: Don't send leave events to destroyed views If a view which has focus is destroyed, we would send a leave event while changing focus, causing a segfault. Prevent this by listening to the view's destroy signal and removing it from the pointer focus. Signed-off-by: Emilio Pozuelo Monfort --- src/compositor.h | 1 + src/input.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/compositor.h b/src/compositor.h index a8504af..b84289a 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -308,6 +308,7 @@ struct weston_pointer { struct wl_list focus_resource_list; struct weston_view *focus; uint32_t focus_serial; + struct wl_listener focus_listener; struct wl_signal focus_signal; struct wl_signal motion_signal; diff --git a/src/input.c b/src/input.c index fc93f88..7480374 100644 --- a/src/input.c +++ b/src/input.c @@ -395,8 +395,9 @@ weston_pointer_create(struct weston_seat *seat) seat->compositor->default_pointer_grab); pointer->default_grab.pointer = pointer; pointer->grab = &pointer->default_grab; - wl_signal_init(&pointer->focus_signal); wl_signal_init(&pointer->motion_signal); + wl_signal_init(&pointer->focus_signal); + wl_list_init(&pointer->focus_listener.link); pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy; @@ -503,6 +504,23 @@ 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, @@ -559,7 +577,14 @@ weston_pointer_set_focus(struct weston_pointer *pointer, pointer->focus_serial = serial; } + if (!wl_list_empty(&pointer->focus_listener.link)) { + wl_list_remove(&pointer->focus_listener.link); + wl_list_init(&pointer->focus_listener.link); + } pointer->focus = view; + pointer->focus_listener.notify = destroy_pointer_focus; + if (view) + wl_signal_add(&view->destroy_signal, &pointer->focus_listener); wl_signal_emit(&pointer->focus_signal, pointer); } -- 2.7.4