[gnome-shell] screenshot: Composite multiple captures into one image



commit 22f0d3076ead0c20ff5fc0e5f861d7164142e168
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Aug 19 10:47:57 2016 +0800

    screenshot: Composite multiple captures into one image
    
    When clutter gives us multiple captures (multiple cairo_surface_t's),
    composite them into one large image and use that as final screenshot
    result. This makes screenshooting work when mutter uses multiple views.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=770128

 src/shell-screenshot.c |   16 +++++++++-------
 src/shell-util.c       |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 src/shell-util.h       |    7 +++++++
 3 files changed, 62 insertions(+), 7 deletions(-)
---
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c
index d7c8088..089828e 100644
--- a/src/shell-screenshot.c
+++ b/src/shell-screenshot.c
@@ -10,6 +10,7 @@
 
 #include "shell-global.h"
 #include "shell-screenshot.h"
+#include "shell-util.h"
 
 #define A11Y_APPS_SCHEMA "org.gnome.desktop.a11y.applications"
 #define MAGNIFIER_ACTIVE_KEY "screen-magnifier-enabled"
@@ -233,14 +234,15 @@ do_grab_screenshot (ShellScreenshot *screenshot,
 
   if (n_captures == 0)
     return;
+  else if (n_captures == 1)
+    priv->image = cairo_surface_reference (captures[0].image);
+  else
+    priv->image = shell_util_composite_capture_images (captures,
+                                                       n_captures,
+                                                       x, y,
+                                                       width, height);
 
-  /*
-   * TODO: Deal with each capture region separately, instead of dropping
-   * anything except the first one.
-   */
-  priv->image = captures[0].image;
-
-  for (i = 1; i < n_captures; i++)
+  for (i = 0; i < n_captures; i++)
     cairo_surface_destroy (captures[i].image);
 
   g_free (captures);
diff --git a/src/shell-util.c b/src/shell-util.c
index b998f2b..f72645c 100644
--- a/src/shell-util.c
+++ b/src/shell-util.c
@@ -446,3 +446,49 @@ shell_util_get_content_for_window_actor (MetaWindowActor *window_actor,
 
   return content;
 }
+
+cairo_surface_t *
+shell_util_composite_capture_images (ClutterCapture  *captures,
+                                     int              n_captures,
+                                     int              x,
+                                     int              y,
+                                     int              width,
+                                     int              height)
+{
+  int i;
+  cairo_format_t format;
+  cairo_surface_t *image;
+  cairo_t *cr;
+
+  format = cairo_image_surface_get_format (captures[0].image);
+  image = cairo_image_surface_create (format, width, height);
+
+  cr = cairo_create (image);
+
+  for (i = 0; i < n_captures; i++)
+    {
+      ClutterCapture *capture = &captures[i];
+      double capture_scale = 1.0;
+
+      /*
+       * Ignore capture regions with scale other than 1 for now; mutter can't
+       * produce them yet, so there is no way to test them.
+       */
+      cairo_surface_get_device_scale (capture->image, &capture_scale, NULL);
+      if ((int) capture_scale != 1)
+        continue;
+
+      cairo_save (cr);
+
+      cairo_translate (cr,
+                       capture->rect.x - x,
+                       capture->rect.y - y);
+      cairo_set_source_surface (cr, capture->image, 0, 0);
+      cairo_paint (cr);
+
+      cairo_restore (cr);
+    }
+  cairo_destroy (cr);
+
+  return image;
+}
diff --git a/src/shell-util.h b/src/shell-util.h
index 1d25d6f..532e19b 100644
--- a/src/shell-util.h
+++ b/src/shell-util.h
@@ -51,6 +51,13 @@ gboolean shell_util_need_background_refresh (void);
 ClutterContent * shell_util_get_content_for_window_actor (MetaWindowActor *window_actor,
                                                           MetaRectangle   *window_rect);
 
+cairo_surface_t * shell_util_composite_capture_images (ClutterCapture  *captures,
+                                                       int              n_captures,
+                                                       int              x,
+                                                       int              y,
+                                                       int              width,
+                                                       int              height);
+
 G_END_DECLS
 
 #endif /* __SHELL_UTIL_H__ */


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