From 22f0d3076ead0c20ff5fc0e5f861d7164142e168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Fri, 19 Aug 2016 10:47:57 +0800 Subject: [PATCH] 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 d7c80881d..089828e05 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 b998f2b9b..f72645c27 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 1d25d6f88..532e19ba9 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__ */