diff options
author | Florian Müllner <fmuellner@gnome.org> | 2018-07-19 14:50:49 +0200 |
---|---|---|
committer | Florian Müllner <florian.muellner@gmail.com> | 2018-07-30 16:55:10 +0000 |
commit | be84a00022cd75528a842fcc8730c1bca66d7eb4 (patch) | |
tree | 20a685dd8ea93c801cc84f4a01f37f7ff5bcecaf | |
parent | da537cda4345374a68570846a91d8d5f2c836d7e (diff) | |
download | gnome-shell-be84a00022cd75528a842fcc8730c1bca66d7eb4.tar.gz |
screenshot: Add pick_color() method
Graphical applications like GIMP or GIMP allow picking colors from
any location on-screen. In order to keep supporting this feature
on wayland and in sandboxed apps, we will expose an appropriate
method in the Screenshot interface, so first add a corresponding
method to ShellScreenshot.
https://gitlab.gnome.org/GNOME/gnome-shell/issues/286
-rw-r--r-- | src/shell-screenshot.c | 122 | ||||
-rw-r--r-- | src/shell-screenshot.h | 10 |
2 files changed, 132 insertions, 0 deletions
diff --git a/src/shell-screenshot.c b/src/shell-screenshot.c index f26ff64b5..4a119a153 100644 --- a/src/shell-screenshot.c +++ b/src/shell-screenshot.c @@ -456,6 +456,27 @@ grab_window_screenshot (ClutterActor *stage, 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, @@ -731,6 +752,107 @@ shell_screenshot_screenshot_window_finish (ShellScreenshot *screenshot, return finish_screenshot (screenshot, result, area, filename_used, error); } +/** + * shell_screenshot_pick_color: + * @screenshot: the #ShellScreenshot + * @x: The X coordinate to pick + * @y: The Y coordinate to pick + * @callback: (scope async): function to call returning success or failure + * of the async grabbing + * + * Picks the pixel at @x, @y and returns its color as #ClutterColor. + * + */ +void +shell_screenshot_pick_color (ShellScreenshot *screenshot, + int x, + int y, + GAsyncReadyCallback callback, + gpointer user_data) +{ + ShellScreenshotPrivate *priv = screenshot->priv; + MetaDisplay *display = shell_global_get_display (priv->global); + ClutterActor *stage; + GTask *result; + + result = g_task_new (screenshot, NULL, callback, user_data); + g_task_set_source_tag (result, shell_screenshot_pick_color); + + priv->screenshot_area.x = x; + priv->screenshot_area.y = y; + priv->screenshot_area.width = 1; + priv->screenshot_area.height = 1; + + stage = CLUTTER_ACTOR (shell_global_get_stage (priv->global)); + + meta_disable_unredirect_for_display (display); + + g_signal_connect_after (stage, "paint", G_CALLBACK (grab_pixel), result); + + clutter_actor_queue_redraw (stage); +} + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define INDEX_A 3 +#define INDEX_R 2 +#define INDEX_G 1 +#define INDEX_B 0 +#else +#define INDEX_A 0 +#define INDEX_R 1 +#define INDEX_G 2 +#define INDEX_B 3 +#endif + +/** + * shell_screenshot_pick_color_finish: + * @screenshot: the #ShellScreenshot + * @result: the #GAsyncResult that was provided to the callback + * @color: (out caller-allocates): the picked color + * @error: #GError for error reporting + * + * Finish the asynchronous operation started by shell_screenshot_pick_color() + * and obtain its result. + * + * Returns: whether the operation was successful + * + */ +gboolean +shell_screenshot_pick_color_finish (ShellScreenshot *screenshot, + GAsyncResult *result, + ClutterColor *color, + GError **error) +{ + ShellScreenshotPrivate *priv = screenshot->priv; + + g_return_val_if_fail (g_async_result_is_tagged (result, + shell_screenshot_pick_color), + FALSE); + + if (!g_task_propagate_boolean (G_TASK (result), error)) + return FALSE; + + /* protect against mutter changing the format used for stage captures */ + g_assert (cairo_image_surface_get_format (priv->image) == CAIRO_FORMAT_ARGB32); + + if (color) + { + uint8_t *data = cairo_image_surface_get_data (priv->image); + + color->alpha = data[INDEX_A]; + color->red = data[INDEX_R]; + color->green = data[INDEX_G]; + color->blue = data[INDEX_B]; + } + + return TRUE; +} + +#undef INDEX_A +#undef INDEX_R +#undef INDEX_G +#undef INDEX_B + ShellScreenshot * shell_screenshot_new (void) { diff --git a/src/shell-screenshot.h b/src/shell-screenshot.h index 61178e2ec..2367d518e 100644 --- a/src/shell-screenshot.h +++ b/src/shell-screenshot.h @@ -53,4 +53,14 @@ gboolean shell_screenshot_screenshot_finish (ShellScreenshot *screensho const char **filename_used, GError **error); +void shell_screenshot_pick_color (ShellScreenshot *screenshot, + int x, + int y, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean shell_screenshot_pick_color_finish (ShellScreenshot *screenshot, + GAsyncResult *result, + ClutterColor *color, + GError **error); + #endif /* ___SHELL_SCREENSHOT_H__ */ |