[PATCH 5/9] input: Don't send leave events to destroyed views

Emilio Pozuelo Monfort pochu27 at gmail.com
Fri Nov 15 08:53:34 PST 2013


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 at collabora.co.uk>
---
 src/compositor.h |  1 +
 src/input.c      | 25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/src/compositor.h b/src/compositor.h
index 6087468..0c24b00 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -306,6 +306,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..b1486ed 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,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);
 }
 
-- 
1.8.4.rc3



More information about the wayland-devel mailing list