[gtk+/wip/otte/clipboard: 74/107] clipboard: Add serialization



commit 520973ca69d33b66b19bc93e7d44dcb8b487f703
Author: Benjamin Otte <otte redhat com>
Date:   Fri Nov 24 11:15:51 2017 +0100

    clipboard: Add serialization
    
    This completes the local clipboard code.

 gdk/gdk.h                  |    1 +
 gdk/gdkclipboard.c         |   72 +++++-
 gdk/gdkcontentserializer.c |  562 ++++++++++++++++++++++++++++++++++++++++++++
 gdk/gdkcontentserializer.h |   90 +++++++
 gdk/meson.build            |    2 +
 5 files changed, 716 insertions(+), 11 deletions(-)
---
diff --git a/gdk/gdk.h b/gdk/gdk.h
index 89f13d2..4f0bf80 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -36,6 +36,7 @@
 #include <gdk/gdkcontentformats.h>
 #include <gdk/gdkcontentprovider.h>
 #include <gdk/gdkcontentproviderimpl.h>
+#include <gdk/gdkcontentserializer.h>
 #include <gdk/gdkcursor.h>
 #include <gdk/gdkdevice.h>
 #include <gdk/gdkdevicepad.h>
diff --git a/gdk/gdkclipboard.c b/gdk/gdkclipboard.c
index b19b090..b5dc5db 100644
--- a/gdk/gdkclipboard.c
+++ b/gdk/gdkclipboard.c
@@ -24,6 +24,7 @@
 #include "gdkcontentformats.h"
 #include "gdkcontentproviderimpl.h"
 #include "gdkcontentproviderprivate.h"
+#include "gdkcontentserializer.h"
 #include "gdkdisplay.h"
 #include "gdkintl.h"
 #include "gdkpipeiostreamprivate.h"
@@ -164,14 +165,10 @@ gdk_clipboard_read_local_async (GdkClipboard        *clipboard,
     }
 
   content_formats = gdk_content_provider_ref_formats (priv->content);
+  content_formats = gdk_content_formats_union_serialize_mime_types (content_formats);
 
-  if (!gdk_content_formats_match (content_formats, formats, NULL, &mime_type)
-      || mime_type == NULL)
-    {
-      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                                     _("No compatible formats to transfer clipboard contents."));
-    }
-  else
+  if (gdk_content_formats_match (content_formats, formats, NULL, &mime_type)
+      && mime_type != NULL)
     {
       GOutputStream *output_stream;
       GIOStream *stream;
@@ -190,6 +187,11 @@ gdk_clipboard_read_local_async (GdkClipboard        *clipboard,
 
       g_object_unref (stream);
     }
+  else
+    {
+      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                                     _("No compatible formats to transfer clipboard contents."));
+    }
 
   gdk_content_formats_unref (content_formats);
   g_object_unref (task);
@@ -826,6 +828,20 @@ gdk_clipboard_write_done (GObject      *content,
   g_object_unref (task);
 }
 
+static void
+gdk_clipboard_write_serialize_done (GObject      *content,
+                                    GAsyncResult *result,
+                                    gpointer      task)
+{
+  GError *error = NULL;
+
+  if (gdk_content_serialize_finish (result, &error))
+    g_task_return_boolean (task, TRUE);
+  else
+    g_task_return_error (task, error);
+
+  g_object_unref (task);
+}
 void
 gdk_clipboard_write_async (GdkClipboard        *clipboard,
                            const char          *mime_type,
@@ -836,8 +852,9 @@ gdk_clipboard_write_async (GdkClipboard        *clipboard,
                            gpointer             user_data)
 {
   GdkClipboardPrivate *priv = gdk_clipboard_get_instance_private (clipboard);
-  GdkContentFormats *formats;
+  GdkContentFormats *formats, *mime_formats;
   GTask *task;
+  GType gtype;
 
   g_return_if_fail (GDK_IS_CLIPBOARD (clipboard));
   g_return_if_fail (priv->local);
@@ -873,11 +890,42 @@ gdk_clipboard_write_async (GdkClipboard        *clipboard,
       return;
     }
 
-  g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-                           _("FIXME: Implement serializing."));
+  mime_formats = gdk_content_formats_new ((const gchar *[2]) { mime_type, NULL }, 1);
+  mime_formats = gdk_content_formats_union_serialize_gtypes (mime_formats);
+  if (gdk_content_formats_match (mime_formats, formats, &gtype, NULL))
+    {
+      GValue value = G_VALUE_INIT;
+      GError *error = NULL;
+
+      g_assert (gtype != G_TYPE_INVALID);
+      
+      g_value_init (&value, gtype);
+      if (gdk_content_provider_get_value (priv->content, &value, &error))
+        {
+          gdk_content_serialize_async (stream,
+                                       mime_type,
+                                       &value,
+                                       io_priority,
+                                       cancellable,
+                                       gdk_clipboard_write_serialize_done,
+                                       g_object_ref (task));
+        }
+      else
+        {
+          g_task_return_error (task, error);
+        }
+      
+      g_value_unset (&value);
+    }
+  else
+    {
+      g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                               _("No compatible formats to transfer clipboard contents."));
+    }
+
+  gdk_content_formats_unref (mime_formats);
   gdk_content_formats_unref (formats);
   g_object_unref (task);
