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



commit 86cf89e787521986bf8bb99e96cbce59882b1a1e
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.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/861

 src/compositor/meta-shaped-texture-private.h |   5 +
 src/compositor/meta-shaped-texture.c         |  14 ++
 src/compositor/meta-window-actor-x11.c       |   3 +
 src/compositor/meta-window-actor.c           |  44 ++++-
 src/compositor/meta-window-content-private.h |  31 +++
 src/compositor/meta-window-content.c         | 285 +++++++++++++++++++++++++++
 src/meson.build                              |   2 +
 src/meta/meson.build                         |   1 +
 src/meta/meta-window-actor.h                 |   3 +
 src/meta/meta-window-content.h               |  39 ++++
 10 files changed, 426 insertions(+), 1 deletion(-)
---
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
index e96c6f8a8..87527e884 100644
--- a/src/compositor/meta-shaped-texture-private.h
+++ b/src/compositor/meta-shaped-texture-private.h
@@ -63,4 +63,9 @@ gboolean meta_shaped_texture_update_area (MetaShapedTexture     *stex,
                                           int                    height,
                                           cairo_rectangle_int_t *clip);
 
+void meta_shaped_texture_paint_node (MetaShapedTexture *stex,
+                                     ClutterPaintNode  *root_node,
+                                     ClutterActorBox   *box,
+                                     guchar             opacity);
+
 #endif
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 401aaadf7..29b70cfb0 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -1431,3 +1431,17 @@ meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex)
 
   return stex->buffer_scale;
 }
+
+void
+meta_shaped_texture_paint_node (MetaShapedTexture *stex,
+                                ClutterPaintNode  *root_node,
+                                ClutterActorBox   *box,
+                                guchar             opacity)
+{
+  g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
+
+  if (!stex->texture)
+    return;
+
+  do_paint_content (stex, root_node, stex->texture, box, opacity);
+}
diff --git a/src/compositor/meta-window-actor-x11.c b/src/compositor/meta-window-actor-x11.c
index 8bf65351f..1c4a22554 100644
--- a/src/compositor/meta-window-actor-x11.c
+++ b/src/compositor/meta-window-actor-x11.c
@@ -1095,12 +1095,15 @@ meta_window_actor_x11_update_shape (MetaWindowActorX11 *actor_x11)
 {
   MetaSurfaceActor *surface =
     meta_window_actor_get_surface (META_WINDOW_ACTOR (actor_x11));
+  ClutterContent *content =
+    meta_window_actor_get_content (META_WINDOW_ACTOR (actor_x11));
 
   actor_x11->needs_reshape = TRUE;
 
   if (meta_window_actor_is_frozen (META_WINDOW_ACTOR (actor_x11)))
     return;
 
+  clutter_content_invalidate_size (content);
   clutter_actor_queue_redraw (CLUTTER_ACTOR (surface));
 }
 
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 6e86424dc..6f5302376 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -32,6 +32,7 @@
 #include "compositor/meta-surface-actor-x11.h"
 #include "compositor/meta-surface-actor.h"
 #include "compositor/meta-window-actor-private.h"
+#include "compositor/meta-window-content-private.h"
 #include "core/boxes-private.h"
 #include "core/window-private.h"
 #include "meta/window.h"
@@ -55,6 +56,8 @@ typedef struct _MetaWindowActorPrivate
 
   MetaSurfaceActor *surface;
 
