[mutter] wayland: Push actor state instead of itself pulling



commit 44624736c59fb44f574e62dd4b7838f8c0157f2d
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Dec 22 14:28:28 2017 +0800

    wayland: Push actor state instead of itself pulling
    
    Make the Wayland objects push the state relevant to their role to the
    MetaSurfaceActor instead of MetaSurfaceActorWayland pulling the state
    from the associated surface.
    
    This makes the relationship between the actor and the objects that
    constructs it more clear; the actor is a drawable that the protocol
    objects control, not the other way around.
    
    This will make it easier to "detach" a surface actor from a surface,
    which is necessary when unmapping a window while the underlying surface
    is yet to be destroyed and potentially reused.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/5
    https://bugzilla.gnome.org/show_bug.cgi?id=791938

 src/compositor/meta-surface-actor-wayland.c | 224 +---------------------------
 src/compositor/meta-surface-actor-wayland.h |   9 --
 src/wayland/meta-wayland-actor-surface.c    | 145 +++++++++++++++++-
 src/wayland/meta-wayland-actor-surface.h    |   6 +
 src/wayland/meta-wayland-shell-surface.c    |  48 +++++-
 src/wayland/meta-wayland-shell-surface.h    |   3 +
 src/wayland/meta-wayland-subsurface.c       | 112 +++++++++++---
 src/wayland/meta-wayland-subsurface.h       |   5 +
 src/wayland/meta-wayland-surface.c          |  39 -----
 src/wayland/meta-wayland-surface.h          |   4 -
 src/wayland/meta-wayland-wl-shell.c         |   5 +-
 src/wayland/meta-wayland-xdg-shell.c        |   8 +-
 src/wayland/meta-window-wayland.c           |   9 +-
 13 files changed, 308 insertions(+), 309 deletions(-)
---
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
index fb4876141..7505b7d79 100644
--- a/src/compositor/meta-surface-actor-wayland.c
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -90,216 +90,6 @@ meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor)
   return FALSE;
 }
 
