[gjs: 2/7] gtk-util: Reimplement with introspection



commit a14df4996edc15b3cff2a182980679678532b481
Author: Florian Müllner <fmuellner gnome org>
Date:   Tue Aug 13 00:23:21 2019 +0200

    gtk-util: Reimplement with introspection
    
    Commit 68b835ca24 added an override for gtk_container_child_set_property()
    to handle NULL values correctly.
    
    That override added a build dependency on GTK3, which nowadays prevents
    people from using GTK4 with gjs. In order to fix that, reimplemment the
    override to look up the needed symbols using introspection information
    instead of directly using the GTK API.
    
    https://gitlab.gnome.org/GNOME/gjs/issues/99

 libgjs-private/gjs-gtk-util.c | 74 +++++++++++++++++++++++++++++++++++--------
 libgjs-private/gjs-gtk-util.h | 14 +++-----
 2 files changed, 65 insertions(+), 23 deletions(-)
---
diff --git a/libgjs-private/gjs-gtk-util.c b/libgjs-private/gjs-gtk-util.c
index 8694a847..2b4ab563 100644
--- a/libgjs-private/gjs-gtk-util.c
+++ b/libgjs-private/gjs-gtk-util.c
@@ -22,24 +22,57 @@
 
 #include <stddef.h>  // for NULL
 
+#include <girepository.h>
 #include <glib-object.h>
 #include <glib.h>
-#include <gtk/gtk.h>
 
 #include "libgjs-private/gjs-gtk-util.h"
 
-void gjs_gtk_container_child_set_property(GtkContainer* container,
-                                          GtkWidget* child,
+static GParamSpec* gjs_gtk_container_class_find_child_property(
+    GIObjectInfo* container_info, GObject* container, const char* property) {
+    GIBaseInfo* class_info = NULL;
+    GIBaseInfo* find_child_property_fun = NULL;
+
+    GIArgument ret;
+    GIArgument find_child_property_args[2];
+
+    class_info = g_object_info_get_class_struct(container_info);
+    find_child_property_fun =
+        g_struct_info_find_method(class_info, "find_child_property");
+
+    find_child_property_args[0].v_pointer = G_OBJECT_GET_CLASS(container);
+    find_child_property_args[1].v_string = (char*)property;
+
+    g_function_info_invoke(find_child_property_fun, find_child_property_args, 2,
+                           NULL, 0, &ret, NULL);
+
+    g_clear_pointer(&class_info, g_base_info_unref);
+    g_clear_pointer(&find_child_property_fun, g_base_info_unref);
+
+    return (GParamSpec*)ret.v_pointer;
+}
+
+void gjs_gtk_container_child_set_property(GObject* container, GObject* child,
                                           const char* property,
                                           const GValue* value) {
-    GParamSpec* pspec;
+    GParamSpec* pspec = NULL;
+    GIBaseInfo* base_info = NULL;
+    GIBaseInfo* child_set_property_fun = NULL;
+    GIObjectInfo* container_info;
+    GValue value_arg = G_VALUE_INIT;
+    GIArgument ret;
 
-    pspec = gtk_container_class_find_child_property(
-        G_OBJECT_GET_CLASS(container), property);
+    GIArgument child_set_property_args[4];
+
+    base_info = g_irepository_find_by_name(NULL, "Gtk", "Container");
+    container_info = (GIObjectInfo*)base_info;
+
+    pspec = gjs_gtk_container_class_find_child_property(container_info,
+                                                        container, property);
     if (pspec == NULL) {
         g_warning("%s does not have a property called %s",
                   g_type_name(G_OBJECT_TYPE(container)), property);
-        return;
+        goto out;
     }
 
     if ((G_VALUE_TYPE(value) == G_TYPE_POINTER) &&
@@ -50,12 +83,27 @@ void gjs_gtk_container_child_set_property(GtkContainer* container,
          * just put NULL into a G_TYPE_POINTER GValue, which will later fail
          * when trying to transform it to the GParamSpec's GType.
          */
-        GValue null_value = G_VALUE_INIT;
-        g_value_init(&null_value, pspec->value_type);
-        gtk_container_child_set_property(container, child, property,
-                                         &null_value);
-        g_value_unset(&null_value);
+        g_value_init(&value_arg, pspec->value_type);
     } else {
-        gtk_container_child_set_property(container, child, property, value);
+        g_value_init(&value_arg, G_VALUE_TYPE(value));
+        g_value_copy(value, &value_arg);
     }
+
+    child_set_property_fun =
+        g_object_info_find_method(container_info, "child_set_property");
+
+    child_set_property_args[0].v_pointer = container;
+    child_set_property_args[1].v_pointer = child;
+    child_set_property_args[2].v_string = (char*)property;
+    child_set_property_args[3].v_pointer = &value_arg;
+
+    g_function_info_invoke(child_set_property_fun, child_set_property_args, 4,
+                           NULL, 0, &ret, NULL);
+
+    g_value_unset(&value_arg);
+
+out:
+    g_clear_pointer(&pspec, g_param_spec_unref);
+    g_clear_pointer(&base_info, g_base_info_unref);
+    g_clear_pointer(&child_set_property_fun, g_base_info_unref);
 }
diff --git a/libgjs-private/gjs-gtk-util.h b/libgjs-private/gjs-gtk-util.h
index e523378c..20492aa5 100644
--- a/libgjs-private/gjs-gtk-util.h
+++ b/libgjs-private/gjs-gtk-util.h
@@ -25,24 +25,18 @@
 
 #include <config.h> /* for ENABLE_GTK */
 
-#ifdef ENABLE_GTK
+#include <glib-object.h>
+#include <glib.h>
 
-#    include <glib-object.h>
-#    include <glib.h>
-#    include <gtk/gtk.h>
-
-#    include "gjs/macros.h"
+#include "gjs/macros.h"
 
 G_BEGIN_DECLS
 
 GJS_EXPORT
-void gjs_gtk_container_child_set_property(GtkContainer* container,
-                                          GtkWidget* child,
+void gjs_gtk_container_child_set_property(GObject* container, GObject* child,
                                           const char* property,
                                           const GValue* value);
 
 G_END_DECLS
 
-#endif
-
 #endif /* LIBGJS_PRIVATE_GJS_GTK_UTIL_H_ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]