[mutter/wayland] wayland-surface: Add support for subsurfaces



commit a9424255a52fe22656cae5f3f96307f9b9ffa570
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Mon Nov 25 16:26:02 2013 -0500

    wayland-surface: Add support for subsurfaces
    
    The state for a subsurface isn't double-buffered yet, though...

 src/wayland/meta-wayland-surface.c  |  183 +++++++++++++++++++++++++++++++++--
 src/wayland/meta-wayland-surface.h  |    1 +
 src/wayland/meta-wayland-versions.h |    2 +
 3 files changed, 178 insertions(+), 8 deletions(-)
---
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index b2c4c90..2a2402a 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -253,12 +253,12 @@ cursor_surface_commit (MetaWaylandSurface *surface)
   meta_wayland_seat_update_sprite (surface->compositor->seat);
 }
 
-static void
-toplevel_surface_commit (MetaWaylandSurface *surface)
+static gboolean
+actor_surface_commit (MetaWaylandSurface *surface)
 {
   MetaSurfaceActor *surface_actor = surface->surface_actor;
-  MetaWindow *window = surface->window;
   MetaWaylandBuffer *buffer = surface->pending.buffer;
+  gboolean changed = FALSE;
 
   /* wl_surface.attach */
   if (surface->pending.newly_attached && buffer != surface->buffer_ref.buffer)
@@ -267,9 +267,26 @@ toplevel_surface_commit (MetaWaylandSurface *surface)
       meta_wayland_buffer_reference (&surface->buffer_ref, buffer);
       meta_surface_actor_attach_wayland_buffer (surface_actor, buffer);
       surface_process_damage (surface, surface->pending.damage);
+      changed = TRUE;
+    }
 
-      meta_window_set_surface_mapped (window, buffer != NULL);
+  if (surface->pending.opaque_region)
+    meta_surface_actor_set_opaque_region (surface_actor, surface->pending.opaque_region);
+  if (surface->pending.input_region)
+    meta_surface_actor_set_input_region (surface_actor, surface->pending.input_region);
+
+  return changed;
+}
+
+static void
+toplevel_surface_commit (MetaWaylandSurface *surface)
+{
+  if (actor_surface_commit (surface))
+    {
+      MetaWindow *window = surface->window;
+      MetaWaylandBuffer *buffer = surface->pending.buffer;
 
+      meta_window_set_surface_mapped (window, buffer != NULL);
       /* We resize X based surfaces according to X events */
       if (buffer != NULL && window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
         {
@@ -286,11 +303,27 @@ toplevel_surface_commit (MetaWaylandSurface *surface)
                                              surface->pending.dx, surface->pending.dy);
         }
     }
+}
 
-  if (surface->pending.opaque_region)
-    meta_surface_actor_set_opaque_region (surface_actor, surface->pending.opaque_region);
-  if (surface->pending.input_region)
-    meta_surface_actor_set_input_region (surface_actor, surface->pending.input_region);
+static void
+subsurface_surface_commit (MetaWaylandSurface *surface)
+{
+  if (actor_surface_commit (surface))
+    {
+      MetaSurfaceActor *surface_actor = surface->surface_actor;
+      MetaWaylandBuffer *buffer = surface->pending.buffer;
+      float x, y;
+
+      if (buffer != NULL)
+        clutter_actor_show (CLUTTER_ACTOR (surface_actor));
+      else
+        clutter_actor_hide (CLUTTER_ACTOR (surface_actor));
+
+      clutter_actor_get_position (CLUTTER_ACTOR (surface_actor), &x, &y);
+      x += surface->pending.dx;
+      y += surface->pending.dy;
+      clutter_actor_set_position (CLUTTER_ACTOR (surface_actor), x, y);
+    }
 }
 
 static void
