[gnome-shell] screenshot: Add API to screenshot stage to a ClutterContent
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] screenshot: Add API to screenshot stage to a ClutterContent
- Date: Thu, 27 Jan 2022 22:30:53 +0000 (UTC)
commit deb614a031b1e0ec3811f537bc7138dd18a02fc3
Author: Ivan Molodetskikh <yalterz gmail com>
Date: Sat Jan 15 18:22:44 2022 +0300
screenshot: Add API to screenshot stage to a ClutterContent
As mentioned in the last commit, we'll split up taking screenshots into
creating a GPU texture first, and later saving that to disk as a PNG.
For individual windows it's already easy to get a ClutterContent with
the texture using meta_window_actor_paint_to_content (), for the stage
it's not that easy and involves a few extra steps including X11 specific
ones.
So introduce a new ShellScreenshot API which does all that and provides
the caller with a ClutterContent of the stage:
shell_screenshot_screenshot_stage_to_content ()
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1954>
src/shell-screenshot.c | 146 +++++++++++++++++++++++++++++++++++++++++++++++++
src/shell-screenshot.h | 8 +++
2 files changed, 154 insertions(+)
---
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c
index 34494185a6..ac549297b5 100644
--- a/src/shell-screenshot.c
+++ b/src/shell-screenshot.c
@@ -57,6 +57,8 @@ struct _ShellScreenshotPrivate
cairo_rectangle_int_t screenshot_area;
gboolean include_frame;
+
+ float scale;
};
G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT);
@@ -289,6 +291,51 @@ grab_screenshot (ShellScreenshot *screenshot,
g_object_unref (task);
}
+static void
+grab_screenshot_content (ShellScreenshot *screenshot,
+ GTask *result)
+{
+ ShellScreenshotPrivate *priv = screenshot->priv;
+ MetaDisplay *display;
+ int width, height;
+ cairo_rectangle_int_t screenshot_rect;
+ ClutterStage *stage;
+ int image_width;
+ int image_height;
+ float scale;
+ g_autoptr (GError) error = NULL;
+ g_autoptr (ClutterContent) content = NULL;
+
+ display = shell_global_get_display (priv->global);
+ meta_display_get_size (display, &width, &height);
+ screenshot_rect = (cairo_rectangle_int_t) {
+ .x = 0,
+ .y = 0,
+ .width = width,
+ .height = height,
+ };
+
+ stage = shell_global_get_stage (priv->global);
+
+ clutter_stage_get_capture_final_size (stage, &screenshot_rect,
+ &image_width,
+ &image_height,
+ &scale);
+
+ priv->scale = scale;
+
+ content = clutter_stage_paint_to_content (stage, &screenshot_rect, scale,
+ CLUTTER_PAINT_FLAG_NO_CURSORS,
+ &error);
+ if (!content)
+ {
+ g_task_return_error (result, g_steal_pointer (&error));
+ return;
+ }
+
+ g_task_return_pointer (result, g_steal_pointer (&content), g_object_unref);
+}
+
static void
grab_window_screenshot (ShellScreenshot *screenshot,
ShellScreenshotFlag flags,
@@ -497,6 +544,105 @@ shell_screenshot_screenshot_finish (ShellScreenshot *screenshot,
return finish_screenshot (screenshot, result, area, error);
}
+static void
+screenshot_stage_to_content_on_after_paint (ClutterStage *stage,
+ ClutterStageView *view,
+ GTask *result)
+{
+ ShellScreenshot *screenshot = g_task_get_task_data (result);
+ ShellScreenshotPrivate *priv = screenshot->priv;
+ MetaDisplay *display = shell_global_get_display (priv->global);
+
+ g_signal_handlers_disconnect_by_func (stage,
+ screenshot_stage_to_content_on_after_paint,
+ result);
+
+ meta_enable_unredirect_for_display (display);
+
+ grab_screenshot_content (screenshot, result);
+}
+
+/**
+ * shell_screenshot_screenshot_stage_to_content:
+ * @screenshot: the #ShellScreenshot
+ * @callback: (scope async): function to call returning success or failure
+ * of the async grabbing
+ * @user_data: the data to pass to callback function
+ *
+ * Takes a screenshot of the whole screen as #ClutterContent.
+ *
+ */
+void
+shell_screenshot_screenshot_stage_to_content (ShellScreenshot *screenshot,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ ShellScreenshotPrivate *priv;
+ GTask *result;
+
+ g_return_if_fail (SHELL_IS_SCREENSHOT (screenshot));
+
+ result = g_task_new (screenshot, NULL, callback, user_data);
+ g_task_set_source_tag (result, shell_screenshot_screenshot_stage_to_content);
+ g_task_set_task_data (result, screenshot, NULL);
+
+ if (meta_is_wayland_compositor ())
+ {
+ grab_screenshot_content (screenshot, result);
+ }
+ else
+ {
+ priv = screenshot->priv;
+
+ MetaDisplay *display = shell_global_get_display (priv->global);
+ ClutterStage *stage = shell_global_get_stage (priv->global);
+
+ meta_disable_unredirect_for_display (display);
+ clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
+ g_signal_connect (stage, "after-paint",
+ G_CALLBACK (screenshot_stage_to_content_on_after_paint),
+ result);
+ }
+}
+
+/**
+ * shell_screenshot_screenshot_stage_to_content_finish:
+ * @screenshot: the #ShellScreenshot
+ * @result: the #GAsyncResult that was provided to the callback
+ * @scale: (out) (optional): location to store the content scale
+ * @error: #GError for error reporting
+ *
+ * Finish the asynchronous operation started by
+ * shell_screenshot_screenshot_stage_to_content() and obtain its result.
+ *
+ * Returns: (transfer full): the #ClutterContent, or NULL
+ *
+ */
+ClutterContent *
+shell_screenshot_screenshot_stage_to_content_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ float *scale,
+ GError **error)
+{
+ ShellScreenshotPrivate *priv = screenshot->priv;
+ ClutterContent *content;
+
+ g_return_val_if_fail (SHELL_IS_SCREENSHOT (screenshot), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+ g_return_val_if_fail (g_async_result_is_tagged (result,
+ shell_screenshot_screenshot_stage_to_content),
+ FALSE);
+
+ content = g_task_propagate_pointer (G_TASK (result), error);
+ if (!content)
+ return NULL;
+
+ if (scale)
+ *scale = priv->scale;
+
+ return content;
+}
+
/**
* shell_screenshot_screenshot_area:
* @screenshot: the #ShellScreenshot
diff --git a/src/shell-screenshot.h b/src/shell-screenshot.h
index 838e910a7e..a5dc96de89 100644
--- a/src/shell-screenshot.h
+++ b/src/shell-screenshot.h
@@ -50,6 +50,14 @@ gboolean shell_screenshot_screenshot_finish (ShellScreenshot *screensho
cairo_rectangle_int_t **area,
GError **error);
+void shell_screenshot_screenshot_stage_to_content (ShellScreenshot *screenshot,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ClutterContent *shell_screenshot_screenshot_stage_to_content_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ float *scale,
+ GError **error);
+
void shell_screenshot_pick_color (ShellScreenshot *screenshot,
int x,
int y,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]