From 4fa4873928f2903dc4aeebf63236aa151b504c03 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 10 Mar 2009 23:17:00 -0400 Subject: [PATCH] Dont crash when surfaces and clients disappear Set up a notification system, so we get a callback when a client and its surfaces disappear and can drop references the lost surface. --- wayland-system-compositor.c | 58 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 7 deletions(-) diff --git a/wayland-system-compositor.c b/wayland-system-compositor.c index 1a28f76..719426f 100644 --- a/wayland-system-compositor.c +++ b/wayland-system-compositor.c @@ -63,6 +63,14 @@ struct wl_visual { struct wl_object base; }; +struct wlsc_surface; + +struct wlsc_listener { + struct wl_list link; + void (*func)(struct wlsc_listener *listener, + struct wlsc_surface *surface); +}; + struct wlsc_output { struct wl_object base; struct wl_list link; @@ -89,6 +97,8 @@ struct wlsc_input_device { struct wlsc_surface *pointer_focus; struct wlsc_surface *keyboard_focus; struct wl_array keys; + + struct wlsc_listener listener; }; struct wlsc_compositor { @@ -104,6 +114,8 @@ struct wlsc_compositor { struct wl_list input_device_list; struct wl_list surface_list; + struct wl_list surface_destroy_listener_list; + struct wl_event_source *term_signal_source; /* tty handling state */ @@ -386,12 +398,25 @@ wlsc_surface_create_from_cairo_surface(struct wlsc_compositor *ec, } static void -wlsc_surface_destroy(struct wlsc_surface *es, struct wlsc_compositor *ec) +wlsc_surface_destroy(struct wlsc_surface *surface, + struct wlsc_compositor *compositor) { - glDeleteTextures(1, &es->texture); - if (es->surface != EGL_NO_SURFACE) - eglDestroySurface(ec->display, es->surface); - free(es); + struct wlsc_listener *l; + + l = container_of(compositor->surface_destroy_listener_list.next, + struct wlsc_listener, link); + while (&l->link != &compositor->surface_destroy_listener_list) { + l->func(l, surface); + l = container_of(l->link.next, struct wlsc_listener, link); + } + + wl_list_remove(&surface->link); + wl_list_remove(&surface->animate.link); + + glDeleteTextures(1, &surface->texture); + if (surface->surface != EGL_NO_SURFACE) + eglDestroySurface(compositor->display, surface->surface); + free(surface); } static void @@ -674,8 +699,6 @@ surface_destroy(struct wl_client *client, struct wlsc_surface *es = (struct wlsc_surface *) surface; struct wlsc_compositor *ec = es->compositor; - wl_list_remove(&es->link); - wl_list_remove(&es->animate.link); wlsc_surface_destroy(es, ec); schedule_repaint(ec); @@ -1108,6 +1131,23 @@ struct evdev_input_device * evdev_input_device_create(struct wlsc_input_device *device, struct wl_display *display, const char *path); +static void +handle_surface_destroy(struct wlsc_listener *listener, + struct wlsc_surface *surface) +{ + struct wlsc_input_device *device = + container_of(listener, struct wlsc_input_device, listener); + + if (device->grab_surface == surface) { + device->grab_surface = NULL; + device->grab = 0; + } + if (device->keyboard_focus == surface) + device->keyboard_focus = NULL; + if (device->pointer_focus == surface) + device->pointer_focus = NULL; +} + static struct wlsc_input_device * create_input_device(struct wlsc_compositor *ec) { @@ -1126,6 +1166,9 @@ create_input_device(struct wlsc_compositor *ec) device->y = 100; device->ec = ec; + device->listener.func = handle_surface_destroy; + wl_list_insert(ec->surface_destroy_listener_list.prev, + &device->listener.link); wl_list_insert(ec->input_device_list.prev, &device->link); return device; @@ -1506,6 +1549,7 @@ wlsc_compositor_create(struct wl_display *display) wl_list_init(&ec->surface_list); wl_list_init(&ec->input_device_list); wl_list_init(&ec->output_list); + wl_list_init(&ec->surface_destroy_listener_list); if (init_libudev(ec) < 0) { fprintf(stderr, "failed to initialize devices\n"); return NULL; -- 2.7.4