xdg-toplevel: send invalid_parent error

This commit is contained in:
Kirill Primak 2022-09-04 14:01:55 +03:00 committed by Simon Ser
parent 5ba6cf517b
commit a049d66dd7
5 changed files with 41 additions and 8 deletions

View file

@ -418,9 +418,11 @@ void wlr_xdg_toplevel_send_close(struct wlr_xdg_toplevel *toplevel);
/**
* Sets the parent of this toplevel. Parent can be NULL.
*
* Returns true on success, false if setting the parent would create a loop.
*/
void wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel,
struct wlr_xdg_toplevel *parent);
bool wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel,
struct wlr_xdg_toplevel *parent);
/**
* Request that this popup closes.

View file

@ -1,5 +1,5 @@
wayland_protos = dependency('wayland-protocols',
version: '>=1.26',
version: '>=1.27',
fallback: 'wayland-protocols',
default_options: ['tests=false'],
)

View file

@ -107,6 +107,14 @@ static void xdg_imported_handle_set_parent_of(struct wl_client *client,
child->xdg_surface_destroy.notify = handle_child_xdg_surface_destroy;
child->xdg_toplevel_set_parent.notify = handle_xdg_toplevel_set_parent;
if (!wlr_xdg_toplevel_set_parent(child_toplevel, surface->toplevel)) {
wl_resource_post_error(surface->toplevel->resource,
XDG_TOPLEVEL_ERROR_INVALID_PARENT,
"a toplevel cannot be a parent of itself or its ancestor");
free(child);
return;
}
wlr_xdg_toplevel_set_parent(child_toplevel, surface->toplevel);
wl_signal_add(&child_toplevel->base->events.destroy,
&child->xdg_surface_destroy);

View file

@ -113,6 +113,14 @@ static void xdg_imported_handle_set_parent_of(struct wl_client *client,
child->xdg_surface_destroy.notify = handle_child_xdg_surface_destroy;
child->xdg_toplevel_set_parent.notify = handle_xdg_toplevel_set_parent;
if (!wlr_xdg_toplevel_set_parent(child_toplevel, surface->toplevel)) {
wl_resource_post_error(surface->toplevel->resource,
XDG_TOPLEVEL_ERROR_INVALID_PARENT,
"a toplevel cannot be a parent of itself or its ancestor");
free(child);
return;
}
wlr_xdg_toplevel_set_parent(child_toplevel, surface->toplevel);
wl_signal_add(&child_toplevel->base->events.destroy,
&child->xdg_surface_destroy);

View file

@ -149,16 +149,27 @@ struct wlr_xdg_toplevel *wlr_xdg_toplevel_from_resource(
static void handle_parent_unmap(struct wl_listener *listener, void *data) {
struct wlr_xdg_toplevel *toplevel =
wl_container_of(listener, toplevel, parent_unmap);
wlr_xdg_toplevel_set_parent(toplevel, toplevel->parent->parent);
if (!wlr_xdg_toplevel_set_parent(toplevel, toplevel->parent->parent)) {
assert(0 && "Unreachable");
}
}
void wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel,
bool wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel,
struct wlr_xdg_toplevel *parent) {
if (toplevel->parent) {
// Check for a loop
struct wlr_xdg_toplevel *iter = parent;
while (iter != NULL) {
if (iter == toplevel) {
return false;
}
iter = iter->parent;
}
if (toplevel->parent != NULL) {
wl_list_remove(&toplevel->parent_unmap.link);
}
if (parent && parent->base->mapped) {
if (parent != NULL && parent->base->mapped) {
toplevel->parent = parent;
toplevel->parent_unmap.notify = handle_parent_unmap;
wl_signal_add(&toplevel->parent->base->events.unmap,
@ -168,6 +179,7 @@ void wlr_xdg_toplevel_set_parent(struct wlr_xdg_toplevel *toplevel,
}
wl_signal_emit_mutable(&toplevel->events.set_parent, NULL);
return true;
}
static void xdg_toplevel_handle_set_parent(struct wl_client *client,
@ -180,7 +192,10 @@ static void xdg_toplevel_handle_set_parent(struct wl_client *client,
parent = wlr_xdg_toplevel_from_resource(parent_resource);
}
wlr_xdg_toplevel_set_parent(toplevel, parent);
if (!wlr_xdg_toplevel_set_parent(toplevel, parent)) {
wl_resource_post_error(resource, XDG_TOPLEVEL_ERROR_INVALID_PARENT,
"a toplevel cannot be a parent of itself or its ancestor");
}
}
static void xdg_toplevel_handle_set_title(struct wl_client *client,