From 799c27484dc7ba307d6f62311a1b468e27581676 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Sun, 12 Jan 2014 22:02:09 +0100 Subject: [PATCH] wayland: Report error when trying to stack subsurface incorrectly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 https://bugzilla.gnome.org/show_bug.cgi?id=705502 --- src/wayland/meta-wayland-surface.c | 56 +++++++++++++++++++++++++++++- src/wayland/meta-wayland-surface.h | 7 ++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 1ca38e564..e96c92228 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -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)); } diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 9533731a6..fe2bfea3b 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -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; };