Blame SOURCES/0006-window-actor-Implement-MetaScreenCastWindow-interfac.patch

776610
From 5f2c181eda1b721b807e41130232714bacb823a9 Mon Sep 17 00:00:00 2001
776610
From: Olivier Fourdan <ofourdan@redhat.com>
776610
Date: Tue, 4 Dec 2018 16:29:47 +0100
776610
Subject: [PATCH 06/12] window-actor: Implement MetaScreenCastWindow interface
776610
776610
Implements the `MetaScreenCastWindow` interface for screen-cast
776610
`RecordWindow` mode.
776610
776610
`meta_window_actor_capture_into()` implementation is still pretty crude
776610
and doesn't take into account subsurfaces and O-R windows so menus,
776610
popups and other tooltips won't show in the capture.
776610
776610
This is left as a future improvement for now.
776610
776610
https://gitlab.gnome.org/GNOME/mutter/merge_requests/306
776610
(cherry picked from commit 931934511c8e885d5f607ba90187286a0a7ec3a3)
776610
---
776610
 src/compositor/meta-window-actor.c | 132 ++++++++++++++++++++++++++++-
776610
 1 file changed, 131 insertions(+), 1 deletion(-)
776610
776610
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
776610
index 5078624..396fef1 100644
776610
--- a/src/compositor/meta-window-actor.c
776610
+++ b/src/compositor/meta-window-actor.c
776610
@@ -24,6 +24,7 @@
776610
 #include <meta/meta-shadow-factory.h>
776610
 
776610
 #include "backends/meta-backend-private.h"
776610
+#include "backends/meta-screen-cast-window.h"
776610
 #include "clutter/clutter-mutter.h"
776610
 #include "compositor-private.h"
776610
 #include "meta-shaped-texture-private.h"
776610
@@ -188,8 +189,11 @@ static void do_send_frame_timings (MetaWindowActor  *self,
776610
 
776610
 static void cullable_iface_init (MetaCullableInterface *iface);
776610
 
776610
+static void screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface);
776610
+
776610
 G_DEFINE_TYPE_WITH_CODE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR,
776610
-                         G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
776610
+                         G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)
776610
+                         G_IMPLEMENT_INTERFACE (META_TYPE_SCREEN_CAST_WINDOW, screen_cast_window_iface_init));
776610
 
776610
 static void
776610
 frame_data_free (FrameData *frame)
776610
@@ -2181,3 +2185,129 @@ meta_window_actor_from_window (MetaWindow *window)
776610
 {
776610
   return META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
776610
 }
776610
+
776610
+static void
776610
+meta_window_actor_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window,
776610
+                                     MetaRectangle        *bounds)
776610
+{
776610
+  MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
776610
+  ClutterActor *clutter_actor;
776610
+
776610
+  clutter_actor = CLUTTER_ACTOR (meta_window_actor_get_texture (window_actor));
776610
+  bounds->x = 0;
776610
+  bounds->y = 0;
776610
+  bounds->width = (int) clutter_actor_get_width (clutter_actor);
776610
+  bounds->height = (int) clutter_actor_get_height (clutter_actor);
776610
+}
776610
+
776610
+static void
776610
+meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
776610
+                                    MetaRectangle        *bounds)
776610
+{
776610
+  MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
776610
+  MetaWindow *window;
776610
+  MetaShapedTexture *stex;
776610
+  MetaRectangle buffer_rect;
776610
+  MetaRectangle frame_rect;
776610
+  double scale_x, scale_y;
776610
+
776610
+  stex = meta_surface_actor_get_texture (window_actor->priv->surface);
776610
+  clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale_x, &scale_y);
776610
+
776610
+  window = window_actor->priv->window;
776610
+  meta_window_get_buffer_rect (window, &buffer_rect);
776610
+  meta_window_get_frame_rect (window, &frame_rect);
776610
+
776610
+  bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale_x);
776610
+  bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale_y);
776610
+  bounds->width = (int) ceil (frame_rect.width / scale_x);
776610
+  bounds->height = (int) ceil (frame_rect.height / scale_y);
776610
+}
776610
+
776610
+static void
776610
+meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast_window,
776610
+                                               double                x,
776610
+                                               double                y,
776610
+                                               double               *x_out,
776610
+                                               double               *y_out)
776610
+
776610
+{
776610
+  MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
776610
+  MetaShapedTexture *stex;
776610
+  MetaRectangle bounds;
776610
+  ClutterVertex v1 = { 0.f, }, v2 = { 0.f, };
776610
+
776610
+  meta_window_actor_get_frame_bounds (screen_cast_window, &bounds);
776610
+
776610
+  v1.x = CLAMP ((float) x,
776610
+                bounds.x,
776610
+                bounds.x + bounds.width);
776610
+  v1.y = CLAMP ((float) y,
776610
+                bounds.y,
776610
+                bounds.y + bounds.height);
776610
+
776610
+  stex = meta_surface_actor_get_texture (window_actor->priv->surface);
776610
+  clutter_actor_apply_transform_to_point (CLUTTER_ACTOR (stex), &v1, &v2;;
776610
+
776610
+  *x_out = (double) v2.x;
776610
+  *y_out = (double) v2.y;
776610
+}
776610
+
776610
+static void
776610
+meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window,
776610
+                                MetaRectangle        *bounds,
776610
+                                uint8_t              *data)
776610
+{
776610
+  MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
776610
+  cairo_surface_t *image;
776610
+  MetaRectangle clip_rect;
776610
+  uint8_t *cr_data;
776610
+  int cr_stride;
776610
+  int bpp = 4;
776610
+
776610
+  if (meta_window_actor_is_destroyed (window_actor))
776610
+    return;
776610
+
776610
+  clip_rect = *bounds;
776610
+  image = meta_surface_actor_get_image (window_actor->priv->surface, &clip_rect);
776610
+  cr_data = cairo_image_surface_get_data (image);
776610
+  cr_stride = cairo_image_surface_get_stride (image);
776610
+
776610
+  if (clip_rect.width < bounds->width || clip_rect.height < bounds->height)
776610
+    {
776610
+      uint8_t *src, *dst;
776610
+      src = cr_data;
776610
+      dst = data;
776610
+
776610
+      for (int i = 0; i < clip_rect.height; i++)
776610
+        {
776610
+          memcpy (dst, src, cr_stride);
776610
+          if (clip_rect.width < bounds->width)
776610
+            memset (dst + cr_stride, 0, (bounds->width * bpp) - cr_stride);
776610
+
776610
+          src += cr_stride;
776610
+          dst += bounds->width * bpp;
776610
+        }
776610
+
776610
+      for (int i = clip_rect.height; i < bounds->height; i++)
776610
+        {
776610
+          memset (dst, 0, bounds->width * bpp);
776610
+          dst += bounds->width * bpp;
776610
+        }
776610
+    }
776610
+  else
776610
+    {
776610
+      memcpy (data, cr_data, clip_rect.height * cr_stride);
776610
+    }
776610
+
776610
+  cairo_surface_destroy (image);
776610
+}
776610
+
776610
+static void
776610
+screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface)
776610
+{
776610
+  iface->get_buffer_bounds = meta_window_actor_get_buffer_bounds;
776610
+  iface->get_frame_bounds = meta_window_actor_get_frame_bounds;
776610
+  iface->transform_relative_position = meta_window_actor_transform_relative_position;
776610
+  iface->capture_into = meta_window_actor_capture_into;
776610
+}
776610
-- 
776610
2.19.2
776610