-double
-meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *self)
-{
-   MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
-   MetaWindow *window;
-   int geometry_scale = 1;
-
-   g_assert (surface);
-
-   window = meta_wayland_surface_get_toplevel_window (surface);
-
-   if (!meta_is_stage_views_scaled ())
-     {
-       /* XXX: We do not handle x11 clients yet */
-       if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
-         geometry_scale = meta_window_wayland_get_geometry_scale (window);
-     }
-
-   return (double) geometry_scale / (double) surface->scale;
-}
-
-static void
-logical_to_actor_position (MetaSurfaceActorWayland *self,
-                           int                     *x,
-                           int                     *y)
-{
-  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
-  MetaWindow *toplevel_window;
-  int geometry_scale = 1;
-
-  g_assert (surface);
-
-  toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
-  if (toplevel_window)
-    geometry_scale = meta_window_wayland_get_geometry_scale (toplevel_window);
-
-  *x = *x * geometry_scale;
-  *y = *y * geometry_scale;
-}
-
-/* Convert the current actor state to the corresponding subsurface rectangle
- * in logical pixel coordinate space. */
-void
-meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
-                                                MetaRectangle           *rect)
-{
-  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
-  MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface);
-  CoglTexture *texture;
-  MetaWindow *toplevel_window;
-  int geometry_scale;
-  float x, y;
-
-  g_assert (surface);
-
-  texture = buffer->texture;
-  toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
-  geometry_scale = meta_window_wayland_get_geometry_scale (toplevel_window);
-
-  clutter_actor_get_position (CLUTTER_ACTOR (self), &x, &y);
-  *rect = (MetaRectangle) {
-    .x = x / geometry_scale,
-    .y = y / geometry_scale,
-    .width = cogl_texture_get_width (texture) / surface->scale,
-    .height = cogl_texture_get_height (texture) / surface->scale,
-  };
-}
-
-void
-meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self)
-{
-  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
-  MetaWindow *window;
-  int x = surface->offset_x + surface->sub.x;
-  int y = surface->offset_y + surface->sub.y;
-
-  g_assert (surface);
-
-  window = meta_wayland_surface_get_toplevel_window (surface);
-  if (window && window->client_type == META_WINDOW_CLIENT_TYPE_X11)
-    {
-      /* Bail directly if this is part of a Xwayland window and warn
-       * if there happen to be offsets anyway since that is not supposed
-       * to happen. */
-      g_warn_if_fail (x == 0 && y == 0);
-      return;
-    }
-
-  logical_to_actor_position (self, &x, &y);
-  clutter_actor_set_position (CLUTTER_ACTOR (self), x, y);
-}
-
-void
-meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self)
-{
-  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
-  MetaShapedTexture *stex =
-    meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
-  double texture_scale;
-
-  g_assert (surface);
-
-  /* Given the surface's window type and what output the surface actor has the
-   * largest region, scale the actor with the determined scale. */
-  texture_scale = meta_surface_actor_wayland_get_scale (self);
-
-  /* Actor scale. */
-  clutter_actor_set_scale (CLUTTER_ACTOR (stex), texture_scale, texture_scale);
-
-  /* Input region */
-  if (surface->input_region)
-    {
-      cairo_region_t *scaled_input_region;
-      int region_scale;
-
-      /* The input region from the Wayland surface is in the Wayland surface
-       * coordinate space, while the surface actor input region is in the
-       * physical pixel coordinate space. */
-      region_scale = (int)(surface->scale * texture_scale);
-      scaled_input_region = meta_region_scale (surface->input_region,
-                                               region_scale);
-      meta_surface_actor_set_input_region (META_SURFACE_ACTOR (self),
-                                           scaled_input_region);
-      cairo_region_destroy (scaled_input_region);
-    }
-  else
-    {
-      meta_surface_actor_set_input_region (META_SURFACE_ACTOR (self), NULL);
-    }
-
-  /* Opaque region */
-  if (surface->opaque_region)
-    {
-      cairo_region_t *scaled_opaque_region;
-
-      /* The opaque region from the Wayland surface is in Wayland surface
-       * coordinate space, while the surface actor opaque region is in the
-       * same coordinate space as the unscaled buffer texture. */
-      scaled_opaque_region = meta_region_scale (surface->opaque_region,
-                                                surface->scale);
-      meta_surface_actor_set_opaque_region (META_SURFACE_ACTOR (self),
-                                            scaled_opaque_region);
-      cairo_region_destroy (scaled_opaque_region);
-    }
-  else
-    {
-      meta_surface_actor_set_opaque_region (META_SURFACE_ACTOR (self), NULL);
-    }
-
-  meta_surface_actor_wayland_sync_subsurface_state (self);
-}
-
-void
-meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self)
-{
-  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
-  MetaWindow *window;
-  GList *iter;
-
-  g_assert (surface);
-
-  window = meta_wayland_surface_get_toplevel_window (surface);
-  meta_surface_actor_wayland_sync_state (self);
-
-  if (window && window->client_type != META_WINDOW_CLIENT_TYPE_X11)
-    {
-      for (iter = surface->subsurfaces; iter != NULL; iter = iter->next)
-        {
-          MetaWaylandSurface *subsurf = iter->data;
-
-          meta_surface_actor_wayland_sync_state_recursive (
-            META_SURFACE_ACTOR_WAYLAND (subsurf->surface_actor));
-        }
-    }
-}
-
-gboolean
-meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
-                                          MetaLogicalMonitor      *logical_monitor)
-{
-  float x, y, width, height;
-  cairo_rectangle_int_t actor_rect;
-  cairo_region_t *region;
-  gboolean is_on_monitor;
-
-  clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y);
-  clutter_actor_get_transformed_size (CLUTTER_ACTOR (self), &width, &height);
-
-  actor_rect.x = (int)roundf (x);
-  actor_rect.y = (int)roundf (y);
-  actor_rect.width = (int)roundf (x + width) - actor_rect.x;
-  actor_rect.height = (int)roundf (y + height) - actor_rect.y;
-
-  /* Calculate the scaled surface actor region. */
-  region = cairo_region_create_rectangle (&actor_rect);
-
-  cairo_region_intersect_rectangle (region,
-                                   &((cairo_rectangle_int_t) {
-                                     .x = logical_monitor->rect.x,
-                                     .y = logical_monitor->rect.y,
-                                     .width = logical_monitor->rect.width,
-                                     .height = logical_monitor->rect.height,
-                                   }));
-
-  is_on_monitor = !cairo_region_is_empty (region);
-  cairo_region_destroy (region);
-
-  return is_on_monitor;
-}
-
 void
 meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
                                                 struct wl_list *frame_callbacks)
@@ -328,16 +118,11 @@ meta_surface_actor_wayland_get_preferred_width  (ClutterActor *actor,
                                                  gfloat       *natural_width_p)
 {
   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
-  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
   MetaShapedTexture *stex;
   double scale;
 
-  if (surface)
-    scale = meta_surface_actor_wayland_get_scale (self);
-  else
-    scale = 1.0;
-
   stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+  clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale, NULL);
   clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex),
                                      for_height,
                                      min_width_p,
