summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Bradford <rob@linux.intel.com>2013-04-03 15:20:49 +0100
committerKristian Høgsberg <krh@bitplanet.net>2013-04-03 12:46:57 -0400
commitdb19b443cc8d3179df31cb96b9c45527ad403fef (patch)
tree84bb0e6583dd2c9c633176b910dc6bf9fca42e0e
parent858fcbde59cfd2b42644c43bf481ffd70b30d5be (diff)
wayland-server: Listen for pointer current surface destruction
Add a destroy listener so that when the current surface associated with the pointer is destroyed we can reset the pointer to the current surface. In order to achieve this add a wl_pointer_set_current() which handles assigning the surface and creating the listener. This resolves a use-after-free error triggered with nested popup surfaces Fixes: https://bugzilla.gnome.org/show_bug.cgi?id=696946
-rw-r--r--src/wayland-server.c25
-rw-r--r--src/wayland-server.h3
2 files changed, 28 insertions, 0 deletions
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 384b465..2109674 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -946,6 +946,31 @@ wl_pointer_end_grab(struct wl_pointer *pointer)
pointer->current_x, pointer->current_y);
}
+static void
+current_surface_destroy(struct wl_listener *listener, void *data)
+{
+ struct wl_pointer *pointer =
+ container_of(listener, struct wl_pointer, current_listener);
+
+ pointer->current = NULL;
+}
+
+WL_EXPORT void
+wl_pointer_set_current(struct wl_pointer *pointer, struct wl_surface *surface)
+{
+ if (pointer->current)
+ wl_list_remove(&pointer->current_listener.link);
+
+ pointer->current = surface;
+
+ if (!surface)
+ return;
+
+ wl_signal_add(&surface->resource.destroy_signal,
+ &pointer->current_listener);
+ pointer->current_listener.notify = current_surface_destroy;
+}
+
WL_EXPORT void
wl_touch_start_grab(struct wl_touch *touch, struct wl_touch_grab *grab)
{
diff --git a/src/wayland-server.h b/src/wayland-server.h
index e5a862a..af2be62 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -312,6 +312,7 @@ struct wl_pointer {
wl_fixed_t x, y;
struct wl_surface *current;
+ struct wl_listener current_listener;
wl_fixed_t current_x, current_y;
uint32_t button_count;
@@ -450,6 +451,8 @@ wl_pointer_start_grab(struct wl_pointer *pointer,
struct wl_pointer_grab *grab);
void
wl_pointer_end_grab(struct wl_pointer *pointer);
+void
+wl_pointer_set_current(struct wl_pointer *pointer, struct wl_surface *surface);
void
wl_keyboard_init(struct wl_keyboard *keyboard);