[mutter/gbsneto/content-part2: 4/7] Add MetaWindowContent



commit 378119362589ac10cebe386466e7afe29d12a891
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Sun Dec 23 12:24:26 2018 -0200

    Add MetaWindowContent
    
    MetaWindowContent is a GObject class that implements ClutterContent.
    It draws the contents of the window, unshadowed in the case of server
    side decorated windows on X11, as a composition of the contents of
    the subsurfaces.
    
    WIP

 src/compositor/meta-window-actor.c           |  49 ++++-
 src/compositor/meta-window-content-private.h |  31 +++
 src/compositor/meta-window-content.c         | 305 +++++++++++++++++++++++++++
 src/meson.build                              |   2 +
 src/meta/meson.build                         |   1 +
 src/meta/meta-window-actor.h                 |   3 +
 src/meta/meta-window-content.h               |  39 ++++
 7 files changed, 429 insertions(+), 1 deletion(-)
---
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index d471f622a..dc888af05 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -33,6 +33,9 @@
 #include "compositor/meta-surface-actor.h"
 #include "compositor/meta-texture-rectangle.h"
 #include "compositor/meta-window-actor-private.h"
+#include "compositor/meta-window-actor-wayland.h"
+#include "compositor/meta-window-actor-x11.h"
+#include "compositor/meta-window-content-private.h"
 #include "compositor/region-utils.h"
 #include "meta/meta-enum-types.h"
 #include "meta/meta-shadow-factory.h"
@@ -58,6 +61,8 @@ typedef struct _MetaWindowActorPrivate
 
   MetaSurfaceActor *surface;
 
