xdg-shell: Require proper object tree destruction
Require all child objects to be destroyed before the parent. In other words, all popups and surfaces created by one xdg_shell instance needs to be destroyed before the xdg_shell object, otherwise a protocol error is raised. Signed-off-by: Jonas Ådahl <jadahl@gmail.com> Reviewed-by: Bryce Harrington <bryce@osg.samsung.com> Acked-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
@@ -107,6 +107,7 @@ struct shell_surface {
|
|||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
struct wl_signal destroy_signal;
|
struct wl_signal destroy_signal;
|
||||||
struct shell_client *owner;
|
struct shell_client *owner;
|
||||||
|
struct wl_resource *owner_resource;
|
||||||
|
|
||||||
struct weston_surface *surface;
|
struct weston_surface *surface;
|
||||||
struct weston_view *view;
|
struct weston_view *view;
|
||||||
@@ -239,6 +240,7 @@ struct shell_client {
|
|||||||
struct wl_event_source *ping_timer;
|
struct wl_event_source *ping_timer;
|
||||||
uint32_t ping_serial;
|
uint32_t ping_serial;
|
||||||
int unresponsive;
|
int unresponsive;
|
||||||
|
struct wl_list surface_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct desktop_shell *
|
static struct desktop_shell *
|
||||||
@@ -3552,6 +3554,7 @@ shell_destroy_shell_surface(struct wl_resource *resource)
|
|||||||
|
|
||||||
if (!wl_list_empty(&shsurf->popup.grab_link))
|
if (!wl_list_empty(&shsurf->popup.grab_link))
|
||||||
remove_popup_grab(shsurf);
|
remove_popup_grab(shsurf);
|
||||||
|
wl_list_remove(wl_resource_get_link(shsurf->resource));
|
||||||
shsurf->resource = NULL;
|
shsurf->resource = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3723,6 +3726,7 @@ shell_get_shell_surface(struct wl_client *client,
|
|||||||
wl_resource_set_implementation(shsurf->resource,
|
wl_resource_set_implementation(shsurf->resource,
|
||||||
&shell_surface_implementation,
|
&shell_surface_implementation,
|
||||||
shsurf, shell_destroy_shell_surface);
|
shsurf, shell_destroy_shell_surface);
|
||||||
|
wl_list_init(wl_resource_get_link(shsurf->resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -3986,6 +3990,21 @@ static void
|
|||||||
xdg_shell_destroy(struct wl_client *client,
|
xdg_shell_destroy(struct wl_client *client,
|
||||||
struct wl_resource *resource)
|
struct wl_resource *resource)
|
||||||
{
|
{
|
||||||
|
struct shell_client *sc = wl_resource_get_user_data(resource);
|
||||||
|
struct wl_resource *shsurf_resource;
|
||||||
|
struct shell_surface *shsurf;
|
||||||
|
|
||||||
|
wl_resource_for_each(shsurf_resource, &sc->surface_list) {
|
||||||
|
shsurf = wl_resource_get_user_data(shsurf_resource);
|
||||||
|
if (shsurf->owner_resource == resource) {
|
||||||
|
wl_resource_post_error(
|
||||||
|
resource,
|
||||||
|
XDG_SHELL_ERROR_DEFUNCT_SURFACES,
|
||||||
|
"not all child surface objects destroyed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4054,6 +4073,9 @@ xdg_get_xdg_surface(struct wl_client *client,
|
|||||||
wl_resource_set_implementation(shsurf->resource,
|
wl_resource_set_implementation(shsurf->resource,
|
||||||
&xdg_surface_implementation,
|
&xdg_surface_implementation,
|
||||||
shsurf, shell_destroy_shell_surface);
|
shsurf, shell_destroy_shell_surface);
|
||||||
|
shsurf->owner_resource = resource;
|
||||||
|
wl_list_insert(&sc->surface_list,
|
||||||
|
wl_resource_get_link(shsurf->resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
@@ -4180,6 +4202,9 @@ xdg_get_xdg_popup(struct wl_client *client,
|
|||||||
wl_resource_set_implementation(shsurf->resource,
|
wl_resource_set_implementation(shsurf->resource,
|
||||||
&xdg_popup_implementation,
|
&xdg_popup_implementation,
|
||||||
shsurf, shell_destroy_shell_surface);
|
shsurf, shell_destroy_shell_surface);
|
||||||
|
shsurf->owner_resource = resource;
|
||||||
|
wl_list_insert(&sc->surface_list,
|
||||||
|
wl_resource_get_link(shsurf->resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -5797,6 +5822,7 @@ shell_client_create(struct wl_client *client, struct desktop_shell *shell,
|
|||||||
sc->shell = shell;
|
sc->shell = shell;
|
||||||
sc->destroy_listener.notify = handle_shell_client_destroy;
|
sc->destroy_listener.notify = handle_shell_client_destroy;
|
||||||
wl_client_add_destroy_listener(client, &sc->destroy_listener);
|
wl_client_add_destroy_listener(client, &sc->destroy_listener);
|
||||||
|
wl_list_init(&sc->surface_list);
|
||||||
|
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
<enum name="error">
|
<enum name="error">
|
||||||
<entry name="role" value="0" summary="given wl_surface has another role"/>
|
<entry name="role" value="0" summary="given wl_surface has another role"/>
|
||||||
|
<entry name="defunct_surfaces" value="1" summary="xdg_shell was destroyed before children"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<request name="destroy" type="destructor">
|
<request name="destroy" type="destructor">
|
||||||
@@ -56,9 +57,8 @@
|
|||||||
Destroy this xdg_shell object.
|
Destroy this xdg_shell object.
|
||||||
|
|
||||||
Destroying a bound xdg_shell object while there are surfaces
|
Destroying a bound xdg_shell object while there are surfaces
|
||||||
still alive with roles from this interface is illegal and will
|
still alive created by this xdg_shell object instance is illegal
|
||||||
result in a protocol error. Make sure to destroy all surfaces
|
and will result in a protocol error.
|
||||||
before destroying this object.
|
|
||||||
</description>
|
</description>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user