Issue #8359: GIMP crashes from "open the font selection dialog" button.

Apparently GDK/Win32 sends the "grab-broken-event" signal before the "clicked"
signal. This has only been changed since GTK4 so far.

Anyway the bottom line is that GimpContainerPopup would process a handled on
"clicked", using the object destroyed when "grab-broken-event" happened as
callback data. The solution is to make sure that the object stays alive long
enough. So I'm changing gimp_editor_add_button() to connect to signals with
g_signal_connect_object() (since all usage of this function was used with
GObject callback data, it was not a problem).

See discussion in !815.

As a side change, gimp_container_popup_dialog_clicked() should emit the
"cancel", not "confirm". This part was taken from MR !815 by Lloyd Konneker.

(cherry picked from commit f77f772f56)
This commit is contained in:
Jehan
2023-02-09 21:50:54 +01:00
parent 22ca5248af
commit aeb5eaa890
11 changed files with 48 additions and 33 deletions

View File

@ -230,7 +230,7 @@ gimp_color_display_editor_init (GimpColorDisplayEditor *editor)
NULL,
G_CALLBACK (gimp_color_display_editor_up_clicked),
NULL,
editor);
G_OBJECT (editor));
editor->down_button =
gimp_editor_add_button (GIMP_EDITOR (ed),
@ -239,7 +239,7 @@ gimp_color_display_editor_init (GimpColorDisplayEditor *editor)
NULL,
G_CALLBACK (gimp_color_display_editor_down_clicked),
NULL,
editor);
G_OBJECT (editor));
gtk_widget_set_sensitive (editor->up_button, FALSE);
gtk_widget_set_sensitive (editor->down_button, FALSE);

View File

@ -333,12 +333,12 @@ gimp_container_popup_create_view (GimpContainerPopup *popup)
_("Smaller Previews"), NULL,
G_CALLBACK (gimp_container_popup_smaller_clicked),
NULL,
popup);
G_OBJECT (popup));
gimp_editor_add_button (editor, "zoom-in",
_("Larger Previews"), NULL,
G_CALLBACK (gimp_container_popup_larger_clicked),
NULL,
popup);
G_OBJECT (popup));
button = gimp_editor_add_icon_box (editor, GIMP_TYPE_VIEW_TYPE, "gimp",
G_CALLBACK (gimp_container_popup_view_type_toggled),
@ -350,7 +350,7 @@ gimp_container_popup_create_view (GimpContainerPopup *popup)
popup->dialog_tooltip, NULL,
G_CALLBACK (gimp_container_popup_dialog_clicked),
NULL,
popup);
G_OBJECT (popup));
gtk_widget_grab_focus (GTK_WIDGET (popup->editor));
}
@ -402,5 +402,5 @@ gimp_container_popup_dialog_clicked (GtkWidget *button,
gtk_widget_get_screen (button),
gimp_widget_get_monitor (button),
popup->dialog_identifier);
g_signal_emit_by_name (popup, "confirm");
g_signal_emit_by_name (popup, "cancel");
}

View File

@ -297,7 +297,7 @@ gimp_controller_list_init (GimpControllerList *list)
NULL,
G_CALLBACK (gimp_controller_list_edit_clicked),
NULL,
list);
G_OBJECT (list));
list->up_button =
gimp_editor_add_button (GIMP_EDITOR (list->dest),
GIMP_ICON_GO_UP,
@ -305,7 +305,7 @@ gimp_controller_list_init (GimpControllerList *list)
NULL,
G_CALLBACK (gimp_controller_list_up_clicked),
NULL,
list);
G_OBJECT (list));
list->down_button =
gimp_editor_add_button (GIMP_EDITOR (list->dest),
GIMP_ICON_GO_DOWN,
@ -313,7 +313,7 @@ gimp_controller_list_init (GimpControllerList *list)
NULL,
G_CALLBACK (gimp_controller_list_down_clicked),
NULL,
list);
G_OBJECT (list));
gtk_widget_set_sensitive (list->edit_button, FALSE);
gtk_widget_set_sensitive (list->up_button, FALSE);

View File

@ -165,7 +165,7 @@ gimp_device_editor_init (GimpDeviceEditor *editor)
NULL,
G_CALLBACK (gimp_device_editor_delete_clicked),
NULL,
editor);
G_OBJECT (editor));
gtk_widget_set_sensitive (private->delete_button, FALSE);

View File

@ -154,7 +154,7 @@ gimp_device_status_init (GimpDeviceStatus *status)
_("Save device status"), NULL,
G_CALLBACK (gimp_device_status_save_clicked),
NULL,
status);
G_OBJECT (status));
}
static void

View File

