gtk4/gtkmm.patch

424 lines
15 KiB
Diff

From 2cbe094b919442471b54685a0fef0d6f83ce44b3 Mon Sep 17 00:00:00 2001
From: Emmanuele Bassi <ebassi@gnome.org>
Date: Thu, 1 Feb 2018 17:43:15 +0100
Subject: [PATCH] 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/
---
docs/reference/gdk/gdk4-sections.txt | 7 ++++++-
gdk/gdkclipboard.c | 2 +-
gdk/gdkcontentdeserializer.c | 4 ++--
gdk/gdkcontentformats.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
gdk/gdkcontentformats.h | 15 +++++++++++++--
gdk/gdkcontentproviderimpl.c | 2 +-
gdk/gdkcontentserializer.c | 4 ++--
gdk/wayland/gdkprimary-wayland.c | 4 ++--
gdk/wayland/gdkselection-wayland.c | 2 +-
gdk/win32/gdkdnd-win32.c | 2 +-
gdk/x11/gdkclipboard-x11.c | 2 +-
gtk/gtkselection.c | 6 +++---
12 files changed, 138 insertions(+), 27 deletions(-)
diff --git a/docs/reference/gdk/gdk4-sections.txt b/docs/reference/gdk/gdk4-sections.txt
index d492279..cf58129 100644
--- a/docs/reference/gdk/gdk4-sections.txt
+++ b/docs/reference/gdk/gdk4-sections.txt
@@ -438,11 +438,16 @@ gdk_content_formats_union_deserialize_mime_types
<SUBSECTION>
GdkContentFormatsBuilder
gdk_content_formats_builder_new
-gdk_content_formats_builder_free
+gdk_content_formats_builder_free_to_formats
gdk_content_formats_builder_add_formats
gdk_content_formats_builder_add_gtype
gdk_content_formats_builder_add_mime_type
+<SUBSECTION>
+gdk_content_formats_builder_ref
+gdk_content_formats_builder_unref
+gdk_content_formats_builder_to_formats
+
<SUBSECTION Private>
GDK_TYPE_FILE_LIST
gdk_file_list_get_type
diff --git a/gdk/gdkclipboard.c b/gdk/gdkclipboard.c
index ee9d8e9..df82147 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 c9df08d..b0df54c 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 04bd064..cd3293f 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 58bbb10..a383434 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 9ae14e0..e7b70c2 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 843c613..92cbb2d 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 89f02e6..62a6941 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 0db6bad..9f7826e 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 190386c..1d844a8 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 02a0b4e..c7b3780 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
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c
index 66dbd02..5dc56a7 100644
--- a/gtk/gtkselection.c
+++ b/gtk/gtkselection.c
@@ -176,7 +176,7 @@ gtk_content_formats_add_text_targets (GdkContentFormats *list)
gdk_content_formats_builder_add_mime_type (builder, text_plain_locale_atom);
gdk_content_formats_builder_add_mime_type (builder, text_plain_atom);
- return gdk_content_formats_builder_free (builder);
+ return gdk_content_formats_builder_free_to_formats (builder);
}
/**
@@ -243,7 +243,7 @@ gtk_content_formats_add_image_targets (GdkContentFormats *list,
g_slist_free (formats);
- return gdk_content_formats_builder_free (builder);
+ return gdk_content_formats_builder_free_to_formats (builder);
}
/**
@@ -270,7 +270,7 @@ gtk_content_formats_add_uri_targets (GdkContentFormats *list)
gdk_content_formats_builder_add_mime_type (builder, text_uri_list_atom);
- return gdk_content_formats_builder_free (builder);
+ return gdk_content_formats_builder_free_to_formats (builder);
}
/**
--
libgit2 0.26.0