From db81ac6933b62ab1b7809b213c812644994e780e Mon Sep 17 00:00:00 2001 From: Jehan Date: Thu, 30 Oct 2025 18:37:35 +0100 Subject: [PATCH] Issue #11613: crashing when freeing window handle (again). This is a followup of commit 0ff960c45b which was the right fix, except that we must make sure that gimp_widget_free_native_handle() is called **before** chaining up with the widget's parent dispose(). Failing to do so, the first parent's dispose() was destroying the associated GdkWindow, which made it impossible to call gdk_wayland_window_unexport_handle() on it. And therefore we were still getting handle callbacks possibly run after the window was destroyed, if we were very fast enough to destroy a window immediately when it is being shown. I was still experiencing a crash when closing the Export file dialog very fast with Esc while it was reappearing after canceling a plug-in's export dialog. This followup commit reorders the one case where we still had the crash because of this order issue, and adds some docs comment to tell developers how to use the freeing function. (cherry picked from commit a5fe4f1ca586b5254e37f91fda4377e3cf18a6e7) --- app/widgets/gimpfiledialog.c | 4 ++-- libgimpwidgets/gimpwidgetsutils.c | 8 +++++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/widgets/gimpfiledialog.c b/app/widgets/gimpfiledialog.c index 0471158cec..1313439d4c 100644 --- a/app/widgets/gimpfiledialog.c +++ b/app/widgets/gimpfiledialog.c @@ -386,6 +386,8 @@ gimp_file_dialog_dispose (GObject *object) { GimpFileDialog *dialog = GIMP_FILE_DIALOG (object); + gimp_widget_free_native_handle (GTK_WIDGET (dialog), &dialog->window_handle); + G_OBJECT_CLASS (parent_class)->dispose (object); dialog->progress = NULL; @@ -395,8 +397,6 @@ gimp_file_dialog_dispose (GObject *object) g_clear_pointer (&dialog->automatic_help_id, g_free); g_clear_pointer (&dialog->automatic_label, g_free); g_clear_pointer (&dialog->file_filter_label, g_free); - - gimp_widget_free_native_handle (GTK_WIDGET (dialog), &dialog->window_handle); } static gboolean diff --git a/libgimpwidgets/gimpwidgetsutils.c b/libgimpwidgets/gimpwidgetsutils.c index 65140c5da8..9ef5d0ef9c 100644 --- a/libgimpwidgets/gimpwidgetsutils.c +++ b/libgimpwidgets/gimpwidgetsutils.c @@ -1179,12 +1179,18 @@ gimp_widget_set_native_handle (GtkWidget *widget, * * Disposes a widget's native window handle created, possibly * asynchronously, by a previous call to [func@GimpUi.widget_set_native_handle]. - * Call this function on `dispose()` or `finalize()`. * * Depending on the platform, this function may also execute other * necessary clean up so you should call it and not simply free the * [struct@GLib.Bytes] yourself. * + * You should call this function in the `dispose()` implementation of + * your custom widget **before** chaining up with the parent class' + * `dispose()` call. The first call to the parent's `dispose()` will + * destroy the `GdkWindow` which will prevent this function to do part + * of its cleanup when run after. This may result in crashes on some + * platforms. + * * This is safe to call even if deferenced @window_handle is %NULL, i.e. * that you don't have to check if the window handle was actually set. *