diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index b6d5f79f..38d6b453 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -114,4 +114,9 @@ int wlr_surface_set_role(struct wlr_surface *surface, const char *role, void wlr_surface_make_subsurface(struct wlr_surface *surface, struct wlr_surface *parent, uint32_t id); +/** + * Get the top of the subsurface tree for this surface. + */ +struct wlr_surface *wlr_surface_get_main_surface(struct wlr_surface *surface); + #endif diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index a142ddd4..12903cda 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -84,10 +84,31 @@ static void subcompositor_get_subsurface(struct wl_client *client, struct wlr_surface *surface = wl_resource_get_user_data(surface_resource); struct wlr_surface *parent = wl_resource_get_user_data(parent_resource); - // TODO: errors - // * cannot be its own parent - // * cannot already a subsurface - // * cannot be an ancestor of parent + static const char msg[] = "get_subsurface: wl_subsurface@"; + + if (surface == parent) { + wl_resource_post_error(resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, + "%s%d: wl_surface@%d cannot be its own parent", + msg, id, wl_resource_get_id(surface_resource)); + return; + } + + if (surface->subsurface) { + wl_resource_post_error(resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, + "%s%d: wl_surface@%d is already a sub-surface", + msg, id, wl_resource_get_id(surface_resource)); + return; + } + + if (wlr_surface_get_main_surface(parent) == surface) { + wl_resource_post_error(resource, + WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, + "%s%d: wl_surface@%d is an ancestor of parent", + msg, id, wl_resource_get_id(surface_resource)); + return; + } if (wlr_surface_set_role(surface, "wl_subsurface", resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0) { diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 6f6df226..8c084ceb 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -769,3 +769,14 @@ void wlr_surface_make_subsurface(struct wlr_surface *surface, surface->subsurface = subsurface; } + + +struct wlr_surface *wlr_surface_get_main_surface(struct wlr_surface *surface) { + struct wlr_subsurface *sub; + + while (surface && (sub = surface->subsurface)) { + surface = sub->parent; + } + + return surface; +}