From c27c4e2048acb630feb24c31288f802345e99f4c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 26 Apr 2016 20:35:25 -0400 Subject: [PATCH] dnd: Fix lifecycle issues with widgets as drag icons The documentation clearly says that the widget is not destroyed, but we were in fact failing to keep it alive, since it was still a child or the icon_window when we destroy that. Fix this by reparenting the icon_widget out before. Also, deal with the possibility that the application might destroy the widget halfway through, for whatever reason. --- gtk/gtkdnd.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index 71913b03d9..d0b391c50c 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -2011,6 +2011,13 @@ gtk_drag_begin (GtkWidget *widget, actions, button, event, -1, -1); } +static void +icon_widget_destroyed (GtkWidget *widget, + GtkDragSourceInfo *info) +{ + g_clear_object (&info->icon_widget); +} + static void gtk_drag_set_icon_widget_internal (GdkDragContext *context, GtkWidget *widget, @@ -2041,6 +2048,8 @@ gtk_drag_set_icon_widget_internal (GdkDragContext *context, if (!widget) goto out; + g_signal_connect (widget, "destroy", G_CALLBACK (icon_widget_destroyed), info); + gdk_drag_context_set_hotspot (context, hot_x, hot_y); if (!info->icon_window) @@ -2715,11 +2724,15 @@ gtk_drag_remove_icon (GtkDragSourceInfo *info) widget = info->icon_widget; info->icon_widget = NULL; + g_signal_handlers_disconnect_by_func (widget, icon_widget_destroyed, info); + gtk_widget_hide (widget); gtk_widget_set_opacity (widget, 1.0); if (info->destroy_icon) gtk_widget_destroy (widget); + else + gtk_container_remove (GTK_CONTAINER (info->icon_window), widget); g_object_unref (widget); }