Issue #11613: crashing when freeing window handle.
It is a tentative fix as I had this crash once but could not reproduce it, even redoing dozens of times the same thing I had done. It is mostly based on something which GDK docs of gdk_wayland_window_export_handle() says: > To unexport the window, gdk_wayland_window_unexport_handle() must be > called the same number of times as gdk_wayland_window_export_handle() > was called. Any 'exported' callback may still be invoked until the > window is unexported or destroyed. So when the GdkWindow of the widget still exists, let's make sure we call gdk_wayland_window_unexport_handle() as many times as necessary (no less, but also no more!), and also that we disconnect all handlers which could possibly call more export_handle().
This commit is contained in:
parent
b879deb323
commit
0ff960c45b
1 changed files with 40 additions and 6 deletions
|
|
@ -1194,15 +1194,40 @@ void
|
|||
gimp_widget_free_native_handle (GtkWidget *widget,
|
||||
GBytes **window_handle)
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
GdkWindow *surface;
|
||||
#endif
|
||||
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (window_handle != NULL);
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()) &&
|
||||
/* The GdkWindow is likely already destroyed. */
|
||||
gtk_widget_get_window (widget) != NULL)
|
||||
gdk_wayland_window_unexport_handle (gtk_widget_get_window (widget));
|
||||
#endif
|
||||
g_signal_handlers_disconnect_by_func (toplevel,
|
||||
G_CALLBACK (gimp_widget_set_handle_on_mapped),
|
||||
window_handle);
|
||||
g_signal_handlers_disconnect_by_func (widget,
|
||||
G_CALLBACK (gimp_widget_set_handle_on_mapped),
|
||||
window_handle);
|
||||
g_signal_handlers_disconnect_by_func (widget,
|
||||
G_CALLBACK (gimp_widget_set_handle_on_realize),
|
||||
window_handle);
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
surface = gtk_widget_get_window (widget);
|
||||
|
||||
if (surface != NULL && GDK_IS_WAYLAND_WINDOW (surface))
|
||||
{
|
||||
gint count;
|
||||
|
||||
count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (surface),
|
||||
"gimp_widget_set_handle_on_mapped-call-count"));
|
||||
g_object_set_data (G_OBJECT (surface),
|
||||
"gimp_widget_set_handle_on_mapped-call-count",
|
||||
NULL);
|
||||
while (count--)
|
||||
gdk_wayland_window_unexport_handle (surface);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_clear_pointer (window_handle, g_bytes_unref);
|
||||
}
|
||||
|
|
@ -1356,6 +1381,15 @@ gimp_widget_set_handle_on_mapped (GtkWidget *widget,
|
|||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW (surface))
|
||||
{
|
||||
gint count;
|
||||
|
||||
count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (surface),
|
||||
"gimp_widget_set_handle_on_mapped-call-count"));
|
||||
count += 1;
|
||||
g_object_set_data (G_OBJECT (surface),
|
||||
"gimp_widget_set_handle_on_mapped-call-count",
|
||||
GINT_TO_POINTER (count));
|
||||
|
||||
/* I don't run this on "realize" event because somehow it locks
|
||||
* the whole processus in Wayland. The "map-event" happens
|
||||
* slightly after the window became visible and I didn't
|
||||
|
|
|
|||
Loading…
Reference in a new issue