forked from AuroraMiddleware/gtk
clipboard: Add serialization
This completes the local clipboard code.
This commit is contained in:
parent
12ca641ff5
commit
25c3895836
@ -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>
|
||||
|
@ -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, >ype, 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
|
||||
{
|
||||
|
562
gdk/gdkcontentserializer.c
Normal file
562
gdk/gdkcontentserializer.c
Normal file
@ -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);
|
||||
}
|
||||
|
90
gdk/gdkcontentserializer.h
Normal file
90
gdk/gdkcontentserializer.h
Normal file
@ -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__ */
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user