@ -488,6 +488,21 @@ gimp_editor_popup_menu (GimpEditor *editor,
return FALSE;
}
/**
* gimp_editor_add_button:
* @editor:
* @icon_name:
* @tooltip:
* @help_id:
* @callback:
* @extended_callback:
* @callback_data:
*
* Creates a new button, connect @callback to the "clicked" signal and
* @extended_callback to the "extended-clicked" signal.
* The @callback_data has to be a %GObject so that we keep a ref on it and avoid
* bad surprises.
*/
GtkWidget *
gimp_editor_add_button (GimpEditor *editor,
const gchar *icon_name,
@ -495,7 +510,7 @@ gimp_editor_add_button (GimpEditor *editor,
const gchar *help_id,
GCallback callback,
GCallback extended_callback,
gpointer callback_data)
GObject *callback_data)
{
GtkWidget *button;
GtkWidget *image;
@ -516,14 +531,14 @@ gimp_editor_add_button (GimpEditor *editor,
gimp_help_set_help_data (button, tooltip, help_id);
if (callback)
g_signal_connect (button, "clicked",
callback,
callback_data);
g_signal_connect_object (button, "clicked",
callback,
callback_data, 0);
if (extended_callback)
g_signal_connect (button, "extended-clicked",
extended_callback,
callback_data);
g_signal_connect_object (button, "extended-clicked",
extended_callback,
callback_data, 0);
image = gtk_image_new_from_icon_name (icon_name, button_icon_size);
gtk_container_add (GTK_CONTAINER (button), image);

View File

@ -65,7 +65,7 @@ GtkWidget * gimp_editor_add_button (GimpEditor *editor,
const gchar *help_id,
GCallback callback,
GCallback extended_callback,
gpointer callback_data);
GObject *callback_data);
GtkWidget * gimp_editor_add_icon_box (GimpEditor *editor,
GType enum_type,
const gchar *icon_prefix,

View File

@ -193,7 +193,7 @@ gimp_settings_editor_constructed (GObject *object)
NULL,
G_CALLBACK (gimp_settings_editor_import_clicked),
NULL,
editor);
G_OBJECT (editor));
private->export_button =
gimp_editor_add_button (GIMP_EDITOR (tree_view),
@ -202,7 +202,7 @@ gimp_settings_editor_constructed (GObject *object)
NULL,
G_CALLBACK (gimp_settings_editor_export_clicked),
NULL,
editor);
G_OBJECT (editor));
private->delete_button =
gimp_editor_add_button (GIMP_EDITOR (tree_view),
@ -211,7 +211,7 @@ gimp_settings_editor_constructed (GObject *object)
NULL,
G_CALLBACK (gimp_settings_editor_delete_clicked),
NULL,
editor);
G_OBJECT (editor));
gtk_widget_set_sensitive (private->delete_button, FALSE);
}

View File

@ -243,7 +243,7 @@ gimp_tool_editor_constructed (GObject *object)
_("Create a new tool group"), NULL,
G_CALLBACK (gimp_tool_editor_new_group_clicked),
NULL,
tool_editor);
G_OBJECT (tool_editor));
tool_editor->priv->raise_button =
gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_GO_UP,
@ -251,7 +251,7 @@ gimp_tool_editor_constructed (GObject *object)
_("Raise this item to the top"),
G_CALLBACK (gimp_tool_editor_raise_clicked),
G_CALLBACK (gimp_tool_editor_raise_extend_clicked),
tool_editor);
G_OBJECT (tool_editor));
tool_editor->priv->lower_button =
gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_GO_DOWN,
@ -259,21 +259,21 @@ gimp_tool_editor_constructed (GObject *object)
_("Lower this item to the bottom"),
G_CALLBACK (gimp_tool_editor_lower_clicked),
G_CALLBACK (gimp_tool_editor_lower_extend_clicked),
tool_editor);
G_OBJECT (tool_editor));
tool_editor->priv->delete_button =
gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_EDIT_DELETE,
_("Delete this tool group"), NULL,
G_CALLBACK (gimp_tool_editor_delete_clicked),
NULL,
tool_editor);
G_OBJECT (tool_editor));
tool_editor->priv->reset_button =
gimp_editor_add_button (GIMP_EDITOR (tool_editor), GIMP_ICON_RESET,
_("Reset tool order and visibility"), NULL,
G_CALLBACK (gimp_tool_editor_reset_clicked),
NULL,
tool_editor);
G_OBJECT (tool_editor));
gimp_tool_editor_update_sensitivity (tool_editor);
}

View File

@ -201,7 +201,7 @@ gimp_tool_options_editor_constructed (GObject *object)
GIMP_HELP_TOOL_OPTIONS_SAVE,
G_CALLBACK (gimp_tool_options_editor_save_clicked),
NULL,
editor);
G_OBJECT (editor));
editor->p->restore_button =
gimp_editor_add_button (GIMP_EDITOR (editor),
@ -210,7 +210,7 @@ gimp_tool_options_editor_constructed (GObject *object)
GIMP_HELP_TOOL_OPTIONS_RESTORE,
G_CALLBACK (gimp_tool_options_editor_restore_clicked),
NULL,
editor);
G_OBJECT (editor));
editor->p->delete_button =
gimp_editor_add_button (GIMP_EDITOR (editor),
@ -219,7 +219,7 @@ gimp_tool_options_editor_constructed (GObject *object)
GIMP_HELP_TOOL_OPTIONS_DELETE,
G_CALLBACK (gimp_tool_options_editor_delete_clicked),
NULL,
editor);
G_OBJECT (editor));
editor->p->reset_button =
gimp_editor_add_action_button (GIMP_EDITOR (editor), "tool-options",