summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPekka Vuorela <pvuorela@iki.fi>2012-09-17 22:15:57 +0300
committerTiago Vignatti <tiago.vignatti@intel.com>2012-09-26 17:38:41 +0300
commitb0b3c6f16d5884e9eecfbad39526b8b29be24b18 (patch)
treef5c0c455c89c416771a1121ad6246626d56b03d0
parent5eca7ed3a1b0b62b2f43629c0f37d28a04ac15a3 (diff)
Protect window callbacks from deleted windows
Calling window_destroy() was able to cause segfault for callbacks triggering afterwards.
-rw-r--r--clients/window.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/clients/window.c b/clients/window.c
index c784911..93d2282 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -166,6 +166,8 @@ struct window {
window_close_handler_t close_handler;
window_fullscreen_handler_t fullscreen_handler;
+ struct wl_callback *frame_cb;
+
struct frame *frame;
struct widget *widget;
@@ -993,6 +995,8 @@ window_destroy(struct window *window)
if (window->cairo_surface != NULL)
cairo_surface_destroy(window->cairo_surface);
+ if (window->frame_cb)
+ wl_callback_destroy(window->frame_cb);
free(window->title);
free(window);
}
@@ -2004,6 +2008,9 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
input->sx = sx;
input->sy = sy;
+ if (!window)
+ return;
+
if (!(input->grab && input->grab_button)) {
widget = widget_find_widget(window->widget, sx, sy);
input_set_focus_widget(input, widget, sx, sy);
@@ -2875,7 +2882,9 @@ frame_callback(void *data, struct wl_callback *callback, uint32_t time)
{
struct window *window = data;
+ assert(callback == window->frame_cb);
wl_callback_destroy(callback);
+ window->frame_cb = 0;
window->redraw_scheduled = 0;
if (window->redraw_needed)
window_schedule_redraw(window);
@@ -2889,7 +2898,6 @@ static void
idle_redraw(struct task *task, uint32_t events)
{
struct window *window = container_of(task, struct window, redraw_task);
- struct wl_callback *callback;
if (window->resize_needed)
idle_resize(window);
@@ -2900,8 +2908,8 @@ idle_redraw(struct task *task, uint32_t events)
window->redraw_needed = 0;
wl_list_init(&window->redraw_task.link);
- callback = wl_surface_frame(window->surface);
- wl_callback_add_listener(callback, &listener, window);
+ window->frame_cb = wl_surface_frame(window->surface);
+ wl_callback_add_listener(window->frame_cb, &listener, window);
}
void