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 <emilio.pozuelo@collabora.co.uk>
This commit is contained in:
committed by
Kristian Høgsberg
parent
df8133b725
commit
aa7a4761f6
@@ -308,6 +308,7 @@ struct weston_pointer {
|
|||||||
struct wl_list focus_resource_list;
|
struct wl_list focus_resource_list;
|
||||||
struct weston_view *focus;
|
struct weston_view *focus;
|
||||||
uint32_t focus_serial;
|
uint32_t focus_serial;
|
||||||
|
struct wl_listener focus_listener;
|
||||||
struct wl_signal focus_signal;
|
struct wl_signal focus_signal;
|
||||||
struct wl_signal motion_signal;
|
struct wl_signal motion_signal;
|
||||||
|
|
||||||
|
|||||||
+26
-1
@@ -395,8 +395,9 @@ weston_pointer_create(struct weston_seat *seat)
|
|||||||
seat->compositor->default_pointer_grab);
|
seat->compositor->default_pointer_grab);
|
||||||
pointer->default_grab.pointer = pointer;
|
pointer->default_grab.pointer = pointer;
|
||||||
pointer->grab = &pointer->default_grab;
|
pointer->grab = &pointer->default_grab;
|
||||||
wl_signal_init(&pointer->focus_signal);
|
|
||||||
wl_signal_init(&pointer->motion_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;
|
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
|
WL_EXPORT void
|
||||||
weston_pointer_set_focus(struct weston_pointer *pointer,
|
weston_pointer_set_focus(struct weston_pointer *pointer,
|
||||||
struct weston_view *view,
|
struct weston_view *view,
|
||||||
@@ -559,7 +577,14 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
|
|||||||
pointer->focus_serial = serial;
|
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 = 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);
|
wl_signal_emit(&pointer->focus_signal, pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user