wayland: Report error when trying to stack subsurface incorrectly

Don't allow a client to stack a subsurface next to a subsurface with
another parent, or to a non-parent non-subsurface surface.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>

https://bugzilla.gnome.org/show_bug.cgi?id=705502
This commit is contained in:
Jonas Ådahl 2014-01-12 22:02:09 +01:00
parent c3b0faec82
commit 799c27484d
2 changed files with 62 additions and 1 deletions

View File

@ -999,7 +999,14 @@ wl_subsurface_destructor (struct wl_resource *resource)
MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
unparent_actor (surface);
if (surface->sub.parent)
{
wl_list_remove (&surface->sub.parent_destroy_listener.link);
surface->sub.parent->subsurfaces =
g_list_remove (surface->sub.parent->subsurfaces, surface);
unparent_actor (surface);
surface->sub.parent = NULL;
}
destroy_surface_extension (subsurface);
}
@ -1022,6 +1029,16 @@ wl_subsurface_set_position (struct wl_client *client,
clutter_actor_set_position (CLUTTER_ACTOR (surface->surface_actor), x, y);
}
static gboolean
is_valid_sibling (MetaWaylandSurface *surface, MetaWaylandSurface *sibling)
{
if (surface->sub.parent == sibling)
return TRUE;
if (surface->sub.parent == sibling->sub.parent)
return TRUE;
return FALSE;
}
static void
wl_subsurface_place_above (struct wl_client *client,
struct wl_resource *resource,
@ -1032,6 +1049,15 @@ wl_subsurface_place_above (struct wl_client *client,
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
if (!is_valid_sibling (surface, sibling))
{
wl_resource_post_error (resource, WL_SUBSURFACE_ERROR_BAD_SURFACE,
"wl_subsurface::place_above: wl_surface@%d is "
"not a valid parent or sibling",
wl_resource_get_id (sibling->resource));
return;
}
parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
clutter_actor_set_child_above_sibling (parent_actor,
@ -1049,6 +1075,15 @@ wl_subsurface_place_below (struct wl_client *client,
MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
if (!is_valid_sibling (surface, sibling))
{
wl_resource_post_error (resource, WL_SUBSURFACE_ERROR_BAD_SURFACE,
"wl_subsurface::place_below: wl_surface@%d is "
"not a valid parent or sibling",
wl_resource_get_id (sibling->resource));
return;
}
parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
clutter_actor_set_child_below_sibling (parent_actor,
@ -1086,6 +1121,18 @@ wl_subcompositor_destroy (struct wl_client *client,
wl_resource_destroy (resource);
}
static void
surface_handle_parent_surface_destroyed (struct wl_listener *listener,
void *data)
{
MetaWaylandSurface *surface = wl_container_of (listener,
surface,
sub.parent_destroy_listener);
surface->sub.parent = NULL;
unparent_actor (surface);
}
static void
wl_subcompositor_get_subsurface (struct wl_client *client,
struct wl_resource *resource,
@ -1108,6 +1155,13 @@ wl_subcompositor_get_subsurface (struct wl_client *client,
return;
}
surface->sub.parent = parent;
surface->sub.parent_destroy_listener.notify =
surface_handle_parent_surface_destroyed;
wl_resource_add_destroy_listener (parent->resource,
&surface->sub.parent_destroy_listener);
parent->subsurfaces = g_list_append (parent->subsurfaces, surface);
clutter_actor_add_child (CLUTTER_ACTOR (parent->surface_actor),
CLUTTER_ACTOR (surface->surface_actor));
}

View File

@ -85,6 +85,13 @@ struct _MetaWaylandSurface
MetaWaylandSurfaceExtension gtk_surface;
MetaWaylandSurfaceExtension subsurface;
GList *subsurfaces;
struct {
MetaWaylandSurface *parent;
struct wl_listener parent_destroy_listener;
} sub;
/* All the pending state, that wl_surface.commit will apply. */
MetaWaylandDoubleBufferedState pending;
};