From: Rob Bradford Date: Wed, 3 Apr 2013 14:20:49 +0000 (+0100) Subject: wayland-server: Listen for pointer current surface destruction X-Git-Tag: 1.0.90~30 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=db19b443cc8d3179df31cb96b9c45527ad403fef;p=platform%2Fupstream%2Fwayland.git 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 --- 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);