[gnome-shell/wip/fmuellner/color-picker: 3/5] screenshot: Add pick_color() method



commit be84a00022cd75528a842fcc8730c1bca66d7eb4
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Jul 19 14:50:49 2018 +0200

    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

 src/shell-screenshot.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/shell-screenshot.h |  10 ++++
 2 files changed, 132 insertions(+)
---
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__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]