@@ -357,16 +142,11 @@ meta_surface_actor_wayland_get_preferred_height  (ClutterActor *actor,
                                                   gfloat       *natural_height_p)
 {
   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
-  MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (self);
   MetaShapedTexture *stex;
   double scale;
 
-  if (surface)
-    scale = meta_surface_actor_wayland_get_scale (self);
-  else
-    scale = 1.0;
-
   stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+  clutter_actor_get_scale (CLUTTER_ACTOR (stex), NULL, &scale);
   clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex),
                                       for_width,
                                       min_height_p,
diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h
index 58943cf72..277b1a39d 100644
--- a/src/compositor/meta-surface-actor-wayland.h
+++ b/src/compositor/meta-surface-actor-wayland.h
@@ -67,15 +67,6 @@ double meta_surface_actor_wayland_get_scale (MetaSurfaceActorWayland *actor);
 void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *self,
                                                      MetaRectangle           *rect);
 
-void meta_surface_actor_wayland_sync_state (MetaSurfaceActorWayland *self);
-
-void meta_surface_actor_wayland_sync_state_recursive (MetaSurfaceActorWayland *self);
-
-void meta_surface_actor_wayland_sync_subsurface_state (MetaSurfaceActorWayland *self);
-
-gboolean meta_surface_actor_wayland_is_on_monitor (MetaSurfaceActorWayland *self,
-                                                   MetaLogicalMonitor      *logical_monitor);
-
 void meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
                                                      struct wl_list *frame_callbacks);
 
diff --git a/src/wayland/meta-wayland-actor-surface.c b/src/wayland/meta-wayland-actor-surface.c
index a07d0d5e9..3ffe493f6 100644
--- a/src/wayland/meta-wayland-actor-surface.c
+++ b/src/wayland/meta-wayland-actor-surface.c
@@ -23,8 +23,12 @@
 
 #include "wayland/meta-wayland-actor-surface.h"
 
+#include "backends/meta-backend-private.h"
+#include "backends/meta-logical-monitor.h"
 #include "compositor/meta-surface-actor-wayland.h"
+#include "compositor/region-utils.h"
 #include "wayland/meta-wayland-surface.h"