@@ -310,6 +343,8 @@ meta_wayland_surface_commit (struct wl_client *client,
     cursor_surface_commit (surface);
   else if (surface->window)
     toplevel_surface_commit (surface);
+  else if (surface->subsurface.resource)
+    subsurface_surface_commit (surface);
 
   if (surface->pending.buffer)
     {
@@ -903,6 +938,132 @@ bind_gtk_shell (struct wl_client *client,
   gtk_shell_send_capabilities (resource, GTK_SHELL_CAPABILITY_GLOBAL_APP_MENU);
 }
 
+static void
+wl_subsurface_destroy (struct wl_client *client,
+                       struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static void
+wl_subsurface_set_position (struct wl_client *client,
+                            struct wl_resource *resource,
+                            int32_t x,
+                            int32_t y)
+{
+  MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
+
+  clutter_actor_set_position (CLUTTER_ACTOR (surface->surface_actor), x, y);
+}
+
+static void
+wl_subsurface_place_above (struct wl_client *client,
+                           struct wl_resource *resource,
+                           struct wl_resource *sibling_resource)
+{
+  ClutterActor *parent_actor;
+  MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
+  MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
+
+  parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
+
+  clutter_actor_set_child_above_sibling (parent_actor,
+                                         CLUTTER_ACTOR (surface->surface_actor),
+                                         CLUTTER_ACTOR (sibling->surface_actor));
+}
+
+static void
+wl_subsurface_place_below (struct wl_client *client,
+                           struct wl_resource *resource,
+                           struct wl_resource *sibling_resource)
+{
+  ClutterActor *parent_actor;
+  MetaWaylandSurfaceExtension *subsurface = wl_resource_get_user_data (resource);
+  MetaWaylandSurface *surface = wl_container_of (subsurface, surface, subsurface);
+  MetaWaylandSurface *sibling = wl_resource_get_user_data (sibling_resource);
+
+  parent_actor = clutter_actor_get_parent (CLUTTER_ACTOR (surface->surface_actor));
+
+  clutter_actor_set_child_below_sibling (parent_actor,
+                                         CLUTTER_ACTOR (surface->surface_actor),
+                                         CLUTTER_ACTOR (sibling->surface_actor));
+}
+
+static void
+wl_subsurface_set_sync (struct wl_client *client,
+                        struct wl_resource *resource)
+{
+  g_warning ("TODO: support wl_subsurface.set_sync");
+}
+
+static void
+wl_subsurface_set_desync (struct wl_client *client,
+                          struct wl_resource *resource)
+{
+  g_warning ("TODO: support wl_subsurface.set_desync");
+}
+
+static const struct wl_subsurface_interface meta_wayland_subsurface_interface = {
+  wl_subsurface_destroy,
+  wl_subsurface_set_position,
+  wl_subsurface_place_above,
+  wl_subsurface_place_below,
+  wl_subsurface_set_sync,
+  wl_subsurface_set_desync,
+};
+
+static void
+wl_subcompositor_destroy (struct wl_client *client,
+                          struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static void
+wl_subcompositor_get_subsurface (struct wl_client *client,
+                                 struct wl_resource *resource,
+                                 guint32 id,
+                                 struct wl_resource *surface_resource,
+                                 struct wl_resource *parent_resource)
+{
+  MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
+  MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
+
+  if (!create_surface_extension (&surface->subsurface, client, surface_resource, resource, id,
+                                 META_GTK_SURFACE_VERSION,
+                                 &wl_subsurface_interface,
+                                 &meta_wayland_subsurface_interface))
+    {
+      wl_resource_post_error (surface_resource,
+                              WL_DISPLAY_ERROR_INVALID_OBJECT,
+                              "wl_subcompositor::get_subsurface already requested");
+      return;
+    }
+
+  clutter_actor_add_child (CLUTTER_ACTOR (parent->surface_actor),
+                           CLUTTER_ACTOR (surface->surface_actor));
+}
+
+static const struct wl_subcompositor_interface meta_wayland_subcompositor_interface = {
+  wl_subcompositor_destroy,
+  wl_subcompositor_get_subsurface,
+};
+
+static void
+bind_subcompositor (struct wl_client *client,
+                    void             *data,
+                    guint32           version,
+                    guint32           id)
+{
+  struct wl_resource *resource;
+
+  resource = wl_resource_create (client, &wl_subcompositor_interface,
+                                MIN (META_WL_SUBCOMPOSITOR_VERSION, version), id);
+  wl_resource_set_implementation (resource, &meta_wayland_subcompositor_interface, data, NULL);
+}
+
 void
 meta_wayland_init_shell (MetaWaylandCompositor *compositor)
 {
@@ -917,6 +1078,12 @@ meta_wayland_init_shell (MetaWaylandCompositor *compositor)
                        META_GTK_SHELL_VERSION,
                        compositor, bind_gtk_shell) == NULL)
     g_error ("Failed to register a global gtk-shell object");
+
+  if (wl_global_create (compositor->wayland_display,
+                        &wl_subcompositor_interface,
+                        META_WL_SUBCOMPOSITOR_VERSION,
+                        compositor, bind_subcompositor) == NULL)
+    g_error ("Failed to register a global wl-subcompositor object");
 }
 
 void
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 4edab87..28dfa14 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -83,6 +83,7 @@ struct _MetaWaylandSurface
   MetaWaylandSurfaceExtension xdg_surface;
   MetaWaylandSurfaceExtension xdg_popup;
   MetaWaylandSurfaceExtension gtk_surface;
+  MetaWaylandSurfaceExtension subsurface;
 
   /* All the pending state, that wl_surface.commit will apply. */
   MetaWaylandDoubleBufferedState pending;
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index 7e85f8b..531cbd4 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -42,6 +42,7 @@
 #define META_XSERVER_VERSION                1
 #define META_GTK_SHELL_VERSION              1
 #define META_XDG_SHELL_VERSION              1
+#define META_WL_SUBCOMPOSITOR_VERSION       1
 
 /* Slave objects (version inherited from a master object) */
 #define META_WL_DATA_OFFER_VERSION          1 /* from wl_data_device */
@@ -55,6 +56,7 @@
 #define META_GTK_SURFACE_VERSION            1 /* from gtk_shell */
 #define META_XDG_SURFACE_VERSION            1 /* from xdg_shell */
 #define META_XDG_POPUP_VERSION              1 /* from xdg_shell */
+#define META_WL_SUBSURFACE_VERSION          1 /* from wl_subcompositor */
 
 /* The first version to implement a specific event */
 #define META_WL_SEAT_HAS_NAME               2


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