[mutter/wayland] wayland: Report error when trying to stack subsurface incorrectly



commit 799c27484dc7ba307d6f62311a1b468e27581676
Author: Jonas Ådahl <jadahl gmail com>
Date:   Sun Jan 12 22:02:09 2014 +0100

    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

 src/wayland/meta-wayland-surface.c |   56 +++++++++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-surface.h |    7 ++++
 2 files changed, 62 insertions(+), 1 deletions(-)
---
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 1ca38e5..e96c922 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,
@@ -1087,6 +1122,18 @@ wl_subcompositor_destroy (struct wl_client *client,
 }
 
 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,
                                  guint32 id,
@@ -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 9533731..fe2bfea 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;
 };


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]