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>
This commit is contained in:
parent
71c6918588
commit
deb614a031
@ -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
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user