+#include "wayland/meta-window-wayland.h"
 
 G_DEFINE_TYPE (MetaWaylandActorSurface,
                meta_wayland_actor_surface,
@@ -55,10 +59,110 @@ queue_surface_actor_frame_callbacks (MetaWaylandSurface      *surface,
   wl_list_init (&pending->frame_callback_list);
 }
 
+double
+meta_wayland_actor_surface_calculate_scale (MetaWaylandActorSurface *actor_surface)
+{
+  MetaWaylandSurfaceRole *surface_role =
+    META_WAYLAND_SURFACE_ROLE (actor_surface);
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+  MetaWindow *toplevel_window;
+  int geometry_scale;
+
+  toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
+  if (meta_is_stage_views_scaled ())
+    {
+      geometry_scale = 1;
+    }
+  else
+    {
+      if (!toplevel_window ||
+          toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+        geometry_scale = 1;
+      else
+        geometry_scale =
+          meta_window_wayland_get_geometry_scale (toplevel_window);
+    }
+
+  return (double) geometry_scale / (double) surface->scale;
+}
+
+static void
+meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor_surface)
+{
+  MetaWaylandSurfaceRole *surface_role =
+    META_WAYLAND_SURFACE_ROLE (actor_surface);
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+  MetaSurfaceActor *surface_actor;
+  MetaShapedTexture *stex;
+  double actor_scale;
+  GList *l;
+
+  surface_actor = surface->surface_actor;
+  stex = meta_surface_actor_get_texture (surface_actor);
+
+  actor_scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
+  clutter_actor_set_scale (CLUTTER_ACTOR (stex), actor_scale, actor_scale);
+
+  if (surface->input_region)
+    {
+      cairo_region_t *scaled_input_region;
+      int region_scale;
+
+      /* Wayland surface coordinate space -> stage coordinate space */
+      region_scale = (int) (surface->scale * actor_scale);
+      scaled_input_region = meta_region_scale (surface->input_region,
+                                               region_scale);
+      meta_surface_actor_set_input_region (surface_actor, scaled_input_region);
+      cairo_region_destroy (scaled_input_region);
+    }
+  else
+    {
+      meta_surface_actor_set_input_region (surface_actor, NULL);
+    }
+
+  if (surface->opaque_region)
+    {
+      cairo_region_t *scaled_opaque_region;
+
+      /* Wayland surface coordinate space -> stage coordinate space */
+      scaled_opaque_region = meta_region_scale (surface->opaque_region,
+                                                surface->scale);
+      meta_surface_actor_set_opaque_region (surface_actor,
+                                            scaled_opaque_region);
+      cairo_region_destroy (scaled_opaque_region);
+    }
+  else
+    {
+      meta_surface_actor_set_opaque_region (surface_actor, NULL);
+    }
+
+  for (l = surface->subsurfaces; l; l = l->next)
+    {
+      MetaWaylandSurface *subsurface_surface = l->data;
+      MetaWaylandActorSurface *subsurface_actor_surface =
+        META_WAYLAND_ACTOR_SURFACE (subsurface_surface->role);
+
+      meta_wayland_actor_surface_sync_actor_state (subsurface_actor_surface);
+    }
+}
+
+void
+meta_wayland_actor_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface)
+{
+  MetaWaylandActorSurfaceClass *actor_surface_class =
+    META_WAYLAND_ACTOR_SURFACE_GET_CLASS (actor_surface);
+
+  actor_surface_class->sync_actor_state (actor_surface);
+}
+
 static void
 meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole  *surface_role,
                                    MetaWaylandPendingState *pending)
 {
+  MetaWaylandActorSurface *actor_surface =
+    META_WAYLAND_ACTOR_SURFACE (surface_role);
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
   MetaWaylandSurface *toplevel_surface;
@@ -69,8 +173,7 @@ meta_wayland_actor_surface_commit (MetaWaylandSurfaceRole  *surface_role,
   if (!toplevel_surface || !toplevel_surface->window)
     return;
 
-  meta_surface_actor_wayland_sync_state (
-    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
+  meta_wayland_actor_surface_sync_actor_state (actor_surface);
 }
 
 static gboolean
@@ -79,10 +182,38 @@ meta_wayland_actor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *surfac
 {
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
-  MetaSurfaceActorWayland *actor =
-    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
-
-  return meta_surface_actor_wayland_is_on_monitor (actor, logical_monitor);
+  ClutterActor *actor = CLUTTER_ACTOR (surface->surface_actor);
+  float x, y, width, height;
+  cairo_rectangle_int_t actor_rect;
+  cairo_region_t *region;
+  MetaRectangle logical_monitor_layout;
+  gboolean is_on_monitor;
+
+  clutter_actor_get_transformed_position (actor, &x, &y);
+  clutter_actor_get_transformed_size (actor, &width, &height);
+
+  actor_rect.x = (int) roundf (x);
+  actor_rect.y = (int) roundf (y);
+  actor_rect.width = (int) roundf (x + width) - actor_rect.x;
+  actor_rect.height = (int) roundf (y + height) - actor_rect.y;
+
+  /* Calculate the scaled surface actor region. */
+  region = cairo_region_create_rectangle (&actor_rect);
+
+  logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
+
+  cairo_region_intersect_rectangle (region,
+                                   &((cairo_rectangle_int_t) {
+                                     .x = logical_monitor_layout.x,
+                                     .y = logical_monitor_layout.y,
+                                     .width = logical_monitor_layout.width,
+                                     .height = logical_monitor_layout.height,
+                                   }));
+
+  is_on_monitor = !cairo_region_is_empty (region);
+  cairo_region_destroy (region);
+
+  return is_on_monitor;
 }
 
 static void
@@ -100,4 +231,6 @@ meta_wayland_actor_surface_class_init (MetaWaylandActorSurfaceClass *klass)
   surface_role_class->commit = meta_wayland_actor_surface_commit;
   surface_role_class->is_on_logical_monitor =
     meta_wayland_actor_surface_is_on_logical_monitor;
+
+  klass->sync_actor_state = meta_wayland_actor_surface_real_sync_actor_state;
 }
diff --git a/src/wayland/meta-wayland-actor-surface.h b/src/wayland/meta-wayland-actor-surface.h
index 9f0f79e7b..a5cc24455 100644
--- a/src/wayland/meta-wayland-actor-surface.h
+++ b/src/wayland/meta-wayland-actor-surface.h
@@ -32,6 +32,12 @@ G_DECLARE_DERIVABLE_TYPE (MetaWaylandActorSurface,
 struct _MetaWaylandActorSurfaceClass
 {
   MetaWaylandSurfaceRoleClass parent_class;
+
+  void (* sync_actor_state) (MetaWaylandActorSurface *actor_surface);
 };
 
+void meta_wayland_actor_surface_sync_actor_state (MetaWaylandActorSurface *actor_surface);
+
+double meta_wayland_actor_surface_calculate_scale (MetaWaylandActorSurface *actor_surface);
+
 #endif /* META_WAYLAND_ACTOR_SURFACE_H */
diff --git a/src/wayland/meta-wayland-shell-surface.c b/src/wayland/meta-wayland-shell-surface.c
index 023ece00a..becaecb08 100644
--- a/src/wayland/meta-wayland-shell-surface.c
+++ b/src/wayland/meta-wayland-shell-surface.c
@@ -26,11 +26,53 @@
 #include "compositor/meta-surface-actor-wayland.h"
 #include "wayland/meta-wayland-actor-surface.h"
 #include "wayland/meta-wayland-buffer.h"
+#include "wayland/meta-wayland-subsurface.h"
+#include "wayland/meta-wayland-surface.h"
+#include "wayland/meta-window-wayland.h"
 
 G_DEFINE_TYPE (MetaWaylandShellSurface,
                meta_wayland_shell_surface,
                META_TYPE_WAYLAND_ACTOR_SURFACE)
 
+void
+meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface,
+                                               MetaRectangle           *out_geometry)
+{
+  MetaWaylandSurfaceRole *surface_role =
+    META_WAYLAND_SURFACE_ROLE (shell_surface);
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+  MetaWaylandBuffer *buffer;
+  CoglTexture *texture;
+  MetaRectangle geometry;
+  GList *l;
+
+  buffer = surface->buffer_ref.buffer;
+  if (!buffer)
+    return;
+
+  texture = meta_wayland_buffer_get_texture (buffer);
+  geometry = (MetaRectangle) {
+    .x = 0,
+    .y = 0,
+    .width = cogl_texture_get_width (texture) / surface->scale,
+    .height = cogl_texture_get_height (texture) / surface->scale,
+  };
+
+  for (l = surface->subsurfaces; l; l = l->next)
+    {
+      MetaWaylandSurface *subsurface_surface = l->data;
+      MetaWaylandSubsurface *subsurface =
+        META_WAYLAND_SUBSURFACE (subsurface_surface->role);
+
+      meta_wayland_subsurface_union_geometry (subsurface,
+                                              0, 0,
+                                              &geometry);
+    }
+
+  *out_geometry = geometry;
+}
+
 void
 meta_wayland_shell_surface_configure (MetaWaylandShellSurface *shell_surface,
                                       int                      new_x,
@@ -83,13 +125,14 @@ static void
 meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole  *surface_role,
                                            MetaWaylandPendingState *pending)
 {
+  MetaWaylandActorSurface *actor_surface =
+    META_WAYLAND_ACTOR_SURFACE (surface_role);
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
   MetaWaylandSurfaceRoleClass *surface_role_class;
   MetaWindow *window;
   MetaWaylandBuffer *buffer;
   CoglTexture *texture;
-  MetaSurfaceActorWayland *surface_actor;
   double scale;
 
   surface_role_class =
@@ -104,8 +147,7 @@ meta_wayland_shell_surface_surface_commit (MetaWaylandSurfaceRole  *surface_role
   if (!window)
     return;
 
-  surface_actor = META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
-  scale = meta_surface_actor_wayland_get_scale (surface_actor);
+  scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
   texture = meta_wayland_buffer_get_texture (buffer);
 
   window->buffer_rect.width = cogl_texture_get_width (texture) * scale;
diff --git a/src/wayland/meta-wayland-shell-surface.h b/src/wayland/meta-wayland-shell-surface.h
index 72b0828b5..0cfb5b69d 100644
--- a/src/wayland/meta-wayland-shell-surface.h
+++ b/src/wayland/meta-wayland-shell-surface.h
@@ -61,4 +61,7 @@ void meta_wayland_shell_surface_close (MetaWaylandShellSurface *shell_surface);
 void meta_wayland_shell_surface_managed (MetaWaylandShellSurface *shell_surface,
                                          MetaWindow              *window);
 
+void meta_wayland_shell_surface_calculate_geometry (MetaWaylandShellSurface *shell_surface,
+                                                    MetaRectangle           *out_geometry);
+
 #endif /* META_WAYLAND_SHELL_SURFACE_H */
diff --git a/src/wayland/meta-wayland-subsurface.c b/src/wayland/meta-wayland-subsurface.c
index 1e630fa98..4bcffd0ea 100644
--- a/src/wayland/meta-wayland-subsurface.c
+++ b/src/wayland/meta-wayland-subsurface.c
@@ -24,7 +24,10 @@
 
 #include "compositor/meta-surface-actor-wayland.h"
 #include "wayland/meta-wayland.h"
+#include "wayland/meta-wayland-actor-surface.h"
+#include "wayland/meta-wayland-buffer.h"
 #include "wayland/meta-wayland-surface.h"
+#include "wayland/meta-window-wayland.h"
 
 typedef enum
 {
@@ -48,10 +51,39 @@ G_DEFINE_TYPE (MetaWaylandSubsurface,
                meta_wayland_subsurface,
                META_TYPE_WAYLAND_ACTOR_SURFACE)
 
+static void
+sync_actor_subsurface_state (MetaWaylandSurface *surface)
+{
+  ClutterActor *actor = CLUTTER_ACTOR (surface->surface_actor);
+  MetaWindow *toplevel_window;
+  int geometry_scale;
+  int x, y;
+
+  toplevel_window = meta_wayland_surface_get_toplevel_window (surface);
+  if (!toplevel_window)
+    return;
+
+  if (toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+    return;
+
+  geometry_scale = meta_window_wayland_get_geometry_scale (toplevel_window);
+  x = (surface->offset_x + surface->sub.x) * geometry_scale;
+  y = (surface->offset_y + surface->sub.y) * geometry_scale;
+
+  clutter_actor_set_position (actor, x, y);
+
+  if (surface->buffer_ref.buffer)
+    clutter_actor_show (actor);
+  else
+    clutter_actor_hide (actor);
+}
+
 void
 meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface)
 {
   MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface);
+  MetaWaylandActorSurface *actor_surface =
+    META_WAYLAND_ACTOR_SURFACE (subsurface);
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
 
@@ -108,27 +140,48 @@ meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface)
   if (meta_wayland_surface_is_effectively_synchronized (surface))
     meta_wayland_surface_apply_pending_state (surface, surface->sub.pending);
 
-  meta_surface_actor_wayland_sync_subsurface_state (
-    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor));
+  meta_wayland_actor_surface_sync_actor_state (actor_surface);
 }
 
-static void
-meta_wayland_subsurface_commit (MetaWaylandSurfaceRole  *surface_role,
-                                MetaWaylandPendingState *pending)
+void
+meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
+                                        int                    parent_x,
+                                        int                    parent_y,
+                                        MetaRectangle         *out_geometry)
 {
-  MetaWaylandSurfaceRoleClass *surface_role_class;
+  MetaWaylandSurfaceRole *surface_role = META_WAYLAND_SURFACE_ROLE (subsurface);
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
-  ClutterActor *actor = CLUTTER_ACTOR (surface->surface_actor);
-
-  surface_role_class =
-    META_WAYLAND_SURFACE_ROLE_CLASS (meta_wayland_subsurface_parent_class);
-  surface_role_class->commit (surface_role, pending);
-
-  if (surface->buffer_ref.buffer != NULL)
-    clutter_actor_show (actor);
-  else
-    clutter_actor_hide (actor);
+  MetaWaylandBuffer *buffer;
+  CoglTexture *texture;
+  MetaRectangle geometry;
+  GList *l;
+
+  buffer = surface->buffer_ref.buffer;
+  if (!buffer)
+    return;
+
+  texture = meta_wayland_buffer_get_texture (buffer);
+  geometry = (MetaRectangle) {
+    .x = surface->offset_x + surface->sub.x,
+    .y = surface->offset_y + surface->sub.y,
+    .width = cogl_texture_get_width (texture) / surface->scale,
+    .height = cogl_texture_get_height (texture) / surface->scale,
+  };
+
+  meta_rectangle_union (out_geometry, &geometry, out_geometry);
+
+  for (l = surface->subsurfaces; l; l = l->next)
+    {
+      MetaWaylandSurface *subsurface_surface = l->data;
+      MetaWaylandSubsurface *subsurface =
+        META_WAYLAND_SUBSURFACE (subsurface_surface->role);
+
+      meta_wayland_subsurface_union_geometry (subsurface,
+                                              parent_x + geometry.x,
+                                              parent_y + geometry.y,
+                                              out_geometry);
+    }
 }
 
 static MetaWaylandSurface *
