[gtk+/wip/otte/clipboard: 60/102] clipboard: Add gdk_clipboard_read_text_async()



commit ed07212360c75d7ad3c85420fa34fa384e687903
Author: Benjamin Otte <otte redhat com>
Date:   Wed Nov 22 14:19:02 2017 +0100

    clipboard: Add gdk_clipboard_read_text_async()
    
    Also add deserializers for G_TYPE_STRING.

 gdk/gdkclipboard.c           |   64 ++++++++++++++++++++++++++++++++
 gdk/gdkclipboard.h           |    9 +++++
 gdk/gdkcontentdeserializer.c |   82 ++++++++++++++++++++++++++++++++++++++++++
 tests/testclipboard2.c       |   36 ++++++++++++++++++
 4 files changed, 191 insertions(+), 0 deletions(-)
---
diff --git a/gdk/gdkclipboard.c b/gdk/gdkclipboard.c
index 67bafba..2b37270 100644
--- a/gdk/gdkclipboard.c
+++ b/gdk/gdkclipboard.c
@@ -546,6 +546,70 @@ gdk_clipboard_read_pixbuf_finish (GdkClipboard  *clipboard,
   return g_value_dup_object (value);
 }
 
+/**
+ * gdk_clipboard_read_text_async:
+ * @clipboard: a #GdkClipboard
+ * @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
+ * @callback: (scope async): callback to call when the request is satisfied
+ * @user_data: (closure): the data to pass to callback function
+ *
+ * Asynchronously request the @clipboard contents converted to a string.
+ * When the operation is finished @callback will be called. You can then
+ * call gdk_clipboard_read_text_finish() to get the result.
+ *
+ * This is a simple wrapper around gdk_clipboard_read_value_async(). Use
+ * that function or gdk_clipboard_read_async() directly if you need more
+ * control over the operation.
+ **/
+void
+gdk_clipboard_read_text_async (GdkClipboard        *clipboard,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
+{
+  g_return_if_fail (GDK_IS_CLIPBOARD (clipboard));
+  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+  g_return_if_fail (callback != NULL);
+
+  gdk_clipboard_read_value_internal (clipboard,
+                                     G_TYPE_STRING,
+                                     gdk_clipboard_read_text_async,
+                                     G_PRIORITY_DEFAULT,
+                                     cancellable,
+                                     callback,
+                                     user_data);
+}
+
+/**
+ * gdk_clipboard_read_text_finish:
+ * @clipboard: a #GdkClipboard
+ * @result: a #GAsyncResult
+ * @error: a #GError location to store the error occurring, or %NULL to 
+ * ignore.
+ *
+ * Finishes an asynchronous clipboard read started with
+ * gdk_clipboard_read_text_async().
+ *
+ * Returns: (transfer full) (nullable): a new string or %NULL on error.
+ **/
+char *
+gdk_clipboard_read_text_finish (GdkClipboard  *clipboard,
+                                GAsyncResult  *res,
+                                GError       **error)
+{
+  const GValue *value;
+
+  g_return_val_if_fail (g_task_is_valid (res, clipboard), NULL);
+  g_return_val_if_fail (g_task_get_source_tag (G_TASK (res)) == gdk_clipboard_read_text_async, NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  value = g_task_propagate_pointer (G_TASK (res), error);
+  if (!value)
+    return NULL;
+  
+  return g_value_dup_string (value);
+}
+
 GdkClipboard *
 gdk_clipboard_new (GdkDisplay *display)
 {
diff --git a/gdk/gdkclipboard.h b/gdk/gdkclipboard.h
index f9a6f14..9fce851 100644
--- a/gdk/gdkclipboard.h
+++ b/gdk/gdkclipboard.h
@@ -74,6 +74,15 @@ GDK_AVAILABLE_IN_3_94
 GdkPixbuf *             gdk_clipboard_read_pixbuf_finish(GdkClipboard          *clipboard,
                                                          GAsyncResult          *res,
                                                          GError               **error);
+GDK_AVAILABLE_IN_3_94
+void                    gdk_clipboard_read_text_async   (GdkClipboard          *clipboard,
+                                                         GCancellable          *cancellable,
+                                                         GAsyncReadyCallback    callback,
+                                                         gpointer               user_data);
+GDK_AVAILABLE_IN_3_94
+char *                  gdk_clipboard_read_text_finish  (GdkClipboard          *clipboard,
+                                                         GAsyncResult          *res,
+                                                         GError               **error);
 
 G_END_DECLS
 
diff --git a/gdk/gdkcontentdeserializer.c b/gdk/gdkcontentdeserializer.c
index d6ec674..bcfc11e 100644
--- a/gdk/gdkcontentdeserializer.c
+++ b/gdk/gdkcontentdeserializer.c
@@ -433,10 +433,72 @@ pixbuf_deserializer (GdkContentDeserializer *deserializer)
 }
 
 static void
+string_deserializer_finish (GObject      *source,
+                            GAsyncResult *result,
+                            gpointer      deserializer)
+{
+  GOutputStream *stream = G_OUTPUT_STREAM (source);
+  GError *error = NULL;
+  gssize written;
+
+  written = g_output_stream_splice_finish (stream, result, &error);
+  if (written < 0)
+    {
+      gdk_content_deserializer_return_error (deserializer, error);
+      return;
+    }
+  else if (written == 0)
+    {
+      /* Never return NULL, we only return that on error */
+      g_value_set_string (gdk_content_deserializer_get_value (deserializer), "");
+    }
+  else
+    {
+      g_value_take_string (gdk_content_deserializer_get_value (deserializer),
+                           g_memory_output_stream_steal_data (G_MEMORY_OUTPUT_STREAM (
+                               g_filter_output_stream_get_base_stream (G_FILTER_OUTPUT_STREAM (stream)))));
+    }
+  gdk_content_deserializer_return_success (deserializer);
+}
+
+static void
+string_deserializer (GdkContentDeserializer *deserializer)
+{
+  GOutputStream *output, *filter;
+  GCharsetConverter *converter;
+  GError *error = NULL;
+
+  converter = g_charset_converter_new ("utf-8",
+                                       gdk_content_deserializer_get_user_data (deserializer),
+                                       &error);
+  if (converter == NULL)
+    {
+      gdk_content_deserializer_return_error (deserializer, error);
+      return;
+    }
+  g_charset_converter_set_use_fallback (converter, TRUE);
+
+  output = g_memory_output_stream_new_resizable ();
+  filter = g_converter_output_stream_new (output, G_CONVERTER (converter));
+  g_object_unref (output);
+  g_object_unref (converter);
+
+  g_output_stream_splice_async (filter,
+                                gdk_content_deserializer_get_input_stream (deserializer),
+                                G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
+                                gdk_content_deserializer_get_priority (deserializer),
+                                gdk_content_deserializer_get_cancellable (deserializer),
+                                string_deserializer_finish,
+                                deserializer);
+  g_object_unref (filter);
+}
+
+static void
 init (void)
 {
   static gboolean initialized = FALSE;
   GSList *formats, *f;
+  const char *charset;
 
   if (initialized)
     return;
@@ -483,5 +545,25 @@ init (void)
     }
 
   g_slist_free (formats);
+
+  gdk_content_register_deserializer ("text/plain;charset=utf-8",
+                                     G_TYPE_STRING,
+                                     string_deserializer,
+                                     (gpointer) "utf-8",
+                                     NULL);
+  if (!g_get_charset (&charset))
+    {
+      char *mime = g_strdup_printf ("text/plain;charset=%s", charset);
+      gdk_content_register_deserializer (mime,
+                                         G_TYPE_STRING,
+                                         string_deserializer,
+                                         mime,
+                                         g_free);
+    }
+  gdk_content_register_deserializer ("text/plain",
+                                     G_TYPE_STRING,
+                                     string_deserializer,
+                                     (gpointer) "ASCII",
+                                     NULL);
 }
 
diff --git a/tests/testclipboard2.c b/tests/testclipboard2.c
index 31efc64..23eddfe 100644
--- a/tests/testclipboard2.c
+++ b/tests/testclipboard2.c
@@ -27,6 +27,9 @@ clipboard_changed_cb (GdkClipboard *clipboard,
 
   child = gtk_stack_get_child_by_name (GTK_STACK (stack), "image");
   gtk_image_clear (GTK_IMAGE (child));
+
+  child = gtk_stack_get_child_by_name (GTK_STACK (stack), "text");
+  gtk_label_set_text (GTK_LABEL (child), "");
 }
 
 static void
@@ -50,6 +53,26 @@ pixbuf_loaded_cb (GObject      *clipboard,
 }
 
 static void
+text_loaded_cb (GObject      *clipboard,
+                GAsyncResult *res,
+                gpointer      data)
+{
+  GError *error = NULL;
+  char *text;
+
+  text = gdk_clipboard_read_text_finish (GDK_CLIPBOARD (clipboard), res, &error);
+  if (text == NULL)
+    {
+      g_print ("%s\n", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  gtk_label_set_text (data, text);
+  g_free (text);
+}
+
+static void
 visible_child_changed_cb (GtkWidget    *stack,
                           GParamSpec   *pspec,
                           GdkClipboard *clipboard)
@@ -69,6 +92,15 @@ visible_child_changed_cb (GtkWidget    *stack,
                                        pixbuf_loaded_cb,
                                        image);
     }
+  else if (g_str_equal (visible_child, "text"))
+    {
+      GtkWidget *label = gtk_stack_get_child_by_name (GTK_STACK (stack), "text");
+
+      gdk_clipboard_read_text_async (clipboard,
+                                     NULL,
+                                     text_loaded_cb,
+                                     label);
+    }
 }
                 
 static void
@@ -103,6 +135,10 @@ get_contents_widget (GdkClipboard *clipboard)
   child = gtk_image_new ();
   gtk_stack_add_titled (GTK_STACK (stack), child, "image", "Image");
 
+  child = gtk_label_new (NULL);
+  gtk_label_set_line_wrap (GTK_LABEL (child), TRUE);
+  gtk_stack_add_titled (GTK_STACK (stack), child, "text", "Text");
+
   return stack;
 }
 


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