+  MetaWindowContent *content;
+
   int geometry_scale;
 
   /*
@@ -94,6 +97,7 @@ static guint signals[LAST_SIGNAL] = { 0 };
 enum
 {
   PROP_META_WINDOW = 1,
+  PROP_CONTENT,
 };
 
 static void meta_window_actor_dispose    (GObject *object);
@@ -207,6 +211,10 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
   g_object_class_install_property (object_class,
                                    PROP_META_WINDOW,
                                    pspec);
+
+  g_object_class_override_property (object_class,
+                                    PROP_CONTENT,
+                                    "content");
 }
 
 static void
@@ -216,6 +224,7 @@ meta_window_actor_init (MetaWindowActor *self)
     meta_window_actor_get_instance_private (self);
 
   priv->geometry_scale = 1;
+  priv->content = meta_window_content_new (self);
 }
 
 static void
@@ -223,7 +232,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));
 }
 
 gboolean
@@ -315,6 +328,8 @@ meta_window_actor_real_assign_surface_actor (MetaWindowActor  *self,
     meta_surface_actor_set_frozen (priv->surface, TRUE);
   else
     meta_window_actor_sync_thawed_state (self);
+
+  clutter_content_invalidate (CLUTTER_CONTENT (priv->content));
 }
 
 void
@@ -389,6 +404,8 @@ meta_window_actor_dispose (GObject *object)
 
   priv->disposed = TRUE;
 
+  g_clear_object (&priv->content);
+
   meta_compositor_remove_window_actor (compositor, self);
 
   g_clear_object (&priv->window);
@@ -415,6 +432,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",
@@ -438,6 +458,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;
@@ -485,6 +508,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
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..cd41b0e52
--- /dev/null
+++ b/src/compositor/meta-window-content.c
@@ -0,0 +1,285 @@
+/*
+ * 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 (ClutterContentInterface *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             scale_h,
+                         float             scale_v)
+{
+  MetaShapedTexture *stex;
+  ClutterActorBox box;
+  CoglTexture *texture;
+  uint8_t opacity;
+
+  stex = meta_surface_actor_get_texture (surface_actor);
+
+  if (!stex)
+    return;
+
+  texture = meta_shaped_texture_get_texture (stex);
+
+  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 * scale_h;
+  box.x2 = box.x2 * scale_h;
+  box.y1 = box.y1 * scale_v;
+  box.y2 = box.y2 * scale_v;
+
+  meta_shaped_texture_paint_node (stex,
+                                  root_node,
+                                  &box,
+                                  opacity);
+}
+
+static void
+meta_window_content_paint_content (ClutterContent   *content,
+                                   ClutterActor     *actor,
+                                   ClutterPaintNode *node)
+{
+  MetaWindowContent *window_content = META_WINDOW_CONTENT (content);
+  ClutterActor *window_actor = CLUTTER_ACTOR (window_content->window_actor);
+  ClutterActor *child;
+  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));
+
+  /* Horizontal and vertical scales */
+  clutter_actor_get_size (window_actor, &width, &height);
+  clutter_actor_get_size (actor, &dst_width, &dst_height);
+  scale_h = dst_width / width;
+  scale_v = dst_height / height;
+
+  for (child = clutter_actor_get_first_child (window_actor);
+       child != NULL;
+       child = clutter_actor_get_next_sibling (child))
+    {
+      if (!META_IS_SURFACE_ACTOR (child))
+        continue;
+
+      add_surface_paint_nodes (META_SURFACE_ACTOR (child),
+                               actor, node,
+                               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);
+
+  clutter_actor_get_size (CLUTTER_ACTOR (window_content->window_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 (ClutterContentInterface *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 db63ed317..a2e07acc4 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -319,6 +319,8 @@ mutter_sources = [
   'compositor/meta-window-actor-private.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 14caec58d..01c9b447d 100644
--- a/src/meta/meson.build
+++ b/src/meta/meson.build
@@ -32,6 +32,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 7d3b96e59..96cd1f11f 100644
--- a/src/meta/meta-window-actor.h
+++ b/src/meta/meta-window-actor.h
@@ -51,6 +51,9 @@ META_EXPORT
 cairo_surface_t * meta_window_actor_get_image (MetaWindowActor       *self,
                                                cairo_rectangle_int_t *clip);
 
+META_EXPORT
+ClutterContent *meta_window_actor_get_content (MetaWindowActor *self);
+
 typedef enum
 {
   META_SHADOW_MODE_AUTO,
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]