@@ -144,6 +197,21 @@ meta_wayland_subsurface_get_toplevel (MetaWaylandSurfaceRole *surface_role)
     return NULL;
 }
 
+static void
+meta_wayland_subsurface_sync_actor_state (MetaWaylandActorSurface *actor_surface)
+{
+  MetaWaylandSurfaceRole *surface_role =
+    META_WAYLAND_SURFACE_ROLE (actor_surface);
+  MetaWaylandSurface *surface =
+    meta_wayland_surface_role_get_surface (surface_role);
+  MetaWaylandActorSurfaceClass *actor_surface_class =
+    META_WAYLAND_ACTOR_SURFACE_CLASS (meta_wayland_subsurface_parent_class);
+
+  actor_surface_class->sync_actor_state (actor_surface);
+
+  sync_actor_subsurface_state (surface);
+}
+
 static void
 meta_wayland_subsurface_init (MetaWaylandSubsurface *role)
 {
@@ -154,9 +222,13 @@ meta_wayland_subsurface_class_init (MetaWaylandSubsurfaceClass *klass)
 {
   MetaWaylandSurfaceRoleClass *surface_role_class =
     META_WAYLAND_SURFACE_ROLE_CLASS (klass);
+  MetaWaylandActorSurfaceClass *actor_surface_class =
+    META_WAYLAND_ACTOR_SURFACE_CLASS (klass);
 
-  surface_role_class->commit = meta_wayland_subsurface_commit;
   surface_role_class->get_toplevel = meta_wayland_subsurface_get_toplevel;
+
+  actor_surface_class->sync_actor_state =
+    meta_wayland_subsurface_sync_actor_state;
 }
 
 static void
@@ -355,6 +427,7 @@ wl_subcompositor_get_subsurface (struct wl_client   *client,
 {
   MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
   MetaWaylandSurface *parent = wl_resource_get_user_data (parent_resource);
+  MetaWindow *toplevel_window;
 
   if (surface->wl_subsurface)
     {
@@ -374,6 +447,11 @@ wl_subcompositor_get_subsurface (struct wl_client   *client,
       return;
     }
 
+  toplevel_window = meta_wayland_surface_get_toplevel_window (parent);
+  if (toplevel_window &&
+      toplevel_window->client_type == META_WINDOW_CLIENT_TYPE_X11)
+    g_warning ("XWayland subsurfaces not currently supported");
+
   surface->wl_subsurface =
     wl_resource_create (client,
                         &wl_subsurface_interface,
diff --git a/src/wayland/meta-wayland-subsurface.h b/src/wayland/meta-wayland-subsurface.h
index eac3c6c7b..d92c02197 100644
--- a/src/wayland/meta-wayland-subsurface.h
+++ b/src/wayland/meta-wayland-subsurface.h
@@ -31,6 +31,11 @@ G_DECLARE_FINAL_TYPE (MetaWaylandSubsurface,
 
 void meta_wayland_subsurface_parent_state_applied (MetaWaylandSubsurface *subsurface);
 
+void meta_wayland_subsurface_union_geometry (MetaWaylandSubsurface *subsurface,
+                                             int                    parent_x,
+                                             int                    parent_y,
+                                             MetaRectangle         *out_geometry);
+
 void meta_wayland_subsurfaces_init (MetaWaylandCompositor *compositor);
 
 #endif /* META_WAYLAND_SUBSURFACE_H */
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index 301992627..8c41a1078 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -334,45 +334,6 @@ dnd_surface_commit (MetaWaylandSurfaceRole  *surface_role,
   meta_wayland_surface_queue_pending_state_frame_callbacks (surface, pending);
 }
 
-void
-meta_wayland_surface_calculate_window_geometry (MetaWaylandSurface *surface,
-                                                MetaRectangle      *total_geometry,
-                                                float               parent_x,
-                                                float               parent_y)
-{
-  MetaSurfaceActorWayland *surface_actor =
-    META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
-  MetaRectangle subsurface_rect;
-  MetaRectangle geom;
-  GList *l;
-
-  /* Unmapped surfaces don't count. */
-  if (!CLUTTER_ACTOR_IS_VISIBLE (CLUTTER_ACTOR (surface_actor)))
-    return;
-
-  if (!surface->buffer_ref.buffer)
-    return;
-
-  meta_surface_actor_wayland_get_subsurface_rect (surface_actor,
-                                                  &subsurface_rect);
-
-  geom.x = parent_x + subsurface_rect.x;
-  geom.y = parent_x + subsurface_rect.y;
-  geom.width = subsurface_rect.width;
-  geom.height = subsurface_rect.height;
-
-  meta_rectangle_union (total_geometry, &geom, total_geometry);
-
-  for (l = surface->subsurfaces; l != NULL; l = l->next)
-    {
-      MetaWaylandSurface *subsurface = l->data;
-      meta_wayland_surface_calculate_window_geometry (subsurface,
-                                                      total_geometry,
-                                                      subsurface_rect.x,
-                                                      subsurface_rect.y);
-    }
-}
-
 void
 meta_wayland_surface_destroy_window (MetaWaylandSurface *surface)
 {
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 92e385030..e04acb655 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -278,10 +278,6 @@ MetaWaylandSurface * meta_wayland_surface_role_get_surface (MetaWaylandSurfaceRo
 
 cairo_region_t *    meta_wayland_surface_calculate_input_region (MetaWaylandSurface *surface);
 
-void                meta_wayland_surface_calculate_window_geometry (MetaWaylandSurface *surface,
-                                                                    MetaRectangle      *total_geometry,
-                                                                    float               parent_x,
-                                                                    float               parent_y);
 
 void                meta_wayland_surface_destroy_window (MetaWaylandSurface *surface);
 
diff --git a/src/wayland/meta-wayland-wl-shell.c b/src/wayland/meta-wayland-wl-shell.c
index 86d809193..4b93c95c8 100644
--- a/src/wayland/meta-wayland-wl-shell.c
+++ b/src/wayland/meta-wayland-wl-shell.c
@@ -30,6 +30,7 @@
 #include "wayland/meta-wayland-popup.h"
 #include "wayland/meta-wayland-private.h"
 #include "wayland/meta-wayland-seat.h"
+#include "wayland/meta-wayland-shell-surface.h"
 #include "wayland/meta-wayland-surface.h"
 #include "wayland/meta-wayland-versions.h"
 #include "wayland/meta-window-wayland.h"
@@ -564,6 +565,8 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole  *surface_role,
 {
   MetaWaylandWlShellSurface *wl_shell_surface =
     META_WAYLAND_WL_SHELL_SURFACE (surface_role);
+  MetaWaylandShellSurface *shell_surface =
+    META_WAYLAND_SHELL_SURFACE (wl_shell_surface);
   MetaWaylandSurfaceRoleClass *surface_role_class;
   MetaWaylandSurface *surface =
     meta_wayland_surface_role_get_surface (surface_role);
@@ -596,7 +599,7 @@ wl_shell_surface_role_commit (MetaWaylandSurfaceRole  *surface_role,
   if (!pending->newly_attached)
     return;
 
-  meta_wayland_surface_calculate_window_geometry (surface, &geom, 0, 0);
+  meta_wayland_shell_surface_calculate_geometry (shell_surface, &geom);
   meta_window_wayland_move_resize (window,
                                    NULL,
                                    geom, pending->dx, pending->dy);
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
index 0fe5c2845..855d31342 100644
--- a/src/wayland/meta-wayland-xdg-shell.c
+++ b/src/wayland/meta-wayland-xdg-shell.c
@@ -32,6 +32,7 @@
 #include "wayland/meta-wayland-popup.h"
 #include "wayland/meta-wayland-private.h"
 #include "wayland/meta-wayland-seat.h"
+#include "wayland/meta-wayland-shell-surface.h"
 #include "wayland/meta-wayland-surface.h"
 #include "wayland/meta-wayland-versions.h"
 #include "wayland/meta-window-wayland.h"
@@ -1230,6 +1231,8 @@ meta_wayland_xdg_surface_commit (MetaWaylandSurfaceRole  *surface_role,
                                  MetaWaylandPendingState *pending)
 {
   MetaWaylandXdgSurface *xdg_surface = META_WAYLAND_XDG_SURFACE (surface_role);
+  MetaWaylandShellSurface *shell_surface =
+    META_WAYLAND_SHELL_SURFACE (xdg_surface);
   MetaWaylandXdgSurfacePrivate *priv =
     meta_wayland_xdg_surface_get_instance_private (xdg_surface);
   MetaWaylandSurface *surface =
@@ -1283,9 +1286,8 @@ meta_wayland_xdg_surface_commit (MetaWaylandSurfaceRole  *surface_role,
       /* If the surface has never set any geometry, calculate
        * a default one unioning the surface and all subsurfaces together. */
 
-      meta_wayland_surface_calculate_window_geometry (surface,
-                                                      &new_geometry,
-                                                      0, 0);
+      meta_wayland_shell_surface_calculate_geometry (shell_surface,
+                                                     &new_geometry);
       if (!meta_rectangle_equal (&new_geometry, &priv->geometry))
         {
           pending->has_new_geometry = TRUE;
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index 4d9aadbbb..939071e08 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -32,6 +32,7 @@
 #include "window-private.h"
 #include "boxes-private.h"
 #include "stack-tracker.h"
+#include "meta-wayland-actor-surface.h"
 #include "meta-wayland-private.h"
 #include "meta-wayland-surface.h"
 #include "meta-wayland-xdg-shell.h"
@@ -491,15 +492,13 @@ meta_window_wayland_main_monitor_changed (MetaWindow               *window,
                                         window,
                                         TRUE);
 
-  /* The surface actor needs to update the scale recursively for itself and all
-   * its subsurfaces */
   surface = window->surface;
   if (surface)
     {
-      MetaSurfaceActorWayland *actor =
-        META_SURFACE_ACTOR_WAYLAND (surface->surface_actor);
+      MetaWaylandActorSurface *actor_surface =
+        META_WAYLAND_ACTOR_SURFACE (surface->role);
 
-      meta_surface_actor_wayland_sync_state_recursive (actor);
+      meta_wayland_actor_surface_sync_actor_state (actor_surface);
     }
 
   wl_window->geometry_scale = geometry_scale;


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