gtkbuilder: check for existing object before extending template
authorChristian Hergert <chergert@redhat.com>
Mon, 1 Aug 2022 04:15:08 +0000 (21:15 -0700)
committerChristian Hergert <chergert@redhat.com>
Mon, 1 Aug 2022 04:25:58 +0000 (21:25 -0700)
If gtk_builder_expose_object() is called twice with the same name, it will
result in a g_critical(). This improves that situation by checking for the
object before exposing additional times.

This turns out to be handy in situations where templates are expanded
multiple times, such as application-side implementations of UI merging.

gtk/gtkbuilder.c

index ab28ccc5d9cd1f685f3a2d7a53134e5d5eef0b60..063bf7b03c0e6079b6c98b3b3c667970c5d76402 100644 (file)
@@ -1367,6 +1367,7 @@ gtk_builder_extend_with_template (GtkBuilder   *builder,
                                   GError      **error)
 {
   GtkBuilderPrivate *priv = gtk_builder_get_instance_private (builder);
+  const char *name;
   GError *tmp_error;
   char *filename;
 
@@ -1384,8 +1385,15 @@ gtk_builder_extend_with_template (GtkBuilder   *builder,
   priv->resource_prefix = NULL;
   priv->template_type = template_type;
 
-  filename = g_strconcat ("<", g_type_name (template_type), " template>", NULL);
-  gtk_builder_expose_object (builder, g_type_name (template_type), object);
+  /* We specifically allow this function to be called multiple times with
+   * the same @template_type as that is used in applications like Builder
+   * to implement UI merging.
+   */
+  name = g_type_name (template_type);
+  if (gtk_builder_get_object (builder, name) != object)
+    gtk_builder_expose_object (builder, name, object);
+
+  filename = g_strconcat ("<", name, " template>", NULL);
   _gtk_builder_parser_parse_buffer (builder, filename,
                                     buffer, length,
                                     NULL,