-  return;
 }
 
 gboolean
@@ -954,6 +1002,7 @@ gdk_clipboard_content_changed_cb (GdkContentProvider *provider,
   GdkContentFormats *formats;
 
   formats = gdk_content_provider_ref_formats (provider);
+  formats = gdk_content_formats_union_serialize_mime_types (formats);
 
   gdk_clipboard_claim (clipboard, formats, TRUE, provider);
 
@@ -1000,6 +1049,7 @@ gdk_clipboard_set_content (GdkClipboard       *clipboard,
         return;
 
       formats = gdk_content_provider_ref_formats (provider);
+      formats = gdk_content_formats_union_serialize_mime_types (formats);
     }
   else
     {
diff --git a/gdk/gdkcontentserializer.c b/gdk/gdkcontentserializer.c
new file mode 100644
index 0000000..6860c97
--- /dev/null
+++ b/gdk/gdkcontentserializer.c
@@ -0,0 +1,562 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2017 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+
+#include "gdkcontentserializer.h"
+
+#include "gdkcontentformats.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <string.h>
+
+typedef struct _Serializer Serializer;
+
+struct _Serializer 
+{
+  const char *                    mime_type; /* interned */
+  GType                           type;
+  GdkContentSerializeFunc         serialize;
+  gpointer                        data;
+  GDestroyNotify                  notify;
+};
+
+GQueue serializers = G_QUEUE_INIT;
+
+static void init (void);
+
+#define GDK_CONTENT_SERIALIZER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), 
GDK_TYPE_CONTENT_SERIALIZER, GdkContentSerializerClass))
+#define GDK_IS_CONTENT_SERIALIZER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), 
GDK_TYPE_CONTENT_SERIALIZER))
+#define GDK_CONTENT_SERIALIZER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), 
GDK_TYPE_CONTENT_SERIALIZER, GdkContentSerializerClass))
+
+typedef struct _GdkContentSerializerClass GdkContentSerializerClass;
+
+struct _GdkContentSerializer
+{
+  GObject parent_instance;
+
+  const char *mime_type; /* interned */
+  GValue value;
+  GOutputStream *stream;
+  int priority;
+  GCancellable *cancellable;
+  gpointer user_data;
+  GAsyncReadyCallback callback;
+  gpointer callback_data;
+
+  GError *error;
+  gboolean returned;
+};
+
+struct _GdkContentSerializerClass
+{
+  GObjectClass parent_class;
+};
+
+static gpointer
+gdk_content_serializer_async_result_get_user_data (GAsyncResult *res)
+{
+  return GDK_CONTENT_SERIALIZER (res)->callback_data;
+}
+
+static GObject *
+gdk_content_serializer_async_result_get_source_object (GAsyncResult *res)
+{
+  return NULL;
+}
+
+static void
+gdk_content_serializer_async_result_iface_init (GAsyncResultIface *iface)
+{
+  iface->get_user_data = gdk_content_serializer_async_result_get_user_data;
+  iface->get_source_object = gdk_content_serializer_async_result_get_source_object;
+}
+
+G_DEFINE_TYPE_WITH_CODE (GdkContentSerializer, gdk_content_serializer, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_RESULT, 
gdk_content_serializer_async_result_iface_init))
+
+static void
+gdk_content_serializer_finalize (GObject *object)
+{
+  GdkContentSerializer *serializer = GDK_CONTENT_SERIALIZER (object);
+
+  g_value_unset (&serializer->value);
+  g_clear_object (&serializer->stream);
+  g_clear_object (&serializer->cancellable);
+  g_clear_error (&serializer->error);
+
+  G_OBJECT_CLASS (gdk_content_serializer_parent_class)->finalize (object);
+}
+
+static void
+gdk_content_serializer_class_init (GdkContentSerializerClass *content_serializer_class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (content_serializer_class);
+
+  object_class->finalize = gdk_content_serializer_finalize;
+}
+
+static void
+gdk_content_serializer_init (GdkContentSerializer *content_serializer)
+{
+}
+
+static void
+gdk_content_serializer_run (const char              *mime_type,
+                            const GValue            *value,
+                            GOutputStream           *stream,
+                            int                      priority,
+                            GCancellable            *cancellable,
+                            GdkContentSerializeFunc  serialize_func,
+                            gpointer                 user_data,
+                            GAsyncReadyCallback      callback,
+                            gpointer                 callback_data)
+{
+  GdkContentSerializer *serializer;
+
+  serializer = g_object_new (GDK_TYPE_CONTENT_SERIALIZER, NULL);
+
+  serializer->mime_type = mime_type;
+  g_value_init (&serializer->value, G_VALUE_TYPE (value));
+  g_value_copy (value, &serializer->value);
+  serializer->stream = g_object_ref (stream);
+  serializer->priority = priority;
+  if (cancellable)
+    serializer->cancellable = g_object_ref (cancellable);
+  serializer->user_data = user_data;
+  serializer->callback = callback;
+  serializer->callback_data = callback_data;
+
+  serialize_func (serializer);
+}
+
+const char *
+gdk_content_serializer_get_mime_type (GdkContentSerializer *serializer)
+{
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer), NULL);
+
+  return serializer->mime_type;
+}
+
+GType
+gdk_content_serializer_get_gtype (GdkContentSerializer *serializer)
+{
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer), G_TYPE_INVALID);
+
+  return G_VALUE_TYPE (&serializer->value);
+}
+
+const GValue *
+gdk_content_serializer_get_value (GdkContentSerializer *serializer)
+{
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer), NULL);
+
+  return &serializer->value;
+}
+
+GOutputStream *
+gdk_content_serializer_get_output_stream (GdkContentSerializer *serializer)
+{
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer), NULL);
+
+  return serializer->stream;
+}
+
+int
+gdk_content_serializer_get_priority (GdkContentSerializer *serializer)
+{
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer), G_PRIORITY_DEFAULT);
+
+  return serializer->priority;
+}
+
+GCancellable *
+gdk_content_serializer_get_cancellable (GdkContentSerializer *serializer)
+{
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer), NULL);
+
+  return serializer->cancellable;
+}
+
+gpointer
+gdk_content_serializer_get_user_data (GdkContentSerializer *serializer)
+{
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer), NULL);
+
+  return serializer->user_data;
+}
+
+static gboolean
+gdk_content_serializer_emit_callback (gpointer data)
+{
+  GdkContentSerializer *serializer = data;
+
+  if (serializer->callback)
+    {
+      serializer->callback (NULL, G_ASYNC_RESULT (serializer), serializer->callback_data);
+    }
+
+  return G_SOURCE_REMOVE;
+}
+
+void
+gdk_content_serializer_return_success (GdkContentSerializer *serializer)
+{
+  g_return_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer));
+  g_return_if_fail (!serializer->returned);
+
+  serializer->returned = TRUE;
+  g_idle_add_full (serializer->priority,
+                   gdk_content_serializer_emit_callback,
+                   serializer,
+                   g_object_unref);
+  /* NB: the idle will destroy our reference */
+}
+
+void
+gdk_content_serializer_return_error (GdkContentSerializer *serializer,
+                                     GError               *error)
+{
+  g_return_if_fail (GDK_IS_CONTENT_SERIALIZER (serializer));
+  g_return_if_fail (!serializer->returned);
+  g_return_if_fail (error != NULL);
+
+  serializer->error = error;
+  /* FIXME: naming */
+  gdk_content_serializer_return_success (serializer);
+}
+
+void
+gdk_content_register_serializer (GType                    type,
+                                 const char              *mime_type,
+                                 GdkContentSerializeFunc  serialize,
+                                 gpointer                 data,
+                                 GDestroyNotify           notify)
+{
+  Serializer *serializer;
+
+  g_return_if_fail (mime_type != NULL);
+  g_return_if_fail (serialize != NULL);
+
+  init ();
+
+  serializer = g_slice_new0 (Serializer);
+
+  serializer->mime_type = g_intern_string (mime_type);
+  serializer->type = type;
+  serializer->serialize = serialize;
+  serializer->data = data;
+  serializer->notify = notify;
+
+  g_queue_push_tail (&serializers, serializer);
+}
+
+static Serializer *
+lookup_serializer (const char *mime_type,
+                   GType       type)
+{
+  GList *l;
+
+  g_return_val_if_fail (mime_type != NULL, NULL);
+
+  init ();
+
+  mime_type = g_intern_string (mime_type);
+
+  for (l = g_queue_peek_head_link (&serializers); l; l = l->next)
+    {
+      Serializer *serializer = l->data;
+
+      if (serializer->mime_type == mime_type &&
+          serializer->type == type)
+        return serializer;
+    }
+  
+  return NULL;
+}
+
+GdkContentFormats *
+gdk_content_formats_union_serialize_gtypes (GdkContentFormats *formats)
+{
+  GdkContentFormatsBuilder *builder;
+  GList *l;
+
+  g_return_val_if_fail (formats != NULL, NULL);
+
+  init ();
+
+  builder = gdk_content_formats_builder_new ();
+  gdk_content_formats_builder_add_formats (builder, formats);
+
+  for (l = g_queue_peek_head_link (&serializers); l; l = l->next)
+    {
+      Serializer *serializer = l->data;
+
+      if (gdk_content_formats_contain_mime_type (formats, serializer->mime_type))
+        gdk_content_formats_builder_add_gtype (builder, serializer->type);
+    }
+
+  gdk_content_formats_unref (formats);
+
+  return gdk_content_formats_builder_free (builder);
+}
+
+GdkContentFormats *
+gdk_content_formats_union_serialize_mime_types (GdkContentFormats *formats)
+{
+  GdkContentFormatsBuilder *builder;
+  GList *l;
+
+  g_return_val_if_fail (formats != NULL, NULL);
+
+  init ();
+
+  builder = gdk_content_formats_builder_new ();
+  gdk_content_formats_builder_add_formats (builder, formats);
+
+  for (l = g_queue_peek_head_link (&serializers); l; l = l->next)
+    {
+      Serializer *serializer = l->data;
+
+      if (gdk_content_formats_contain_gtype (formats, serializer->type))
+        gdk_content_formats_builder_add_mime_type (builder, serializer->mime_type);
+    }
+
+  gdk_content_formats_unref (formats);
+
+  return gdk_content_formats_builder_free (builder);
+}
+
+static void
+serialize_not_found (GdkContentSerializer *serializer)
+{
+  GError *error = g_error_new (G_IO_ERROR,
+                               G_IO_ERROR_NOT_FOUND,
+                               "Could not convert data from %s to %s",
+                               g_type_name (gdk_content_serializer_get_gtype (serializer)),
+                               gdk_content_serializer_get_mime_type (serializer));
+  gdk_content_serializer_return_error (serializer, error);
+}
+
+void
+gdk_content_serialize_async (GOutputStream       *stream,
+                             const char          *mime_type,
+                             const GValue        *value,
+                             int                  io_priority,
+                             GCancellable        *cancellable,
+                             GAsyncReadyCallback  callback,
+                             gpointer             user_data)
+{
+  Serializer *serializer;
+
+  g_return_if_fail (G_IS_OUTPUT_STREAM (stream));
+  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+  g_return_if_fail (callback != NULL);
+
+  serializer = lookup_serializer (mime_type, G_VALUE_TYPE (value));
+
+  gdk_content_serializer_run (mime_type,
+                              value,
+                              stream,
+                              io_priority,
+                              cancellable,
+                              serializer ? serializer->serialize : serialize_not_found,
+                              serializer ? serializer->data : NULL,
+                              callback,
+                              user_data);
+}
+
+gboolean
+gdk_content_serialize_finish (GAsyncResult  *result,
+                              GError       **error)
+{
+  GdkContentSerializer *serializer;
+
+  g_return_val_if_fail (GDK_IS_CONTENT_SERIALIZER (result), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  serializer = GDK_CONTENT_SERIALIZER (result);
+
+  if (serializer->error)
+    {
+      if (error)
+        *error = g_error_copy (serializer->error);
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+/*** SERIALIZERS ***/
+
+static void
+pixbuf_serializer_finish (GObject      *source,
+                          GAsyncResult *res,
+                          gpointer      serializer)
+{
+  GError *error = NULL;
+
+  if (!gdk_pixbuf_save_to_stream_finish (res, &error))
+    gdk_content_serializer_return_error (serializer, error);
+  else
+    gdk_content_serializer_return_success (serializer);
+}
+
+static void
+pixbuf_serializer (GdkContentSerializer *serializer)
+{
+  const char *name = gdk_content_serializer_get_user_data (serializer);
+
+  gdk_pixbuf_save_to_stream_async (g_value_get_object (gdk_content_serializer_get_value (serializer)),
+                                   gdk_content_serializer_get_output_stream (serializer),
+                                   name,
+                                  gdk_content_serializer_get_cancellable (serializer),
+                                   pixbuf_serializer_finish,
+                                   serializer,
+                                   g_str_equal (name, "png") ? "compression" : NULL, "2",
+                                   NULL);
+}
+
+static void
+string_serializer_finish (GObject      *source,
+                          GAsyncResult *result,
+                          gpointer      serializer)
+{
+  GOutputStream *stream = G_OUTPUT_STREAM (source);
+  GError *error = NULL;
+
+  if (!g_output_stream_write_all_finish (stream, result, NULL, &error))
+    gdk_content_serializer_return_error (serializer, error);
+  else
+    gdk_content_serializer_return_success (serializer);
+}
+
+static void
+string_serializer (GdkContentSerializer *serializer)
+{
+  GOutputStream *filter;
+  GCharsetConverter *converter;
+  GError *error = NULL;
+  const char *text;
+
+  converter = g_charset_converter_new (gdk_content_serializer_get_user_data (serializer),
+                                       "utf-8",
+                                       &error);
+  if (converter == NULL)
+    {
+      gdk_content_serializer_return_error (serializer, error);
+      return;
+    }
+  g_charset_converter_set_use_fallback (converter, TRUE);
+
+  filter = g_converter_output_stream_new (gdk_content_serializer_get_output_stream (serializer),
+                                          G_CONVERTER (converter));
+  g_object_unref (converter);
+
+  text = g_value_get_string (gdk_content_serializer_get_value (serializer));
+  if (text == NULL)
+    text = "";
+
+  g_output_stream_write_all_async (filter,
+                                   text,
+                                   strlen (text) + 1,
+                                   gdk_content_serializer_get_priority (serializer),
+                                   gdk_content_serializer_get_cancellable (serializer),
+                                   string_serializer_finish,
+                                   serializer);
+  g_object_unref (filter);
+}
+
+static void
+init (void)
+{
+  static gboolean initialized = FALSE;
+  GSList *formats, *f;
+  const char *charset;
+
+  if (initialized)
+    return;
+
+  initialized = TRUE;
+
+  formats = gdk_pixbuf_get_formats ();
+
+  /* Make sure png comes first */
+  for (f = formats; f; f = f->next)
+    {
+      GdkPixbufFormat *fmt = f->data;
+      gchar *name; 
+ 
+      name = gdk_pixbuf_format_get_name (fmt);
+      if (g_str_equal (name, "png"))
+       {
+         formats = g_slist_delete_link (formats, f);
+         formats = g_slist_prepend (formats, fmt);
+
+         g_free (name);
+
+         break;
+       }
+
+      g_free (name);
+    }  
+
+  for (f = formats; f; f = f->next)
+    {
+      GdkPixbufFormat *fmt = f->data;
+      gchar **mimes, **m;
+
+      if (!gdk_pixbuf_format_is_writable (fmt))
+       continue;
+
+      mimes = gdk_pixbuf_format_get_mime_types (fmt);
+      for (m = mimes; *m; m++)
+       {
+          gdk_content_register_serializer (GDK_TYPE_PIXBUF,
+                                           *m,
+                                           pixbuf_serializer,
+                                           g_strdup (gdk_pixbuf_format_get_name (fmt)),
+                                           g_free);
+       }
+      g_strfreev (mimes);
+    }
+
+  g_slist_free (formats);
+
+  gdk_content_register_serializer (G_TYPE_STRING,
+                                   "text/plain;charset=utf-8",
+                                   string_serializer,
+                                   (gpointer) "utf-8",
+                                   NULL);
+  if (!g_get_charset (&charset))
+    {
+      char *mime = g_strdup_printf ("text/plain;charset=%s", charset);
+      gdk_content_register_serializer (G_TYPE_STRING,
+                                       mime,
+                                       string_serializer,
+                                       mime,
+                                       g_free);
+    }
+  gdk_content_register_serializer (G_TYPE_STRING,
+                                   "text/plain",
+                                   string_serializer,
+                                   (gpointer) "ASCII",
+                                   NULL);
+}
+
diff --git a/gdk/gdkcontentserializer.h b/gdk/gdkcontentserializer.h
new file mode 100644
index 0000000..b1acf7f
--- /dev/null
+++ b/gdk/gdkcontentserializer.h
@@ -0,0 +1,90 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2017 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_CONTENT_SERIALIZER_H__
+#define __GTK_CONTENT_SERIALIZER_H__
+
+#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+
+#include <gdk/gdkversionmacros.h>
+#include <gdk/gdktypes.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_CONTENT_SERIALIZER         (gdk_content_serializer_get_type ())
+#define GDK_CONTENT_SERIALIZER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GDK_TYPE_CONTENT_SERIALIZER, 
GdkContentSerializer))
+#define GDK_IS_CONTENT_SERIALIZER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDK_TYPE_CONTENT_SERIALIZER))
+
+typedef struct _GdkContentSerializer GdkContentSerializer;
+
+typedef void (* GdkContentSerializeFunc) (GdkContentSerializer *serializer);
+
+GDK_AVAILABLE_IN_3_94
+GType                   gdk_content_serializer_get_type                 (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_94
+const char *            gdk_content_serializer_get_mime_type            (GdkContentSerializer   *serializer);
+GDK_AVAILABLE_IN_3_94
+GType                   gdk_content_serializer_get_gtype                (GdkContentSerializer   *serializer);
+GDK_AVAILABLE_IN_3_94
+const GValue *          gdk_content_serializer_get_value                (GdkContentSerializer   *serializer);
+GDK_AVAILABLE_IN_3_94
+GOutputStream *         gdk_content_serializer_get_output_stream        (GdkContentSerializer   *serializer);
+GDK_AVAILABLE_IN_3_94
+int                     gdk_content_serializer_get_priority             (GdkContentSerializer   *serializer);
+GDK_AVAILABLE_IN_3_94
+GCancellable *          gdk_content_serializer_get_cancellable          (GdkContentSerializer   *serializer);
+GDK_AVAILABLE_IN_3_94
+gpointer                gdk_content_serializer_get_user_data            (GdkContentSerializer   *serializer);
+
+GDK_AVAILABLE_IN_3_94
+void                    gdk_content_serializer_return_success           (GdkContentSerializer   *serializer);
+GDK_AVAILABLE_IN_3_94
+void                    gdk_content_serializer_return_error             (GdkContentSerializer   *serializer,
+                                                                         GError                 *error);
+
+GDK_AVAILABLE_IN_3_94
+GdkContentFormats *     gdk_content_formats_union_serialize_gtypes      (GdkContentFormats      *formats);
+GDK_AVAILABLE_IN_3_94
+GdkContentFormats *     gdk_content_formats_union_serialize_mime_types  (GdkContentFormats      *formats);
+
+GDK_AVAILABLE_IN_3_94
+void                    gdk_content_register_serializer                 (GType                   type,
+                                                                         const char             *mime_type,
+                                                                         GdkContentSerializeFunc serialize,
+                                                                         gpointer                data,
+                                                                         GDestroyNotify          notify);
+GDK_AVAILABLE_IN_3_94
+void                    gdk_content_serialize_async                     (GOutputStream          *stream,
+                                                                         const char             *mime_type,
+                                                                         const GValue           *value,
+                                                                         int                     io_priority,
+                                                                         GCancellable           *cancellable,
+                                                                         GAsyncReadyCallback     callback,
+                                                                         gpointer                user_data);
+GDK_AVAILABLE_IN_3_94
+gboolean                gdk_content_serialize_finish                    (GAsyncResult           *result,
+                                                                         GError                **error);
+
+
+G_END_DECLS
+
+#endif /* __GDK_CONTENT_SERIALIZER_H__ */
diff --git a/gdk/meson.build b/gdk/meson.build
index b13e9c7..90f8001 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -7,6 +7,7 @@ gdk_public_sources = files([
   'gdkcontentformats.c',
   'gdkcontentprovider.c',
   'gdkcontentproviderimpl.c',
+  'gdkcontentserializer.c',
   'gdkcursor.c',
   'gdkdevice.c',
   'gdkdevicepad.c',
@@ -51,6 +52,7 @@ gdk_public_headers = files([
   'gdkcontentformats.h',
   'gdkcontentprovider.h',
   'gdkcontentproviderimpl.h',
+  'gdkcontentserializer.h',
   'gdkcursor.h',
   'gdkdevice.h',
   'gdkdevicepad.h',


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