[gtk/wip/otte/builder: 4/10] builder: Add gtk_builder_create_closure()
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/otte/builder: 4/10] builder: Add gtk_builder_create_closure()
- Date: Fri, 22 Nov 2019 07:14:43 +0000 (UTC)
commit 094c537001c4618aad71e890af937013d06a579a
Author: Benjamin Otte <otte redhat com>
Date: Thu Nov 21 21:20:16 2019 +0100
builder: Add gtk_builder_create_closure()
This will be the future way to connect signals automatically (and be
used for other things, too).
For now, gtk_builder_connect_signals_default() is ported to use it.
docs/reference/gtk/gtk4-sections.txt | 2 +
gtk/gtkbuilder.c | 150 ++++++++++++++++++++++++++++++-----
gtk/gtkbuilder.h | 21 ++++-
3 files changed, 150 insertions(+), 23 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 04bf68f83b..c9fefcebf1 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -529,6 +529,8 @@ gtk_builder_new_from_string
gtk_builder_add_callback_symbol
gtk_builder_add_callback_symbols
gtk_builder_lookup_callback_symbol
+gtk_builder_create_closure
+gtk_builder_create_cclosure
gtk_builder_add_from_file
gtk_builder_add_from_resource
gtk_builder_add_from_string
diff --git a/gtk/gtkbuilder.c b/gtk/gtkbuilder.c
index 5538ecfe8c..5c00a50570 100644
--- a/gtk/gtkbuilder.c
+++ b/gtk/gtkbuilder.c
@@ -1658,31 +1658,23 @@ gtk_builder_connect_signals_default (GtkBuilder *builder,
GConnectFlags flags,
gpointer user_data)
{
- GCallback func;
+ GClosure *closure;
+ GError *error = NULL;
- func = gtk_builder_lookup_callback_symbol (builder, handler_name);
+ closure = gtk_builder_create_closure (builder,
+ handler_name,
+ flags & G_CONNECT_SWAPPED ? TRUE : FALSE,
+ connect_object,
+ &error);
- if (!func)
+ if (closure == NULL)
{
- GModule *module = gtk_builder_get_module (builder);
-
- /* Only error out for missing GModule support if we've not
- * found the symbols explicitly added with gtk_builder_add_callback_symbol()
- */
- if (module == NULL)
- g_error ("gtk_builder_connect_signals() requires working GModule");
-
- if (!g_module_symbol (module, handler_name, (gpointer)&func))
- {
- g_warning ("Could not find signal handler '%s'. Did you compile with -rdynamic?", handler_name);
- return;
- }
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return;
}
- if (connect_object)
- g_signal_connect_object (object, signal_name, func, connect_object, flags);
- else
- g_signal_connect_data (object, signal_name, func, user_data, NULL, flags);
+ g_signal_connect_closure (object, signal_name, closure, flags & G_CONNECT_AFTER ? TRUE : FALSE);
}
@@ -2571,7 +2563,7 @@ _gtk_builder_get_template_type (GtkBuilder *builder)
*
* Adds the @callback_symbol to the scope of @builder under the given @callback_name.
*
- * Using this function overrides the behavior of gtk_builder_connect_signals()
+ * Using this function overrides the behavior of gtk_builder_create_closure()
* for any callback symbols that are added. Using this method allows for better
* encapsulation as it does not require that callback symbols be declared in
* the global namespace.
@@ -2666,6 +2658,122 @@ gtk_builder_lookup_callback_symbol (GtkBuilder *builder,
return g_hash_table_lookup (priv->callbacks, callback_name);
}
+static GClosure *
+gtk_builder_create_closure_for_funcptr (GtkBuilder *builder,
+ GCallback callback,
+ gboolean swapped,
+ GObject *object)
+{
+ GClosure *closure;
+
+ if (object)
+ {
+ if (swapped)
+ closure = g_cclosure_new_object_swap (callback, object);
+ else
+ closure = g_cclosure_new_object (callback, object);
+ }
+ else
+ {
+ if (swapped)
+ closure = g_cclosure_new_swap (callback, NULL, NULL);
+ else
+ closure = g_cclosure_new (callback, NULL, NULL);
+ }
+
+ return closure;
+}
+
+/**
+ * gtk_builder_create_closure:
+ * @builder: a #GtkBuilder
+ * @function_name: name of the function to look up
+ * @swapped: %TRUE to create a swapped closure
+ * @object: (nullable): Object to create the closure with
+ * @error: (allow-none): return location for an error, or %NULL
+ *
+ * Creates a closure to invoke the function called @function_name.
+ *
+ * If a closure function was set via gtk_builder_set_closure_func(),
+ * will be invoked.
+ * Otherwise, gtk_builder_create_cclosure() will be called.
+ *
+ * If no closure could be created, %NULL will be returned and @error will
+ * be set.
+ *
+ * Returns: (nullable): A new closure for invoking @function_name
+ **/
+GClosure *
+gtk_builder_create_closure (GtkBuilder *builder,
+ const char *function_name,
+ gboolean swapped,
+ GObject *object,
+ GError **error)
+{
+ g_return_val_if_fail (GTK_IS_BUILDER (builder), NULL);
+ g_return_val_if_fail (function_name, NULL);
+ g_return_val_if_fail (object == NULL || G_IS_OBJECT (object), NULL);
+ g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+ return gtk_builder_create_cclosure (builder, function_name, swapped, object, error);
+}
+
+/**
+ * gtk_builder_create_cclosure: (skip)
+ * @builder: a #GtkBuilder
+ * @function_name: name of the function to look up
+ * @swapped: %TRUE to create a swapped closure
+ * @object: (nullable): Object to create the closure with
+ * @error: (allow-none): return location for an error, or %NULL
+ *
+ * This is the default function used by gtk_builder_set_closure_func(). Some bindings
+ * with C support may want to call this function as a fallback from their closure
+ * function.
+ *
+ * This function has no purpose otherwise.
+ *
+ * This function will prefer callbacks added via gtk_builder_add_callback_symbol()
+ * to looking up public symbols.
+ *
+ * Returns: (nullable): A new closure for invoking @function_name
+ **/
+GClosure *
+gtk_builder_create_cclosure (GtkBuilder *builder,
+ const char *function_name,
+ gboolean swapped,
+ GObject *object,
+ GError **error)
+{
+ GModule *module = gtk_builder_get_module (builder);
+ GCallback func;
+
+ func = gtk_builder_lookup_callback_symbol (builder, function_name);
+ if (func)
+ return gtk_builder_create_closure_for_funcptr (builder, func, swapped, object);
+
+ if (module == NULL)
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_FUNCTION,
+ "Could not look up function `%s`: GModule is not supported.",
+ function_name);
+ return NULL;
+ }
+
+ if (!g_module_symbol (module, function_name, (gpointer)&func))
+ {
+ g_set_error (error,
+ GTK_BUILDER_ERROR,
+ GTK_BUILDER_ERROR_INVALID_FUNCTION,
+ "No function named `%s`.",
+ function_name);
+ return NULL;
+ }
+
+ return gtk_builder_create_closure_for_funcptr (builder, func, swapped, object);
+}
+
/**
* gtk_builder_new_from_file:
* @filename: filename of user interface description file
diff --git a/gtk/gtkbuilder.h b/gtk/gtkbuilder.h
index f3353cedcf..fb192dc4a9 100644
--- a/gtk/gtkbuilder.h
+++ b/gtk/gtkbuilder.h
@@ -63,7 +63,10 @@ typedef struct _GtkBuilderClass GtkBuilderClass;
* @GTK_BUILDER_ERROR_TEMPLATE_MISMATCH: The wrong type was specified in a composite class’s template XML
* @GTK_BUILDER_ERROR_INVALID_PROPERTY: The specified property is unknown for the object class.
* @GTK_BUILDER_ERROR_INVALID_SIGNAL: The specified signal is unknown for the object class.
- * @GTK_BUILDER_ERROR_INVALID_ID: An object id is unknown
+ * @GTK_BUILDER_ERROR_INVALID_ID: An object id is unknown.
+ * @GTK_BUILDER_ERROR_INVALID_FUNCTION: A function could not be found. This often happens
+ * when symbols are set to be kept private. Compiling code with -rdynamic or using the
+ * `gmodule-export-2.0` pkgconfig module can fix this problem.
*
* Error codes that identify various errors that can occur while using
* #GtkBuilder.
@@ -83,7 +86,8 @@ typedef enum
GTK_BUILDER_ERROR_TEMPLATE_MISMATCH,
GTK_BUILDER_ERROR_INVALID_PROPERTY,
GTK_BUILDER_ERROR_INVALID_SIGNAL,
- GTK_BUILDER_ERROR_INVALID_ID
+ GTK_BUILDER_ERROR_INVALID_ID,
+ GTK_BUILDER_ERROR_INVALID_FUNCTION
} GtkBuilderError;
GDK_AVAILABLE_IN_ALL
@@ -196,6 +200,19 @@ void gtk_builder_add_callback_symbols (GtkBuilder *builder,
GDK_AVAILABLE_IN_ALL
GCallback gtk_builder_lookup_callback_symbol (GtkBuilder *builder,
const gchar *callback_name);
+GDK_AVAILABLE_IN_ALL
+GClosure * gtk_builder_create_closure (GtkBuilder *builder,
+ const char *function_name,
+ gboolean swapped,
+ GObject *object,
+ GError **error);
+GDK_AVAILABLE_IN_ALL
+GClosure * gtk_builder_create_cclosure (GtkBuilder *builder,
+ const char *function_name,
+ gboolean swapped,
+ GObject *object,
+ GError **error);
+
/**
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]