+  MetaWindowContent *content;
+
   /* MetaShadowFactory only caches shadows that are actually in use;
    * to avoid unnecessary recomputation we do two things: 1) we store
    * both a focused and unfocused shadow for the window. If the window
@@ -124,6 +129,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
 enum
 {
   PROP_META_WINDOW = 1,
+  PROP_CONTENT,
   PROP_SHADOW_MODE,
   PROP_SHADOW_CLASS
 };
@@ -255,11 +261,19 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
   g_object_class_install_property (object_class,
                                    PROP_SHADOW_CLASS,
                                    pspec);
+
+  g_object_class_override_property (object_class,
+                                    PROP_CONTENT,
+                                    "content");
 }
 
 static void
 meta_window_actor_init (MetaWindowActor *self)
 {
+  MetaWindowActorPrivate *priv =
+    meta_window_actor_get_instance_private (self);
+
+  priv->content = meta_window_content_new (self);
 }
 
 static void
@@ -267,7 +281,11 @@ window_appears_focused_notify (MetaWindow *mw,
                                GParamSpec *arg1,
                                gpointer    data)
 {
-  clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
+  MetaWindowActor *window_actor = META_WINDOW_ACTOR (data);
+  MetaWindowActorPrivate *priv =
+    meta_window_actor_get_instance_private (window_actor);
+
+  clutter_content_invalidate (CLUTTER_CONTENT (priv->content));
 }
 
 static void
@@ -396,6 +414,8 @@ set_surface (MetaWindowActor  *self,
       else
         meta_window_actor_sync_thawed_state (self);
     }
+
+  clutter_content_invalidate (CLUTTER_CONTENT (priv->content));
 }
 
 void
@@ -463,6 +483,7 @@ meta_window_actor_dispose (GObject *object)
 
   priv->disposed = TRUE;
 
+  g_clear_object (&priv->content);
   g_clear_pointer (&priv->shape_region, cairo_region_destroy);
   g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
 
@@ -492,6 +513,9 @@ meta_window_actor_set_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_CONTENT:
+      g_warning ("Overriding the content of MetaWindowActor is not allowed.");
+      break;
     case PROP_META_WINDOW:
       priv->window = g_value_dup_object (value);
       g_signal_connect_object (priv->window, "notify::appears-focused",
@@ -540,6 +564,9 @@ meta_window_actor_get_property (GObject      *object,
 
   switch (prop_id)
     {
+    case PROP_CONTENT:
+      g_value_set_object (value, priv->content);
+      break;
     case PROP_META_WINDOW:
       g_value_set_object (value, priv->window);
       break;
@@ -841,6 +868,25 @@ meta_window_actor_get_texture (MetaWindowActor *self)
     return NULL;
 }
 
+/**
+ * meta_window_actor_get_content:
+ * @window_actor: a #MetaWindowActor
+ *
+ * Gets the #ClutterContent that represents the visible contents of the
+ * window. This includes subsurfaces. It should be used as the content
+ * of a #ClutterActor, through clutter_actor_set_content().
+ *
+ * Return value: (transfer none): a #ClutterContent
+ */
+ClutterContent *
+meta_window_actor_get_content (MetaWindowActor *window_actor)
+{
+  MetaWindowActorPrivate *priv =
+    meta_window_actor_get_instance_private (window_actor);
+
+  return CLUTTER_CONTENT (priv->content);
+}
+
 /**
  * meta_window_actor_get_surface:
  * @self: a #MetaWindowActor
@@ -1722,6 +1768,7 @@ meta_window_actor_update_shape (MetaWindowActor *self)
   if (is_frozen (self))
     return;
 
+  clutter_content_invalidate_size (CLUTTER_CONTENT (priv->content));
   clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
 }
 
diff --git a/src/compositor/meta-window-content-private.h b/src/compositor/meta-window-content-private.h
new file mode 100644
index 000000000..ab34e4337
--- /dev/null
+++ b/src/compositor/meta-window-content-private.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2018 Endless, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Georges Basile Stavracas Neto <gbsneto gnome org>
+ */
+
+#ifndef META_WINDOW_CONTENT_PRIVATE_H
+#define META_WINDOW_CONTENT_PRIVATE_H
+
+#include "meta/meta-window-content.h"
+#include "meta/meta-window-actor.h"
+
+MetaWindowContent* meta_window_content_new (MetaWindowActor *window_actor);
+
+#endif /* META_WINDOW_CONTENT_PRIVATE_H */
diff --git a/src/compositor/meta-window-content.c b/src/compositor/meta-window-content.c
new file mode 100644
index 000000000..1b4b9d51a
--- /dev/null
+++ b/src/compositor/meta-window-content.c
@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2018 Endless, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Georges Basile Stavracas Neto <gbsneto gnome org>
+ */
+
+#include "compositor/meta-shaped-texture-private.h"
+#include "compositor/meta-surface-actor.h"
+#include "compositor/meta-window-actor-private.h"
+#include "compositor/meta-window-content-private.h"
+
+struct _MetaWindowContent
+{
+  GObject parent;
+
+  MetaWindowActor *window_actor;
+
+  unsigned int attached_actors;
+};
+
+static void clutter_content_iface_init (ClutterContentIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaWindowContent, meta_window_content, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT, clutter_content_iface_init))
+
+/**
+ * SECTION:meta-window-content
+ * @title: MetaWindowContent
+ * @short_description: Contents of a MetaWindowActor
+ *
+ * #MetaWindowContent represents the user-visible content of
+ * a #MetaWindowActor. It combines the contents of all the
+ * #MetaSurfaceActors that the window contains into a final
+ * texture.
+ *
+ * It is intended to be used as follows:
+ *
+ * |[
+ * ClutterActor *
+ * create_window_clone (MetaWindowActor *window_actor)
+ * {
+ *   ClutterContent *window_content;
+ *   ClutterActor *clone;
+ *
+ *   window_content = meta_window_actor_get_content (window_actor);
+ *
+ *   clone = clutter_actor_new ();
+ *   clutter_actor_set_content (clone, window_content);
+ *
+ *   return clone;
+ * }
+ * ]|
+ *
+ * It is also exposed as the #MetaWindowActor.content property
+ * that can be binded to other actors. Notice, however, that
+ * the value of #MetaWindowActor.content cannot be modified,
+ * only read.
+ */
+
+enum
+{
+  PROP_0,
+  PROP_WINDOW_ACTOR,
+  N_PROPS
+};
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+add_surface_paint_nodes (MetaSurfaceActor     *surface_actor,
+                         ClutterActor         *actor,
+                         ClutterPaintNode     *root_node,
+                         float                 dx,
+                         float                 dy,
+                         float                 scale_h,
+                         float                 scale_v)
+{
+  MetaShapedTexture *shaped_texture;
+  ClutterActorIter iter;
+  ClutterActor *child;
+  ClutterActorBox box;
+  CoglTexture *texture;
+  double actor_scale, surface_scale;
+  uint8_t opacity;
+
+  shaped_texture = meta_surface_actor_get_texture (surface_actor);
+  texture = meta_shaped_texture_get_texture (shaped_texture);
+
+  if (!texture)
+    return;
+
+  opacity = (guint) clutter_actor_get_paint_opacity (CLUTTER_ACTOR (surface_actor)) *
+            (guint) clutter_actor_get_paint_opacity (actor) /
+            255;
+
+  clutter_actor_get_content_box (CLUTTER_ACTOR (surface_actor),
+                                 &box);
+  box.x1 = (box.x1 + dx) * scale_h;
+  box.x2 = (box.x2 + dx) * scale_h;
+  box.y1 = (box.y1 + dy) * scale_v;
+  box.y2 = (box.y2 + dy) * scale_v;
+
+  clutter_actor_get_scale (actor, &actor_scale, NULL);
+  clutter_actor_get_scale (CLUTTER_ACTOR (surface_actor), &surface_scale, NULL);
+
+  _meta_shaped_texture_paint_node (shaped_texture,
+                                   root_node,
+                                   &box,
+                                   actor_scale * surface_scale,
+                                   opacity);
+
+  clutter_actor_iter_init (&iter, CLUTTER_ACTOR (surface_actor));
+  while (clutter_actor_iter_next (&iter, &child))
+    {
+      float subsurface_dx, subsurface_dy;
+
+      subsurface_dx = dx + clutter_actor_get_x (child);
+      subsurface_dy = dy +  clutter_actor_get_y (child);
+
+      add_surface_paint_nodes (META_SURFACE_ACTOR (child),
+                               actor, root_node,
+                               subsurface_dx, subsurface_dy,
+                               scale_h, scale_v);
+    }
+}
+
+static void
+meta_window_content_paint_content (ClutterContent   *content,
+                                   ClutterActor     *actor,
+                                   ClutterPaintNode *node)
+{
+  MetaWindowContent *window_content = META_WINDOW_CONTENT (content);
+  MetaSurfaceActor *surface_actor =
+    meta_window_actor_get_surface (window_content->window_actor);
+  float dst_width, dst_height;
+  float scale_h, scale_v;
+  float width, height;
+
+  g_assert (!META_IS_WINDOW_ACTOR (actor));
+  g_assert (!META_IS_SURFACE_ACTOR (actor));
+
+  if (!surface_actor)
+    return;
+
+  /* Horizontal and vertical scales */
+  clutter_actor_get_size (CLUTTER_ACTOR (surface_actor),
+                          &width, &height);
+  clutter_actor_get_size (actor, &dst_width, &dst_height);
+  scale_h = dst_width / width;
+  scale_v = dst_height / height;
+
+  add_surface_paint_nodes (surface_actor, actor,
+                           node, 0.0, 0.0,
+                           scale_h, scale_v);
+}
+
+static gboolean
+meta_window_content_get_preferred_size (ClutterContent *content,
+                                        float          *width,
+                                        float          *height)
+{
+  MetaWindowContent *window_content = META_WINDOW_CONTENT (content);
+  MetaSurfaceActor *surface_actor =
+    meta_window_actor_get_surface (window_content->window_actor);
+
+  if (!surface_actor)
+    return FALSE;
+
+  clutter_actor_get_size (CLUTTER_ACTOR (surface_actor),
+                          width, height);
+  return TRUE;
+}
+
+static void
+meta_window_content_attached (ClutterContent *content,
+                            ClutterActor   *actor)
+{
+  MetaWindowContent *window_content = META_WINDOW_CONTENT (content);
+
+  window_content->attached_actors++;
+}
+
+static void
+meta_window_content_detached (ClutterContent *content,
+                            ClutterActor   *actor)
+{
+  MetaWindowContent *window_content = META_WINDOW_CONTENT (content);
+
+  window_content->attached_actors--;
+}
+
+static void
+clutter_content_iface_init (ClutterContentIface *iface)
+{
+  iface->paint_content = meta_window_content_paint_content;
+  iface->get_preferred_size = meta_window_content_get_preferred_size;
+  iface->attached = meta_window_content_attached;
+  iface->detached = meta_window_content_detached;
+}
+
+static void
+meta_window_content_get_property (GObject    *object,
+                                  guint       prop_id,
+                                  GValue     *value,
+                                  GParamSpec *pspec)
+{
+  MetaWindowContent *window_content = META_WINDOW_CONTENT (object);
+
+  switch (prop_id)
+    {
+    case PROP_WINDOW_ACTOR:
+      g_value_set_object (value, window_content->window_actor);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+meta_window_content_set_property (GObject      *object,
+                                  guint         prop_id,
+                                  const GValue *value,
+                                  GParamSpec   *pspec)
+{
+  MetaWindowContent *window_content = META_WINDOW_CONTENT (object);
+
+  switch (prop_id)
+    {
+    case PROP_WINDOW_ACTOR:
+      g_assert (window_content->window_actor == NULL);
+
+      window_content->window_actor = g_value_get_object (value);
+      g_assert (window_content->window_actor != NULL);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+meta_window_content_class_init (MetaWindowContentClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->get_property = meta_window_content_get_property;
+  object_class->set_property = meta_window_content_set_property;
+
+  properties[PROP_WINDOW_ACTOR] =
+    g_param_spec_object ("window-actor",
+                         "Window actor",
+                         "Window actor",
+                         META_TYPE_WINDOW_ACTOR,
+                         G_PARAM_READWRITE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+meta_window_content_init (MetaWindowContent *self)
+{
+}
+
+MetaWindowContent *
+meta_window_content_new (MetaWindowActor *window_actor)
+{
+  return g_object_new (META_TYPE_WINDOW_CONTENT,
+                       "window-actor", window_actor,
+                       NULL);
+}
+
+/**
+ * meta_window_content_get_window_actor:
+ * @window_content: a #MetaWindowContent
+ *
+ * Retrieves the window actor that @window_content represents.
+ *
+ * Returns: (transfer none): a #MetaWindowActor
+ */
+MetaWindowActor *
+meta_window_content_get_window_actor (MetaWindowContent *window_content)
+{
+  g_return_val_if_fail (META_IS_WINDOW_CONTENT (window_content), NULL);
+
+  return window_content->window_actor;
+}
diff --git a/src/meson.build b/src/meson.build
index a3e579d9b..a94d2de2e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -300,6 +300,8 @@ mutter_sources = [
   'compositor/meta-window-actor-wayland.h',
   'compositor/meta-window-actor-x11.c',
   'compositor/meta-window-actor-x11.h',
+  'compositor/meta-window-content.c',
+  'compositor/meta-window-content-private.h',
   'compositor/meta-window-group.c',
   'compositor/meta-window-group-private.h',
   'compositor/meta-window-shape.c',
diff --git a/src/meta/meson.build b/src/meta/meson.build
index 53c4723a2..853182606 100644
--- a/src/meta/meson.build
+++ b/src/meta/meson.build
@@ -29,6 +29,7 @@ mutter_public_headers = [
   'meta-stage.h',
   'meta-startup-notification.h',
   'meta-window-actor.h',
+  'meta-window-content.h',
   'meta-window-group.h',
   'meta-window-shape.h',
   'meta-workspace-manager.h',
diff --git a/src/meta/meta-window-actor.h b/src/meta/meta-window-actor.h
index 55e2e7b27..ce80d8692 100644
--- a/src/meta/meta-window-actor.h
+++ b/src/meta/meta-window-actor.h
@@ -52,6 +52,9 @@ void               meta_window_actor_sync_visibility      (MetaWindowActor *self
 META_EXPORT
 gboolean       meta_window_actor_is_destroyed (MetaWindowActor *self);
 
+META_EXPORT
+ClutterContent *   meta_window_actor_get_content          (MetaWindowActor *self);
+
 typedef enum {
   META_SHADOW_MODE_AUTO,
   META_SHADOW_MODE_FORCED_OFF,
diff --git a/src/meta/meta-window-content.h b/src/meta/meta-window-content.h
new file mode 100644
index 000000000..1acb6d87d
--- /dev/null
+++ b/src/meta/meta-window-content.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Endless, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Georges Basile Stavracas Neto <gbsneto gnome org>
+ */
+
+#ifndef META_WINDOW_CONTENT_H
+#define META_WINDOW_CONTENT_H
+
+#include "meta/meta-window-actor.h"
+
+#define META_TYPE_WINDOW_CONTENT (meta_window_content_get_type())
+
+META_EXPORT
+G_DECLARE_FINAL_TYPE (MetaWindowContent,
+                      meta_window_content,
+                      META, WINDOW_CONTENT,
+                      GObject)
+
+META_EXPORT
+MetaWindowActor * meta_window_content_get_window_actor (MetaWindowContent *window_content);
+
+#endif /* META_WINDOW_CONTENT_H */


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