diff --git a/gdk/Makefile.am b/gdk/Makefile.am index 11a1109cfd..57e80bd7e6 100644 --- a/gdk/Makefile.am +++ b/gdk/Makefile.am @@ -68,6 +68,7 @@ gdk_public_h_sources = \ gdkapplaunchcontext.h \ gdkcairo.h \ gdkclipboard.h \ + gdkclipboardfallback.h \ gdkcursor.h \ gdkdevice.h \ gdkdevicemanager.h \ @@ -129,6 +130,7 @@ gdk_c_sources = \ gdkapplaunchcontext.c \ gdkcairo.c \ gdkclipboard.c \ + gdkclipboardfallback.c \ gdkcursor.c \ gdkdeprecated.c \ gdkdevice.c \ diff --git a/gdk/gdk.h b/gdk/gdk.h index bdf402d960..ec87425472 100644 --- a/gdk/gdk.h +++ b/gdk/gdk.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include diff --git a/gdk/gdkclipboardfallback.c b/gdk/gdkclipboardfallback.c new file mode 100644 index 0000000000..2d65675873 --- /dev/null +++ b/gdk/gdkclipboardfallback.c @@ -0,0 +1,333 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2014 Red Hat, Inc. + * + * 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 . + */ + +#include "config.h" +#include +#include + + +typedef struct _GdkClipboardFallbackClass GdkClipboardFallbackClass; + +struct _GdkClipboardFallback +{ + GdkClipboard parent; + + gchar *text; + GdkPixbuf *pixbuf; + GdkClipboardProvider provider; + gpointer data; + GDestroyNotify destroy; +}; + +struct _GdkClipboardFallbackClass +{ + GdkClipboardClass parent_class; +}; + +G_DEFINE_TYPE (GdkClipboardFallback, gdk_clipboard_fallback, GDK_TYPE_CLIPBOARD) + +static void +clear_data (GdkClipboardFallback *cf) +{ + if (cf->text) + { + g_free (cf->text); + cf->text = NULL; + } + + if (cf->pixbuf) + { + g_object_unref (cf->pixbuf); + cf->pixbuf = NULL; + } + + if (cf->provider) + { + if (cf->destroy) + cf->destroy (cf->data); + + cf->provider = NULL; + cf->data = NULL; + cf->destroy = NULL; + } +} + +static void +gdk_clipboard_fallback_get_text_async (GdkClipboard *clipboard, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *res; + + res = g_simple_async_result_new (G_OBJECT (clipboard), + callback, user_data, + gdk_clipboard_fallback_get_text_async); + g_simple_async_result_complete (res); + g_object_unref (res); +} + +static gchar * +gdk_clipboard_fallback_get_text_finish (GdkClipboard *clipboard, + GAsyncResult *res, + GError **error) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (clipboard); + + g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (cf), gdk_clipboard_fallback_get_text_async), NULL); + + if (_gdk_clipboard_get_available_content (clipboard) != TEXT_CONTENT) + { + /* FIXME: set error ? */ + return NULL; + } + + return g_strdup (cf->text); +} + +static void +gdk_clipboard_fallback_set_text (GdkClipboard *clipboard, + const gchar *text) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (clipboard); + + clear_data (cf); + cf->text = g_strdup (text); + _gdk_clipboard_set_available_content (clipboard, TEXT_CONTENT, NULL); +} + +static void +gdk_clipboard_fallback_get_image_async (GdkClipboard *clipboard, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *res; + + res = g_simple_async_result_new (G_OBJECT (clipboard), + callback, user_data, + gdk_clipboard_fallback_get_image_async); + g_simple_async_result_complete (res); + g_object_unref (res); +} + +static GdkPixbuf * +gdk_clipboard_fallback_get_image_finish (GdkClipboard *clipboard, + GAsyncResult *res, + GError **error) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (clipboard); + + g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (cf), gdk_clipboard_fallback_get_image_async), NULL); + + if (_gdk_clipboard_get_available_content (clipboard) != IMAGE_CONTENT) + { + /* FIXME: set error ? */ + return NULL; + } + + return g_object_ref (cf->pixbuf); +} + +static void +gdk_clipboard_fallback_set_image (GdkClipboard *clipboard, + GdkPixbuf *pixbuf) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (clipboard); + + clear_data (cf); + cf->pixbuf = g_object_ref (pixbuf); + _gdk_clipboard_set_available_content (clipboard, IMAGE_CONTENT, NULL); +} + +static void +gdk_clipboard_fallback_get_data_async (GdkClipboard *clipboard, + const gchar *content_type, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *res; + + res = g_simple_async_result_new (G_OBJECT (clipboard), + callback, user_data, + gdk_clipboard_fallback_get_data_async); + g_object_set_data (G_OBJECT (res), "ctype", (gpointer) content_type); + g_simple_async_result_complete (res); + g_object_unref (res); +} + +typedef struct +{ + GOutputStream parent; + GMemoryInputStream *is; +} ReadbackOutputStream; + +typedef struct +{ + GOutputStreamClass parent_class; +} ReadbackOutputStreamClass; + +G_DEFINE_TYPE (ReadbackOutputStream, readback_output_stream, G_TYPE_OUTPUT_STREAM) + +static void +readback_output_stream_init (ReadbackOutputStream *stream) +{ +} + +static gssize +readback_output_stream_write (GOutputStream *stream, + const void *buffer, + gsize count, + GCancellable *cancellable, + GError **error) +{ + ReadbackOutputStream *rs = (ReadbackOutputStream *)stream; + + if (count) + g_memory_input_stream_add_data (rs->is, g_memdup (buffer, count), count, g_free); + + return count; +} + +static void +readback_output_stream_finalize (GObject *obj) +{ + ReadbackOutputStream *rs = (ReadbackOutputStream *)obj; + + g_object_unref (rs->is); + + G_OBJECT_CLASS (readback_output_stream_parent_class)->finalize (obj); +} + +static void +readback_output_stream_class_init (ReadbackOutputStreamClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GOutputStreamClass *ostream_class = G_OUTPUT_STREAM_CLASS (class); + + object_class->finalize = readback_output_stream_finalize; + ostream_class->write_fn = readback_output_stream_write; +} + +static GOutputStream * +readback_output_stream_new (GMemoryInputStream *is) +{ + ReadbackOutputStream *stream; + + stream = g_object_new (readback_output_stream_get_type (), NULL); + stream->is = g_object_ref (is); + + return G_OUTPUT_STREAM (stream); +} + +static GInputStream * +gdk_clipboard_fallback_get_data_finish (GdkClipboard *clipboard, + GAsyncResult *res, + GError **error) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (clipboard); + const gchar *ctype; + GOutputStream *ostream = NULL; + GInputStream *istream = NULL; + + g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (cf), gdk_clipboard_fallback_get_data_async), NULL); + + ctype = (const gchar *) g_object_get_data (G_OBJECT (res), "ctype"); + + if (!gdk_clipboard_data_available (clipboard, ctype)) + { + /* FIXME: set error ? */ + return NULL; + } + + istream = g_memory_input_stream_new (); + ostream = readback_output_stream_new (G_MEMORY_INPUT_STREAM (istream)); + + cf->provider (clipboard, ctype, ostream, cf->data); + + g_object_unref (ostream); + + return istream; +} + +static void +gdk_clipboard_fallback_set_data (GdkClipboard *clipboard, + const gchar **content_types, + GdkClipboardProvider provider, + gpointer data, + GDestroyNotify destroy) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (clipboard); + + clear_data (cf); + cf->provider = provider; + cf->data = data; + cf->destroy = destroy; + _gdk_clipboard_set_available_content (clipboard, OTHER_CONTENT, content_types); +} + +static void +gdk_clipboard_fallback_clear (GdkClipboard *clipboard) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (clipboard); + + clear_data (cf); + _gdk_clipboard_set_available_content (clipboard, NO_CONTENT, NULL); +} + +static void +gdk_clipboard_fallback_init (GdkClipboardFallback *clipboard) +{ +} + +static void +gdk_clipboard_fallback_finalize (GObject *object) +{ + GdkClipboardFallback *cf = GDK_CLIPBOARD_FALLBACK (object); + + clear_data (cf); + + G_OBJECT_CLASS (gdk_clipboard_fallback_parent_class)->finalize (object); + +} + +static void +gdk_clipboard_fallback_class_init (GdkClipboardFallbackClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GdkClipboardClass *clipboard_class = GDK_CLIPBOARD_CLASS (class); + + object_class->finalize = gdk_clipboard_fallback_finalize; + + clipboard_class->get_text_async = gdk_clipboard_fallback_get_text_async; + clipboard_class->get_text_finish = gdk_clipboard_fallback_get_text_finish; + clipboard_class->set_text = gdk_clipboard_fallback_set_text; + clipboard_class->get_image_async = gdk_clipboard_fallback_get_image_async; + clipboard_class->get_image_finish = gdk_clipboard_fallback_get_image_finish; + clipboard_class->set_image = gdk_clipboard_fallback_set_image; + clipboard_class->get_data_async = gdk_clipboard_fallback_get_data_async; + clipboard_class->get_data_finish = gdk_clipboard_fallback_get_data_finish; + clipboard_class->set_data = gdk_clipboard_fallback_set_data; + clipboard_class->clear = gdk_clipboard_fallback_clear; +} + +GdkClipboard * +gdk_clipboard_fallback_new (void) +{ + return GDK_CLIPBOARD (g_object_new (GDK_TYPE_CLIPBOARD_FALLBACK, NULL)); +} diff --git a/gdk/gdkclipboardfallback.h b/gdk/gdkclipboardfallback.h new file mode 100644 index 0000000000..6b00d53f73 --- /dev/null +++ b/gdk/gdkclipboardfallback.h @@ -0,0 +1,44 @@ +/* GDK - The GIMP Drawing Kit + * Copyright (C) 2014 Red Hat, Inc. + * + * 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 . + */ + +#ifndef __GDK_CLIPBOARD_FALLBACK_H__ +#define __GDK_CLIPBOARD_FALLBACK_H__ + +#if !defined (__GDK_H_INSIDE__) && !defined (GDK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + + +G_BEGIN_DECLS + +#define GDK_TYPE_CLIPBOARD_FALLBACK (gdk_clipboard_fallback_get_type ()) +#define GDK_CLIPBOARD_FALLBACK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_CLIPBOARD_FALLBACK, GdkClipboardFallback)) +#define GDK_IS_CLIPBOARD_FALLBACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_CLIPBOARD_FALLBACK)) + +typedef struct _GdkClipboardFallback GdkClipboardFallback; + +GDK_AVAILABLE_IN_3_14 +GType gdk_clipboard_fallback_get_type (void) G_GNUC_CONST; + +GDK_AVAILABLE_IN_3_14 +GdkClipboard *gdk_clipboard_fallback_new (void); + +G_END_DECLS + +#endif /* __GDK_CLIPBOARD_FALLBACK_H__ */