diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2018-02-01 17:43:15 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2018-02-03 16:24:13 +0100 |
commit | 2cbe094b919442471b54685a0fef0d6f83ce44b3 (patch) | |
tree | 187a9b099feed2d2da8bcc14885ab1701fc92a95 /gdk | |
parent | 4fa4b8525e62c711e6a7c10f25d5015428b2fa27 (diff) | |
download | gtk+-2cbe094b919442471b54685a0fef0d6f83ce44b3.tar.gz |
Allow binding GdkContentFormatsBuilder
GdkContentFormatsBuilder is currently not introspectable, as it does not
have a GType. We can turn it into a boxed type, but we need to implement
memory management for it.
The current gdk_content_formats_builder_free() function returns a newly
constructed value, so we cannot use it as a GBoxedFreeFunc; additionally
copying a GdkContentFormatsBuilder contents would make it a bit odd, as
you could get multiple identical GdkContentFormats out of the copies.
A simple approach is to model the GdkContentFormatsBuilder API to follow
the GBytes one: use reference counting for memory management, and have
a function to release a reference, return a GdkContentFormats, and reset
the GdkContentFormatsBuilder state.
For language bindings, we can provide a get_formats() function that
returns the GdkContentFormats instance and resets the builder instance,
leaving the reference count untouched.
For C convenience we can keep gdk_content_formats_builder_free(), and
make it a wrapper around gdk_content_formats_builder_get_formats(), with
the guarantee that it'll free the builder instance regardless of its
current reference count.
https://bugzilla.gnome.org/show_bug.cgi?id=793097
https://blogs.gnome.org/otte/2018/02/03/builders/
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/gdkclipboard.c | 2 | ||||
-rw-r--r-- | gdk/gdkcontentdeserializer.c | 4 | ||||
-rw-r--r-- | gdk/gdkcontentformats.c | 115 | ||||
-rw-r--r-- | gdk/gdkcontentformats.h | 15 | ||||
-rw-r--r-- | gdk/gdkcontentproviderimpl.c | 2 | ||||
-rw-r--r-- | gdk/gdkcontentserializer.c | 4 | ||||
-rw-r--r-- | gdk/wayland/gdkprimary-wayland.c | 4 | ||||
-rw-r--r-- | gdk/wayland/gdkselection-wayland.c | 2 | ||||
-rw-r--r-- | gdk/win32/gdkdnd-win32.c | 2 | ||||
-rw-r--r-- | gdk/x11/gdkclipboard-x11.c | 2 |
10 files changed, 129 insertions, 23 deletions
diff --git a/gdk/gdkclipboard.c b/gdk/gdkclipboard.c index ee9d8e991b..df821477f2 100644 --- a/gdk/gdkclipboard.c +++ b/gdk/gdkclipboard.c @@ -820,7 +820,7 @@ gdk_clipboard_read_value_internal (GdkClipboard *clipboard, builder = gdk_content_formats_builder_new (); gdk_content_formats_builder_add_gtype (builder, type); - formats = gdk_content_formats_builder_free (builder); + formats = gdk_content_formats_builder_free_to_formats (builder); formats = gdk_content_formats_union_deserialize_mime_types (formats); gdk_clipboard_read_internal (clipboard, diff --git a/gdk/gdkcontentdeserializer.c b/gdk/gdkcontentdeserializer.c index c9df08dba9..b0df54cb12 100644 --- a/gdk/gdkcontentdeserializer.c +++ b/gdk/gdkcontentdeserializer.c @@ -458,7 +458,7 @@ gdk_content_formats_union_deserialize_gtypes (GdkContentFormats *formats) gdk_content_formats_unref (formats); - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } /** @@ -493,7 +493,7 @@ gdk_content_formats_union_deserialize_mime_types (GdkContentFormats *formats) gdk_content_formats_unref (formats); - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } static void diff --git a/gdk/gdkcontentformats.c b/gdk/gdkcontentformats.c index 04bd0647f4..cd3293f0a3 100644 --- a/gdk/gdkcontentformats.c +++ b/gdk/gdkcontentformats.c @@ -307,7 +307,7 @@ gdk_content_formats_union (GdkContentFormats *first, gdk_content_formats_unref (first); gdk_content_formats_builder_add_formats (builder, second); - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } static gboolean @@ -510,12 +510,22 @@ gdk_content_formats_get_mime_types (GdkContentFormats *formats, struct _GdkContentFormatsBuilder { + int ref_count; + + /* (element-type GType) */ GSList *gtypes; gsize n_gtypes; + + /* (element-type utf8) (interned) */ GSList *mime_types; gsize n_mime_types; }; +G_DEFINE_BOXED_TYPE (GdkContentFormatsBuilder, + gdk_content_formats_builder, + gdk_content_formats_builder_ref, + gdk_content_formats_builder_unref) + /** * gdk_content_formats_builder_new: * @@ -528,19 +538,106 @@ struct _GdkContentFormatsBuilder GdkContentFormatsBuilder * gdk_content_formats_builder_new (void) { - return g_slice_new0 (GdkContentFormatsBuilder); + GdkContentFormatsBuilder *builder; + + builder = g_slice_new0 (GdkContentFormatsBuilder); + builder->ref_count = 1; + + return builder; } /** - * gdk_content_formats_builder_free: + * gdk_content_formats_builder_ref: * @builder: a #GdkContentFormatsBuilder * - * Frees @builder and creates a new #GdkContentFormats from it. + * Acquires a reference on the given @builder. * - * Returns: a new #GdkContentFormats with all the formats added to @builder - **/ + * This function is intended primarily for bindings. #GdkContentFormatsBuilder objects + * should not be kept around. + * + * Returns: (transfer none): the given #GdkContentFormatsBuilder with + * its reference count increased + */ +GdkContentFormatsBuilder * +gdk_content_formats_builder_ref (GdkContentFormatsBuilder *builder) +{ + g_return_val_if_fail (builder != NULL, NULL); + g_return_val_if_fail (builder->ref_count > 0, NULL); + + builder->ref_count += 1; + + return builder; +} + +static void +gdk_content_formats_builder_clear (GdkContentFormatsBuilder *builder) +{ + g_clear_pointer (&builder->gtypes, g_slist_free); + g_clear_pointer (&builder->mime_types, g_slist_free); +} + +/** + * gdk_content_formats_builder_unref: + * @builder: a #GdkContentFormatsBuilder + * + * Releases a reference on the given @builder. + */ +void +gdk_content_formats_builder_unref (GdkContentFormatsBuilder *builder) +{ + g_return_if_fail (builder != NULL); + g_return_if_fail (builder->ref_count > 0); + + builder->ref_count -= 1; + + if (builder->ref_count > 0) + return; + + gdk_content_formats_builder_clear (builder); + g_slice_free (GdkContentFormatsBuilder, builder); +} + +/** + * gdk_content_formats_builder_free_to_formats: (skip) + * @builder: a #GdkContentFormatsBuilder + * + * Creates a new #GdkContentFormats from the current state of the + * given @builder, and frees the @builder instance. + * + * Returns: (transfer full): the newly created #GdkContentFormats + * with all the formats added to @builder + */ +GdkContentFormats * +gdk_content_formats_builder_free_to_formats (GdkContentFormatsBuilder *builder) +{ + GdkContentFormats *res; + + g_return_val_if_fail (builder != NULL, NULL); + + res = gdk_content_formats_builder_to_formats (builder); + + gdk_content_formats_builder_unref (builder); + + return res; +} + +/** + * gdk_content_formats_builder_to_formats: + * @builder: a #GdkContentFormatsBuilder + * + * Creates a new #GdkContentFormats from the given @builder. + * + * The given #GdkContentFormatsBuilder is reset once this function returns; + * you cannot call this function multiple times on the same @builder instance. + * + * This function is intended primarily for bindings. C code should use + * gdk_content_formats_builder_free_to_formats(). + * + * Returns: (transfer full): the newly created #GdkContentFormats + * with all the formats added to @builder + */ GdkContentFormats * -gdk_content_formats_builder_free (GdkContentFormatsBuilder *builder) +gdk_content_formats_builder_to_formats (GdkContentFormatsBuilder *builder) { GdkContentFormats *result; GType *gtypes; @@ -567,9 +664,7 @@ gdk_content_formats_builder_free (GdkContentFormatsBuilder *builder) result = gdk_content_formats_new_take (gtypes, builder->n_gtypes, mime_types, builder->n_mime_types); - g_slist_free (builder->gtypes); - g_slist_free (builder->mime_types); - g_slice_free (GdkContentFormatsBuilder, builder); + gdk_content_formats_builder_clear (builder); return result; } diff --git a/gdk/gdkcontentformats.h b/gdk/gdkcontentformats.h index 58bbb103fd..a3834344f4 100644 --- a/gdk/gdkcontentformats.h +++ b/gdk/gdkcontentformats.h @@ -77,12 +77,23 @@ GDK_AVAILABLE_IN_3_94 gboolean gdk_content_formats_contain_mime_type (const GdkContentFormats *formats, const char *mime_type); +#define GDK_TYPE_CONTENT_FORMATS_BUILDER (gdk_content_formats_builder_get_type ()) + typedef struct _GdkContentFormatsBuilder GdkContentFormatsBuilder; GDK_AVAILABLE_IN_3_94 -GdkContentFormatsBuilder*gdk_content_formats_builder_new (void); +GType gdk_content_formats_builder_get_type (void) G_GNUC_CONST; + +GDK_AVAILABLE_IN_3_94 +GdkContentFormatsBuilder *gdk_content_formats_builder_new (void); +GDK_AVAILABLE_IN_3_94 +GdkContentFormatsBuilder *gdk_content_formats_builder_ref (GdkContentFormatsBuilder *builder); +GDK_AVAILABLE_IN_3_94 +void gdk_content_formats_builder_unref (GdkContentFormatsBuilder *builder); +GDK_AVAILABLE_IN_3_94 +GdkContentFormats * gdk_content_formats_builder_free_to_formats (GdkContentFormatsBuilder *builder) G_GNUC_WARN_UNUSED_RESULT; GDK_AVAILABLE_IN_3_94 -GdkContentFormats * gdk_content_formats_builder_free (GdkContentFormatsBuilder *builder) G_GNUC_WARN_UNUSED_RESULT; +GdkContentFormats * gdk_content_formats_builder_to_formats (GdkContentFormatsBuilder *builder) G_GNUC_WARN_UNUSED_RESULT; GDK_AVAILABLE_IN_3_94 void gdk_content_formats_builder_add_formats (GdkContentFormatsBuilder *builder, const GdkContentFormats *formats); diff --git a/gdk/gdkcontentproviderimpl.c b/gdk/gdkcontentproviderimpl.c index 9ae14e0a40..e7b70c28ab 100644 --- a/gdk/gdkcontentproviderimpl.c +++ b/gdk/gdkcontentproviderimpl.c @@ -168,7 +168,7 @@ gdk_content_provider_bytes_ref_formats (GdkContentProvider *provider) builder = gdk_content_formats_builder_new (); gdk_content_formats_builder_add_mime_type (builder, content->mime_type); - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } static void diff --git a/gdk/gdkcontentserializer.c b/gdk/gdkcontentserializer.c index 843c613485..92cbb2df6b 100644 --- a/gdk/gdkcontentserializer.c +++ b/gdk/gdkcontentserializer.c @@ -461,7 +461,7 @@ gdk_content_formats_union_serialize_gtypes (GdkContentFormats *formats) gdk_content_formats_unref (formats); - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } /** @@ -496,7 +496,7 @@ gdk_content_formats_union_serialize_mime_types (GdkContentFormats *formats) gdk_content_formats_unref (formats); - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } static void diff --git a/gdk/wayland/gdkprimary-wayland.c b/gdk/wayland/gdkprimary-wayland.c index 89f02e65ff..62a6941db2 100644 --- a/gdk/wayland/gdkprimary-wayland.c +++ b/gdk/wayland/gdkprimary-wayland.c @@ -58,7 +58,7 @@ gdk_wayland_primary_discard_pending (GdkWaylandPrimary *cb) { if (cb->pending_builder) { - GdkContentFormats *ignore = gdk_content_formats_builder_free (cb->pending_builder); + GdkContentFormats *ignore = gdk_content_formats_builder_free_to_formats (cb->pending_builder); gdk_content_formats_unref (ignore); cb->pending_builder = NULL; } @@ -178,7 +178,7 @@ primary_selection_selection (void *data, return; } - formats = gdk_content_formats_builder_free (cb->pending_builder); + formats = gdk_content_formats_builder_free_to_formats (cb->pending_builder); cb->pending_builder = NULL; cb->pending = NULL; diff --git a/gdk/wayland/gdkselection-wayland.c b/gdk/wayland/gdkselection-wayland.c index 0db6bad4ad..9f7826e1da 100644 --- a/gdk/wayland/gdkselection-wayland.c +++ b/gdk/wayland/gdkselection-wayland.c @@ -124,7 +124,7 @@ data_offer_offer (void *data, gdk_content_formats_builder_add_formats (builder, info->targets); gdk_content_formats_builder_add_mime_type (builder, type); gdk_content_formats_unref (info->targets); - info->targets = gdk_content_formats_builder_free (builder); + info->targets = gdk_content_formats_builder_free_to_formats (builder); } static inline GdkDragAction diff --git a/gdk/win32/gdkdnd-win32.c b/gdk/win32/gdkdnd-win32.c index 190386c25a..1d844a8185 100644 --- a/gdk/win32/gdkdnd-win32.c +++ b/gdk/win32/gdkdnd-win32.c @@ -552,7 +552,7 @@ query_targets (LPDATAOBJECT pDataObj, for (p = g_list_reverse (result); p; p = p->next) gdk_content_formats_builder_add_mime_type (builder, (const gchar *) p->data); - result_formats = gdk_content_formats_builder_free (builder); + result_formats = gdk_content_formats_builder_free_to_formats (builder); g_list_free (result); return result_formats; diff --git a/gdk/x11/gdkclipboard-x11.c b/gdk/x11/gdkclipboard-x11.c index 02a0b4e8ce..c7b3780885 100644 --- a/gdk/x11/gdkclipboard-x11.c +++ b/gdk/x11/gdkclipboard-x11.c @@ -243,7 +243,7 @@ gdk_x11_clipboard_formats_from_atoms (GdkDisplay *display, } } - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } static void |