commit 97069f8
Michael Forney
·
2018-11-09 05:38:59 +0000 UTC
parent 2011cc7
xdg-shell: Handle role destruction in xdg_surface properly xdg_surface should clear its `role` field upon destruction of its role. Then, in its destructor, it can destroy the role only if it has not already been destroyed. This fixes a double-destruction of xdg_toplevel if it is destroyed explicitly before the xdg_surface (as the spec requires).
1 files changed,
+13,
-2
+13,
-2
1@@ -36,7 +36,7 @@
2 struct xdg_surface {
3 struct wl_resource *resource, *role;
4 struct surface *surface;
5- struct wl_listener surface_destroy_listener;
6+ struct wl_listener surface_destroy_listener, role_destroy_listener;
7 uint32_t configure_serial;
8 };
9
10@@ -375,6 +375,7 @@ get_toplevel(struct wl_client *client, struct wl_resource *resource, uint32_t id
11 return;
12 }
13 xdg_surface->role = toplevel->resource;
14+ wl_resource_add_destroy_listener(xdg_surface->role, &xdg_surface->role_destroy_listener);
15 }
16
17 static void
18@@ -416,13 +417,22 @@ handle_surface_destroy(struct wl_listener *listener, void *data)
19 wl_resource_destroy(xdg_surface->resource);
20 }
21
22+static void
23+handle_role_destroy(struct wl_listener *listener, void *data)
24+{
25+ struct xdg_surface *xdg_surface = wl_container_of(listener, xdg_surface, role_destroy_listener);
26+
27+ xdg_surface->role = NULL;
28+}
29+
30 static void
31 destroy_xdg_surface(struct wl_resource *resource)
32 {
33 struct xdg_surface *xdg_surface = wl_resource_get_user_data(resource);
34
35 wl_list_remove(&xdg_surface->surface_destroy_listener.link);
36- wl_resource_destroy(xdg_surface->role);
37+ if (xdg_surface->role)
38+ wl_resource_destroy(xdg_surface->role);
39 free(xdg_surface);
40 }
41
42@@ -439,6 +449,7 @@ xdg_surface_new(struct wl_client *client, uint32_t version, uint32_t id, struct
43 goto error1;
44 xdg_surface->surface = surface;
45 xdg_surface->surface_destroy_listener.notify = &handle_surface_destroy;
46+ xdg_surface->role_destroy_listener.notify = &handle_role_destroy;
47 wl_resource_add_destroy_listener(surface->resource, &xdg_surface->surface_destroy_listener);
48 wl_resource_set_implementation(xdg_surface->resource, &xdg_surface_impl, xdg_surface, destroy_xdg_surface);
49