[gnome-shell/wip/fmuellner/color-picker: 2/5] screenshot: Adopt GIO's async pattern
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell/wip/fmuellner/color-picker: 2/5] screenshot: Adopt GIO's async pattern
- Date: Mon, 30 Jul 2018 16:58:57 +0000 (UTC)
commit da537cda4345374a68570846a91d8d5f2c836d7e
Author: Florian Müllner <fmuellner gnome org>
Date: Thu Jul 19 15:54:33 2018 +0200
screenshot: Adopt GIO's async pattern
A custom callback type is more convenient, but only as long as no
other callback type is required. We are about to add functionality
that does not return the filename to a screenshot saved on disk, so
prepare for that by moving to GIO's generic async callback pattern.
https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
js/ui/screenshot.js | 38 ++++++--
src/shell-screenshot.c | 242 ++++++++++++++++++++++++++++++++++++++-----------
src/shell-screenshot.h | 55 ++++++-----
3 files changed, 253 insertions(+), 82 deletions(-)
---
diff --git a/js/ui/screenshot.js b/js/ui/screenshot.js
index 6e99568a3..5f9ab1933 100644
--- a/js/ui/screenshot.js
+++ b/js/ui/screenshot.js
@@ -110,7 +110,7 @@ var ScreenshotService = new Lang.Class({
y + height <= global.screen_height;
},
- _onScreenshotComplete(obj, result, area, filenameUsed, flash, invocation) {
+ _onScreenshotComplete(result, area, filenameUsed, flash, invocation) {
if (result) {
if (flash) {
let flashspot = new Flashspot(area);
@@ -157,9 +157,15 @@ var ScreenshotService = new Lang.Class({
if (!screenshot)
return;
screenshot.screenshot_area (x, y, width, height, filename,
- (obj, result, area, filenameUsed) => {
- this._onScreenshotComplete(obj, result, area, filenameUsed,
- flash, invocation);
+ (o, res) => {
+ try {
+ let [result, area, filenameUsed] =
+ screenshot.screenshot_area_finish(res);
+ this._onScreenshotComplete(result, area, filenameUsed,
+ flash, invocation);
+ } catch (e) {
+ invocation.return_gerror (e);
+ }
});
},
@@ -169,9 +175,15 @@ var ScreenshotService = new Lang.Class({
if (!screenshot)
return;
screenshot.screenshot_window (include_frame, include_cursor, filename,
- (obj, result, area, filenameUsed) => {
- this._onScreenshotComplete(obj, result, area, filenameUsed,
- flash, invocation);
+ (o, res) => {
+ try {
+ let [result, area, filenameUsed] =
+ screenshot.screenshot_window_finish(res);
+ this._onScreenshotComplete(result, area, filenameUsed,
+ flash, invocation);
+ } catch (e) {
+ invocation.return_gerror (e);
+ }
});
},
@@ -181,9 +193,15 @@ var ScreenshotService = new Lang.Class({
if (!screenshot)
return;
screenshot.screenshot(include_cursor, filename,
- (obj, result, area, filenameUsed) => {
- this._onScreenshotComplete(obj, result, area, filenameUsed,
- flash, invocation);
+ (o, res) => {
+ try {
+ let [result, area, filenameUsed] =
+ screenshot.screenshot_finish(res);
+ this._onScreenshotComplete(result, area, filenameUsed,
+ flash, invocation);
+ } catch (e) {
+ invocation.return_gerror (e);
+ }
});
},
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c
index e0b765d53..f26ff64b5 100644
--- a/src/shell-screenshot.c
+++ b/src/shell-screenshot.c
@@ -38,8 +38,6 @@ struct _ShellScreenshotPrivate
gboolean include_cursor;
gboolean include_frame;
-
- ShellScreenshotCallback callback;
};
G_DEFINE_TYPE_WITH_PRIVATE (ShellScreenshot, shell_screenshot, G_TYPE_OBJECT);
@@ -59,17 +57,15 @@ shell_screenshot_init (ShellScreenshot *screenshot)
static void
on_screenshot_written (GObject *source,
- GAsyncResult *result,
+ GAsyncResult *task,
gpointer user_data)
{
ShellScreenshot *screenshot = SHELL_SCREENSHOT (source);
ShellScreenshotPrivate *priv = screenshot->priv;
+ GTask *result = user_data;
- if (priv->callback)
- priv->callback (screenshot,
- g_task_propagate_boolean (G_TASK (result), NULL),
- &priv->screenshot_area,
- priv->filename_used);
+ g_task_return_boolean (result, g_task_propagate_boolean (G_TASK (task), NULL));
+ g_object_unref (result);
g_clear_pointer (&priv->image, cairo_surface_destroy);
g_clear_pointer (&priv->filename, g_free);
@@ -313,14 +309,15 @@ _draw_cursor_image (MetaCursorTracker *tracker,
static void
grab_screenshot (ClutterActor *stage,
- ShellScreenshot *screenshot)
+ GTask *result)
{
MetaDisplay *display;
MetaCursorTracker *tracker;
int width, height;
- GTask *result;
GSettings *settings;
+ 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);
@@ -380,19 +377,20 @@ grab_screenshot (ClutterActor *stage,
}
g_object_unref (settings);
- g_signal_handlers_disconnect_by_func (stage, (void *)grab_screenshot, (gpointer)screenshot);
+ g_signal_handlers_disconnect_by_func (stage, grab_screenshot, result);
- result = g_task_new (screenshot, NULL, on_screenshot_written, NULL);
- g_task_run_in_thread (result, write_screenshot_thread);
- g_object_unref (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,
- ShellScreenshot *screenshot)
+ GTask *result)
{
- GTask *result;
+ ShellScreenshot *screenshot = g_task_get_source_object (result);
ShellScreenshotPrivate *priv = screenshot->priv;
+ GTask *task;
do_grab_screenshot (screenshot,
CLUTTER_STAGE (stage),
@@ -401,18 +399,19 @@ grab_area_screenshot (ClutterActor *stage,
priv->screenshot_area.width,
priv->screenshot_area.height);
- g_signal_handlers_disconnect_by_func (stage, (void *)grab_area_screenshot, (gpointer)screenshot);
- result = g_task_new (screenshot, NULL, on_screenshot_written, NULL);
- g_task_run_in_thread (result, write_screenshot_thread);
- g_object_unref (result);
+ 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,
- ShellScreenshot *screenshot)
+ GTask *result)
{
+ ShellScreenshot *screenshot = g_task_get_source_object (result);
ShellScreenshotPrivate *priv = screenshot->priv;
- GTask *result;
+ GTask *task;
GSettings *settings;
MetaDisplay *display = shell_global_get_display (priv->global);
MetaCursorTracker *tracker;
@@ -451,10 +450,31 @@ grab_window_screenshot (ClutterActor *stage,
}
g_object_unref (settings);
- g_signal_handlers_disconnect_by_func (stage, (void *)grab_window_screenshot, (gpointer)screenshot);
- result = g_task_new (screenshot, NULL, on_screenshot_written, NULL);
- g_task_run_in_thread (result, write_screenshot_thread);
- g_object_unref (result);
+ 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 gboolean
+finish_screenshot (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ cairo_rectangle_int_t **area,
+ const char **filename_used,
+ GError **error)
+{
+ ShellScreenshotPrivate *priv = screenshot->priv;
+
+ if (!g_task_propagate_boolean (G_TASK (result), error))
+ return FALSE;
+
+ if (area)
+ *area = &priv->screenshot_area;
+
+ if (filename_used)
+ *filename_used = priv->filename_used;
+
+ return TRUE;
}
/**
@@ -464,39 +484,79 @@ grab_window_screenshot (ClutterActor *stage,
* @filename: The filename for the screenshot
* @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
* in @filename as png image.
*
*/
void
-shell_screenshot_screenshot (ShellScreenshot *screenshot,
- gboolean include_cursor,
- const char *filename,
- ShellScreenshotCallback callback)
+shell_screenshot_screenshot (ShellScreenshot *screenshot,
+ gboolean include_cursor,
+ const char *filename,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
ClutterActor *stage;
ShellScreenshotPrivate *priv = screenshot->priv;
+ GTask *result;
if (priv->filename != NULL) {
if (callback)
- callback (screenshot, FALSE, NULL, "");
+ g_task_report_new_error (screenshot,
+ callback,
+ user_data,
+ shell_screenshot_screenshot,
+ G_IO_ERROR,
+ G_IO_ERROR_PENDING,
+ "Only one screenshot operation at a time "
+ "is permitted");
return;
}
+ result = g_task_new (screenshot, NULL, callback, user_data);
+ g_task_set_source_tag (result, shell_screenshot_screenshot);
+
priv->filename = g_strdup (filename);
- priv->callback = callback;
priv->include_cursor = include_cursor;
stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global));
meta_disable_unredirect_for_display (shell_global_get_display (priv->global));
- g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), (gpointer)screenshot);
+ g_signal_connect_after (stage, "paint", G_CALLBACK (grab_screenshot), result);
clutter_actor_queue_redraw (stage);
}
+/**
+ * shell_screenshot_screenshot_finish:
+ * @screenshot: the #ShellScreenshot
+ * @result: the #GAsyncResult that was provided to the callback
+ * @area: (out) (transfer none): the area that was grabbed in screen coordinates
+ * @filename_used: (out) (transfer none): the name of the file the screenshot
+ * was written to
+ * @error: #GError for error reporting
+ *
+ * Finish the asynchronous operation started by shell_screenshot_screenshot()
+ * and obtain its result.
+ *
+ * Returns: whether the operation was successful
+ *
+ */
+gboolean
+shell_screenshot_screenshot_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ cairo_rectangle_int_t **area,
+ const char **filename_used,
+ GError **error)
+{
+ g_return_val_if_fail (g_async_result_is_tagged (result,
+ shell_screenshot_screenshot),
+ FALSE);
+ return finish_screenshot (screenshot, result, area, filename_used, error);
+}
+
/**
* shell_screenshot_screenshot_area:
* @screenshot: the #ShellScreenshot
@@ -507,45 +567,85 @@ shell_screenshot_screenshot (ShellScreenshot *screenshot,
* @filename: The filename for the screenshot
* @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 passed in area and saves it
* in @filename as png image.
*
*/
void
-shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
- int x,
- int y,
- int width,
- int height,
- const char *filename,
- ShellScreenshotCallback callback)
+shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
+ int x,
+ int y,
+ int width,
+ int height,
+ const char *filename,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
ClutterActor *stage;
ShellScreenshotPrivate *priv = screenshot->priv;
+ GTask *result;
if (priv->filename != NULL) {
if (callback)
- callback (screenshot, FALSE, NULL, "");
+ g_task_report_new_error (screenshot,
+ callback,
+ NULL,
+ shell_screenshot_screenshot_area,
+ G_IO_ERROR,
+ G_IO_ERROR_PENDING,
+ "Only one screenshot operation at a time "
+ "is permitted");
return;
}
+ result = g_task_new (screenshot, NULL, callback, user_data);
+ g_task_set_source_tag (result, shell_screenshot_screenshot_area);
+
priv->filename = g_strdup (filename);
priv->screenshot_area.x = x;
priv->screenshot_area.y = y;
priv->screenshot_area.width = width;
priv->screenshot_area.height = height;
- priv->callback = callback;
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, "paint", G_CALLBACK (grab_area_screenshot), (gpointer)screenshot);
+ g_signal_connect_after (stage, "paint", G_CALLBACK (grab_area_screenshot), result);
clutter_actor_queue_redraw (stage);
}
+/**
+ * shell_screenshot_screenshot_area_finish:
+ * @screenshot: the #ShellScreenshot
+ * @result: the #GAsyncResult that was provided to the callback
+ * @area: (out) (transfer none): the area that was grabbed in screen coordinates
+ * @filename_used: (out) (transfer none): the name of the file the screenshot
+ * was written to
+ * @error: #GError for error reporting
+ *
+ * Finish the asynchronous operation started by shell_screenshot_screenshot_area()
+ * and obtain its result.
+ *
+ * Returns: whether the operation was successful
+ *
+ */
+gboolean
+shell_screenshot_screenshot_area_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ cairo_rectangle_int_t **area,
+ const char **filename_used,
+ GError **error)
+{
+ g_return_val_if_fail (g_async_result_is_tagged (result,
+ shell_screenshot_screenshot_area),
+ FALSE);
+ return finish_screenshot (screenshot, result, area, filename_used, error);
+}
+
/**
* shell_screenshot_screenshot_window:
* @screenshot: the #ShellScreenshot
@@ -554,31 +654,43 @@ shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
* @filename: The filename for the screenshot
* @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 focused window (optionally omitting the frame)
* in @filename as png image.
*
*/
void
-shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
- gboolean include_frame,
- gboolean include_cursor,
- const char *filename,
- ShellScreenshotCallback callback)
+shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
+ gboolean include_frame,
+ gboolean include_cursor,
+ const char *filename,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
ShellScreenshotPrivate *priv = screenshot->priv;
MetaDisplay *display = shell_global_get_display (priv->global);
ClutterActor *stage;
MetaWindow *window = meta_display_get_focus_window (display);
+ GTask *result;
if (priv->filename != NULL || !window) {
if (callback)
- callback (screenshot, FALSE, NULL, "");
+ g_task_report_new_error (screenshot,
+ callback,
+ NULL,
+ shell_screenshot_screenshot_window,
+ G_IO_ERROR,
+ G_IO_ERROR_PENDING,
+ "Only one screenshot operation at a time "
+ "is permitted");
return;
}
+ result = g_task_new (screenshot, NULL, callback, user_data);
+ g_task_set_source_tag (result, shell_screenshot_screenshot_window);
+
priv->filename = g_strdup (filename);
- priv->callback = callback;
priv->include_frame = include_frame;
priv->include_cursor = include_cursor;
@@ -586,11 +698,39 @@ shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
meta_disable_unredirect_for_display (shell_global_get_display (shell_global_get ()));
- g_signal_connect_after (stage, "paint", G_CALLBACK (grab_window_screenshot), (gpointer)screenshot);
+ g_signal_connect_after (stage, "paint", G_CALLBACK (grab_window_screenshot), result);
clutter_actor_queue_redraw (stage);
}
+/**
+ * shell_screenshot_screenshot_window_finish:
+ * @screenshot: the #ShellScreenshot
+ * @result: the #GAsyncResult that was provided to the callback
+ * @area: (out) (transfer none): the area that was grabbed in screen coordinates
+ * @filename_used: (out) (transfer none): the name of the file the screenshot
+ * was written to
+ * @error: #GError for error reporting
+ *
+ * Finish the asynchronous operation started by shell_screenshot_screenshot_window()
+ * and obtain its result.
+ *
+ * Returns: whether the operation was successful
+ *
+ */
+gboolean
+shell_screenshot_screenshot_window_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ cairo_rectangle_int_t **area,
+ const char **filename_used,
+ GError **error)
+{
+ g_return_val_if_fail (g_async_result_is_tagged (result,
+ shell_screenshot_screenshot_window),
+ FALSE);
+ return finish_screenshot (screenshot, result, area, filename_used, error);
+}
+
ShellScreenshot *
shell_screenshot_new (void)
{
diff --git a/src/shell-screenshot.h b/src/shell-screenshot.h
index df00568f7..61178e2ec 100644
--- a/src/shell-screenshot.h
+++ b/src/shell-screenshot.h
@@ -16,28 +16,41 @@ G_DECLARE_FINAL_TYPE (ShellScreenshot, shell_screenshot,
ShellScreenshot *shell_screenshot_new (void);
-typedef void (*ShellScreenshotCallback) (ShellScreenshot *screenshot,
- gboolean success,
- cairo_rectangle_int_t *screenshot_area,
- const gchar *filename_used);
+void shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
+ int x,
+ int y,
+ int width,
+ int height,
+ const char *filename,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean shell_screenshot_screenshot_area_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ cairo_rectangle_int_t **area,
+ const char **filename_used,
+ GError **error);
-void shell_screenshot_screenshot_area (ShellScreenshot *screenshot,
- int x,
- int y,
- int width,
- int height,
- const char *filename,
- ShellScreenshotCallback callback);
+void shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
+ gboolean include_frame,
+ gboolean include_cursor,
+ const char *filename,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean shell_screenshot_screenshot_window_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ cairo_rectangle_int_t **area,
+ const char **filename_used,
+ GError **error);
-void shell_screenshot_screenshot_window (ShellScreenshot *screenshot,
- gboolean include_frame,
- gboolean include_cursor,
- const char *filename,
- ShellScreenshotCallback callback);
-
-void shell_screenshot_screenshot (ShellScreenshot *screenshot,
- gboolean include_cursor,
- const char *filename,
- ShellScreenshotCallback callback);
+void shell_screenshot_screenshot (ShellScreenshot *screenshot,
+ gboolean include_cursor,
+ const char *filename,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean shell_screenshot_screenshot_finish (ShellScreenshot *screenshot,
+ GAsyncResult *result,
+ cairo_rectangle_int_t **area,
+ const char **filename_used,
+ GError **error);
#endif /* ___SHELL_SCREENSHOT_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]