libgimp: sink the floating references after adding them to hash table.

Though the previous implementation worked fine on C plug-ins, I realized
it was problematic on bindings. In particular, the Python binding at
least was somehow freeing returned floating objects, unless assigned to
a variable.
For instance, the widget returned by the following code:

> dialog.get_color_widget('color', True, GimpUi.ColorAreaType.FLAT)

… was freed by the PyGObject binding when it was floating, even though
(transfer none) was set (hence telling the binding it should not free
the returned object). The workaround was to assign it to some variable,
even though I was not planning to use it.
Making sure all references are full fixes it.

GObject docs also notes:

> **Note**: Floating references are a C convenience API and should not
> be used in modern GObject code. Language bindings in particular find
> the concept highly problematic, as floating references are not
> identifiable through annotations, and neither are deviations from the
> floating reference behavior, like types that inherit from
> GInitiallyUnowned and still return a full reference from
> g_object_new().
This commit is contained in:
Jehan 2021-04-20 17:08:31 +02:00
parent f15d16150e
commit e1a489a43a

View file

@ -627,6 +627,8 @@ gimp_procedure_dialog_get_widget (GimpProcedureDialog *dialog,
gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL); gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL);
g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget); g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget);
if (g_object_is_floating (widget))
g_object_ref_sink (widget);
return widget; return widget;
} }
@ -707,6 +709,8 @@ gimp_procedure_dialog_get_color_widget (GimpProcedureDialog *dialog,
gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL); gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL);
g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget); g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget);
if (g_object_is_floating (widget))
g_object_ref_sink (widget);
return widget; return widget;
} }
@ -782,6 +786,8 @@ gimp_procedure_dialog_get_int_combo (GimpProcedureDialog *dialog,
gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL); gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL);
g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget); g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget);
if (g_object_is_floating (widget))
g_object_ref_sink (widget);
return widget; return widget;
} }
@ -847,6 +853,8 @@ gimp_procedure_dialog_get_scale_entry (GimpProcedureDialog *dialog,
gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL); gimp_procedure_dialog_check_mnemonic (dialog, widget, property, NULL);
g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget); g_hash_table_insert (dialog->priv->widgets, g_strdup (property), widget);
if (g_object_is_floating (widget))
g_object_ref_sink (widget);
return widget; return widget;
} }
@ -896,6 +904,8 @@ gimp_procedure_dialog_get_label (GimpProcedureDialog *dialog,
label = gtk_label_new (text); label = gtk_label_new (text);
g_hash_table_insert (dialog->priv->widgets, g_strdup (label_id), label); g_hash_table_insert (dialog->priv->widgets, g_strdup (label_id), label);
if (g_object_is_floating (label))
g_object_ref_sink (label);
return label; return label;
} }
@ -1299,6 +1309,8 @@ gimp_procedure_dialog_fill_frame (GimpProcedureDialog *dialog,
} }
g_hash_table_insert (dialog->priv->widgets, g_strdup (container_id), frame); g_hash_table_insert (dialog->priv->widgets, g_strdup (container_id), frame);
if (g_object_is_floating (frame))
g_object_ref_sink (frame);
return frame; return frame;
} }
@ -1694,6 +1706,8 @@ gimp_procedure_dialog_fill_container_list (GimpProcedureDialog *dialog,
g_list_free (properties); g_list_free (properties);
g_hash_table_insert (dialog->priv->widgets, g_strdup (container_id), container); g_hash_table_insert (dialog->priv->widgets, g_strdup (container_id), container);
if (g_object_is_floating (container))
g_object_ref_sink (container);
return GTK_WIDGET (container); return GTK_WIDGET (container);
} }