compositor: allow using nested parent as a subsurface sibling
The parent of a subsurface can be used as a sibling in the place_below
and place_above calls. However this did not work when the parent is
nested, so fix the sibling check and add a test to check this case.
Signed-off-by: Daniel Stone <daniels@collabora.com>
diff --git a/libweston/compositor.c b/libweston/compositor.c
index d552e18..ee0a007 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -3521,17 +3521,16 @@
}
static struct weston_subsurface *
-subsurface_from_surface(struct weston_surface *surface)
+subsurface_find_sibling(struct weston_subsurface *sub,
+ struct weston_surface *surface)
{
- struct weston_subsurface *sub;
+ struct weston_surface *parent = sub->parent;
+ struct weston_subsurface *sibling;
- sub = weston_surface_to_subsurface(surface);
- if (sub)
- return sub;
-
- wl_list_for_each(sub, &surface->subsurface_list, parent_link)
- if (sub->surface == surface)
- return sub;
+ wl_list_for_each(sibling, &parent->subsurface_list, parent_link) {
+ if (sibling->surface == surface && sibling != sub)
+ return sibling;
+ }
return NULL;
}
@@ -3543,8 +3542,7 @@
{
struct weston_subsurface *sibling;
- sibling = subsurface_from_surface(surface);
-
+ sibling = subsurface_find_sibling(sub, surface);
if (!sibling) {
wl_resource_post_error(sub->resource,
WL_SUBSURFACE_ERROR_BAD_SURFACE,
@@ -3553,13 +3551,7 @@
return NULL;
}
- if (sibling->parent != sub->parent) {
- wl_resource_post_error(sub->resource,
- WL_SUBSURFACE_ERROR_BAD_SURFACE,
- "%s: wl_surface@%d has a different parent",
- request, wl_resource_get_id(surface->resource));
- return NULL;
- }
+ assert(sibling->parent == sub->parent);
return sibling;
}
diff --git a/tests/subsurface-test.c b/tests/subsurface-test.c
index 3ababdd..03ff539 100644
--- a/tests/subsurface-test.c
+++ b/tests/subsurface-test.c
@@ -250,6 +250,50 @@
WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE);
}
+TEST(test_subsurface_place_above_nested_parent)
+{
+ struct client *client;
+ struct compound_surface com;
+ struct wl_surface *grandchild;
+ struct wl_subcompositor *subco;
+ struct wl_subsurface *sub;
+
+ client = create_client_and_test_surface(100, 50, 123, 77);
+ assert(client);
+
+ populate_compound_surface(&com, client);
+
+ subco = get_subcompositor(client);
+ grandchild = wl_compositor_create_surface(client->wl_compositor);
+ sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
+
+ wl_subsurface_place_above(sub, com.child[0]);
+
+ client_roundtrip(client);
+}
+
+TEST(test_subsurface_place_below_nested_parent)
+{
+ struct client *client;
+ struct compound_surface com;
+ struct wl_subcompositor *subco;
+ struct wl_surface *grandchild;
+ struct wl_subsurface *sub;
+
+ client = create_client_and_test_surface(100, 50, 123, 77);
+ assert(client);
+
+ populate_compound_surface(&com, client);
+
+ subco = get_subcompositor(client);
+ grandchild = wl_compositor_create_surface(client->wl_compositor);
+ sub = wl_subcompositor_get_subsurface(subco, grandchild, com.child[0]);
+
+ wl_subsurface_place_below(sub, com.child[0]);
+
+ client_roundtrip(client);
+}
+
TEST(test_subsurface_place_above_stranger)
{
struct client *client;