[gnome-shell] shell-screenshot: Change to use clutter_stage_paint_to*() API
- From: Georges Basile Stavracas Neto <gbsneto src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] shell-screenshot: Change to use clutter_stage_paint_to*() API
- Date: Thu, 6 Aug 2020 16:36:06 +0000 (UTC)
commit 757e4b6731f9b430dce13aedd28efdaef55456c9
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Thu Jul 30 09:51:06 2020 +0200
shell-screenshot: Change to use clutter_stage_paint_to*() API
This eliminates the need to wait for redraws, drawing cursors, and
stiching together cairo images in case the screenshot covers multiple
monitors.
All of that is now handled by mutter itself.
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1383
src/shell-screenshot.c | 296 +++++++++++++------------------------------------
1 file changed, 74 insertions(+), 222 deletions(-)
---
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c
index 36ca2fb24b..3a1c92ccec 100644
--- a/src/shell-screenshot.c
+++ b/src/shell-screenshot.c
@@ -12,6 +12,12 @@
#include "shell-screenshot.h"
#include "shell-util.h"
+typedef enum _ShellScreenshotFlag
+{
+ SHELL_SCREENSHOT_FLAG_NONE,
+ SHELL_SCREENSHOT_FLAG_INCLUDE_CURSOR,
+} ShellScreenshotFlag;
+
typedef struct _ShellScreenshotPrivate ShellScreenshotPrivate;
struct _ShellScreenshot
@@ -32,7 +38,6 @@ struct _ShellScreenshotPrivate
cairo_surface_t *image;
cairo_rectangle_int_t screenshot_area;
- gboolean include_cursor;
gboolean include_frame;
};
@@ -45,10 +50,6 @@ typedef enum
G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT);
-static void
-grab_screenshot (ClutterActor *stage,
- GTask *result);
-
static void
shell_screenshot_class_init (ShellScreenshotClass *screenshot_class)
{
@@ -77,8 +78,6 @@ on_screenshot_written (GObject *source,
g_clear_pointer (&priv->image, cairo_surface_destroy);
g_clear_object (&priv->stream);
g_clear_pointer (&priv->datetime, g_date_time_unref);
-
- meta_enable_unredirect_for_display (shell_global_get_display (priv->global));
}
static void
@@ -121,63 +120,49 @@ write_screenshot_thread (GTask *result,
}
static void
-do_grab_screenshot (ShellScreenshot *screenshot,
- ClutterStage *stage,
- int x,
- int y,
- int width,
- int height)
+do_grab_screenshot (ShellScreenshot *screenshot,
+ int x,
+ int y,
+ int width,
+ int height,
+ ShellScreenshotFlag flags)
{
ShellScreenshotPrivate *priv = screenshot->priv;
+ ClutterStage *stage = shell_global_get_stage (priv->global);
cairo_rectangle_int_t screenshot_rect = { x, y, width, height };
- ClutterCapture *captures;
- int n_captures;
- int i;
-
- if (!clutter_stage_capture (stage, FALSE,
- &screenshot_rect,
- &captures,
- &n_captures))
- return;
-
- if (n_captures == 1)
- priv->image = cairo_surface_reference (captures[0].image);
+ int image_width;
+ int image_height;
+ float scale;
+ cairo_surface_t *image;
+ ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_NONE;
+ g_autoptr (GError) error = NULL;
+
+ clutter_stage_get_capture_final_size (stage, &screenshot_rect,
+ &image_width,
+ &image_height,
+ &scale);
+ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ image_width, image_height);
+
+ if (flags & SHELL_SCREENSHOT_FLAG_INCLUDE_CURSOR)
+ paint_flags |= CLUTTER_PAINT_FLAG_FORCE_CURSORS;
else
+ paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS;
+ if (!clutter_stage_paint_to_buffer (stage, &screenshot_rect, scale,
+ cairo_image_surface_get_data (image),
+ cairo_image_surface_get_stride (image),
+ CLUTTER_CAIRO_FORMAT_ARGB32,
+ paint_flags,
+ &error))
{
- float target_scale;
-
- clutter_stage_get_capture_final_size (stage, &screenshot_rect,
- &width, &height, &target_scale);
- priv->image = shell_util_composite_capture_images (captures,
- n_captures,
- x, y,
- width, height,
- target_scale);
+ cairo_surface_destroy (image);
+ g_warning ("Failed to take screenshot: %s", error->message);
+ return;
}
- priv->datetime = g_date_time_new_now_local ();
-
- for (i = 0; i < n_captures; i++)
- cairo_surface_destroy (captures[i].image);
+ priv->image = image;
- g_free (captures);
-}
-
-static gboolean
-should_draw_cursor_image (ShellScreenshotMode mode)
-{
- if (mode == SHELL_SCREENSHOT_WINDOW || !meta_is_wayland_compositor ())
- {
- StSettings *settings = st_settings_get ();
- gboolean magnifier_active = FALSE;
-
- g_object_get (settings, "magnifier-active", &magnifier_active, NULL);
-
- if (!magnifier_active)
- return TRUE;
- }
-
- return FALSE;
+ priv->datetime = g_date_time_new_now_local ();
}
static void
@@ -256,116 +241,37 @@ draw_cursor_image (cairo_surface_t *surface,
}
static void
-on_paint (ClutterActor *actor,
- ClutterPaintContext *paint_context,
- GTask *result)
-{
- grab_screenshot (actor, result);
-}
-
-static void
-on_actors_painted (ClutterActor *actor,
- GTask *result)
-{
- grab_screenshot (actor, result);
-}
-
-static void
-grab_screenshot (ClutterActor *stage,
- GTask *result)
+grab_screenshot (ShellScreenshot *screenshot,
+ ShellScreenshotFlag flags,
+ GTask *result)
{
+ ShellScreenshotPrivate *priv = screenshot->priv;
MetaDisplay *display;
int width, height;
- ShellScreenshot *screenshot = g_task_get_source_object (result);
- ShellScreenshotPrivate *priv = screenshot->priv;
GTask *task;
display = shell_global_get_display (priv->global);
meta_display_get_size (display, &width, &height);
- do_grab_screenshot (screenshot, CLUTTER_STAGE (stage), 0, 0, width, height);
-
- if (meta_display_get_n_monitors (display) > 1)
- {
- cairo_region_t *screen_region = cairo_region_create ();
- cairo_region_t *stage_region;
- MetaRectangle monitor_rect;
- cairo_rectangle_int_t stage_rect;
- int i;
- cairo_t *cr;
-
- for (i = meta_display_get_n_monitors (display) - 1; i >= 0; i--)
- {
- meta_display_get_monitor_geometry (display, i, &monitor_rect);
- cairo_region_union_rectangle (screen_region,
- (const cairo_rectangle_int_t *) &monitor_rect);
- }
-
- stage_rect.x = 0;
- stage_rect.y = 0;
- stage_rect.width = width;
- stage_rect.height = height;
-
- stage_region = cairo_region_create_rectangle ((const cairo_rectangle_int_t *) &stage_rect);
- cairo_region_xor (stage_region, screen_region);
- cairo_region_destroy (screen_region);
-
- cr = cairo_create (priv->image);
-
- for (i = 0; i < cairo_region_num_rectangles (stage_region); i++)
- {
- cairo_rectangle_int_t rect;
- cairo_region_get_rectangle (stage_region, i, &rect);
- cairo_rectangle (cr, (double) rect.x, (double) rect.y, (double) rect.width, (double) rect.height);
- cairo_fill (cr);
- }
-
- cairo_destroy (cr);
- cairo_region_destroy (stage_region);
- }
+ do_grab_screenshot (screenshot,
+ 0, 0, width, height,
+ flags);
priv->screenshot_area.x = 0;
priv->screenshot_area.y = 0;
priv->screenshot_area.width = width;
priv->screenshot_area.height = height;
- if (priv->include_cursor)
- draw_cursor_image (priv->image, priv->screenshot_area);
-
- g_signal_handlers_disconnect_by_func (stage, on_paint, result);
- g_signal_handlers_disconnect_by_func (stage, on_actors_painted, result);
-
task = g_task_new (screenshot, NULL, on_screenshot_written, result);
g_task_run_in_thread (task, write_screenshot_thread);
g_object_unref (task);
}
static void
-grab_area_screenshot (ClutterActor *stage,
- GTask *result)
+grab_window_screenshot (ShellScreenshot *screenshot,
+ ShellScreenshotFlag flags,
+ GTask *result)
{
- ShellScreenshot *screenshot = g_task_get_source_object (result);
- ShellScreenshotPrivate *priv = screenshot->priv;
- GTask *task;
-
- do_grab_screenshot (screenshot,
- CLUTTER_STAGE (stage),
- priv->screenshot_area.x,
- priv->screenshot_area.y,
- priv->screenshot_area.width,
- priv->screenshot_area.height);
-
- g_signal_handlers_disconnect_by_func (stage, grab_area_screenshot, result);
- task = g_task_new (screenshot, NULL, on_screenshot_written, result);
- g_task_run_in_thread (task, write_screenshot_thread);
- g_object_unref (task);
-}
-
-static void
-grab_window_screenshot (ClutterActor *stage,
- GTask *result)
-{
- ShellScreenshot *screenshot = g_task_get_source_object (result);
ShellScreenshotPrivate *priv = screenshot->priv;
GTask *task;
MetaDisplay *display = shell_global_get_display (priv->global);
@@ -388,7 +294,7 @@ grab_window_screenshot (ClutterActor *stage,
NULL);
priv->datetime = g_date_time_new_now_local ();
- if (priv->include_cursor)
+ if (flags & SHELL_SCREENSHOT_FLAG_INCLUDE_CURSOR)
{
if (meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_WAYLAND)
{
@@ -401,33 +307,11 @@ grab_window_screenshot (ClutterActor *stage,
draw_cursor_image (priv->image, priv->screenshot_area);
}
- g_signal_handlers_disconnect_by_func (stage, grab_window_screenshot, result);
task = g_task_new (screenshot, NULL, on_screenshot_written, result);
g_task_run_in_thread (task, write_screenshot_thread);
g_object_unref (task);
}
-static void
-grab_pixel (ClutterActor *stage,
- GTask *result)
-{
- ShellScreenshot *screenshot = g_task_get_source_object (result);
- ShellScreenshotPrivate *priv = screenshot->priv;
-
- do_grab_screenshot (screenshot,
- CLUTTER_STAGE (stage),
- priv->screenshot_area.x,
- priv->screenshot_area.y,
- 1,
- 1);
-
- meta_enable_unredirect_for_display (shell_global_get_display (priv->global));
-
- g_signal_handlers_disconnect_by_func (stage, grab_pixel, result);
- g_task_return_boolean (result, TRUE);
- g_object_unref (result);
-}
-
static gboolean
finish_screenshot (ShellScreenshot *screenshot,
GAsyncResult *result,
@@ -465,10 +349,9 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
GAsyncReadyCallback callback,
gpointer user_data)
{
- ClutterActor *stage;
ShellScreenshotPrivate *priv;
- gboolean use_paint_signal = FALSE;
GTask *result;
+ ShellScreenshotFlag flags;
g_return_if_fail (SHELL_IS_SCREENSHOT (screenshot));
g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
@@ -492,34 +375,12 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
g_task_set_source_tag (result, shell_screenshot_screenshot);
priv->stream = g_object_ref (stream);
- priv->include_cursor = FALSE;
-
- stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
-
- meta_disable_unredirect_for_display (shell_global_get_display (priv->global));
+ flags = SHELL_SCREENSHOT_FLAG_NONE;
if (include_cursor)
- {
- if (should_draw_cursor_image (SHELL_SCREENSHOT_SCREEN))
- priv->include_cursor = TRUE;
- else
- use_paint_signal = TRUE;
- }
+ flags |= SHELL_SCREENSHOT_FLAG_INCLUDE_CURSOR;
- if (use_paint_signal)
- {
- g_signal_connect_after (stage, "paint",
- G_CALLBACK (on_paint),
- result);
- }
- else
- {
- g_signal_connect_after (stage, "actors-painted",
- G_CALLBACK (on_actors_painted),
- result);
- }
-
- clutter_actor_queue_redraw (stage);
+ grab_screenshot (screenshot, flags, result);
}
/**
@@ -575,9 +436,9 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
GAsyncReadyCallback callback,
gpointer user_data)
{
- ClutterActor *stage;
ShellScreenshotPrivate *priv;
GTask *result;
+ g_autoptr (GTask) task = NULL;
g_return_if_fail (SHELL_IS_SCREENSHOT (screenshot));
g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
@@ -606,13 +467,15 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
priv->screenshot_area.width = width;
priv->screenshot_area.height = height;
- stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
-
- meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
-
- g_signal_connect_after (stage, "actors-painted", G_CALLBACK (grab_area_screenshot), result);
+ do_grab_screenshot (screenshot,
+ priv->screenshot_area.x,
+ priv->screenshot_area.y,
+ priv->screenshot_area.width,
+ priv->screenshot_area.height,
+ SHELL_SCREENSHOT_FLAG_NONE);
- clutter_actor_queue_redraw (stage);
+ task = g_task_new (screenshot, NULL, on_screenshot_written, result);
+ g_task_run_in_thread (task, write_screenshot_thread);
}
/**
@@ -666,7 +529,6 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
{
ShellScreenshotPrivate *priv;
MetaDisplay *display;
- ClutterActor *stage;
MetaWindow *window;
GTask *result;
@@ -695,16 +557,8 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
priv->stream = g_object_ref (stream);
priv->include_frame = include_frame;
- priv->include_cursor = include_cursor &&
- should_draw_cursor_image (SHELL_SCREENSHOT_WINDOW);
-
- stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
- meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
-
- g_signal_connect_after (stage, "actors-painted", G_CALLBACK (grab_window_screenshot), result);
-
- clutter_actor_queue_redraw (stage);
+ grab_window_screenshot (screenshot, include_cursor, result);
}
/**
@@ -753,9 +607,7 @@ shell_screenshot_pick_color (ShellScreenshot *screenshot,
gpointer user_data)
{
ShellScreenshotPrivate *priv;
- MetaDisplay *display;
- ClutterActor *stage;
- GTask *result;
+ g_autoptr (GTask) result = NULL;
g_return_if_fail (SHELL_IS_SCREENSHOT (screenshot));
@@ -769,14 +621,14 @@ shell_screenshot_pick_color (ShellScreenshot *screenshot,
priv->screenshot_area.width = 1;
priv->screenshot_area.height = 1;
- display = shell_global_get_display (priv->global);
- stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
-
- meta_disable_unredirect_for_display (display);
-
- g_signal_connect_after (stage, "actors-painted", G_CALLBACK (grab_pixel), result);
+ do_grab_screenshot (screenshot,
+ priv->screenshot_area.x,
+ priv->screenshot_area.y,
+ 1,
+ 1,
+ SHELL_SCREENSHOT_FLAG_NONE);
- clutter_actor_queue_redraw (stage);
+ g_task_return_boolean (result, TRUE);
}
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]