On 12/11/13 19:28, Emilio Pozuelo Monfort wrote: > 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 <[email protected]> > --- > src/compositor.h | 1 + > src/input.c | 22 ++++++++++++++++++++++ > 2 files changed, 23 insertions(+) > > diff --git a/src/compositor.h b/src/compositor.h > index 21d94d3..b69111f 100644 > --- a/src/compositor.h > +++ b/src/compositor.h > @@ -311,6 +311,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 weston_view *sprite; > diff --git a/src/input.c b/src/input.c > index ed3e06f..64f0606 100644 > --- a/src/input.c > +++ b/src/input.c > @@ -392,6 +392,7 @@ weston_pointer_create(void) > pointer->default_grab.pointer = pointer; > pointer->grab = &pointer->default_grab; > wl_signal_init(&pointer->focus_signal); > + wl_list_init(&pointer->focus_listener.link); > > pointer->sprite_destroy_listener.notify = pointer_handle_sprite_destroy; > > @@ -487,6 +488,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, > @@ -543,7 +561,11 @@ 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); > pointer->focus = view; > + pointer->focus_listener.notify = destroy_pointer_focus; > + wl_signal_add(&view->destroy_signal, &pointer->focus_listener);
There's a bug here if view is NULL (e.g. when unsetting focus). I'll send an updated patch. Emilio > wl_signal_emit(&pointer->focus_signal, pointer); > } > > _______________________________________________ wayland-devel mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/wayland-devel
