From 2fa5967f21aa9011e4dc91be47d3d4299aa73430 Mon Sep 17 00:00:00 2001 From: Jehan Date: Mon, 5 May 2025 22:06:23 +0200 Subject: [PATCH] Issue #1486: invalid disconnected monitor on exit. Note that I also tried to set the monitor as a weak pointer, but it was not properly finalized by GDK at disconnection apparently. Anyway processing the "invalidate" signal is a correct way to do this too. A further possible improvement may be to store the description of the monitor in the sessionrc file, and keep these in the GimpSessionInfo too, so that we can easily retrieve a monitor which is often disconnected and reconnected. --- app/widgets/gimpsessioninfo.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/app/widgets/gimpsessioninfo.c b/app/widgets/gimpsessioninfo.c index 9cff0eed86..485c2eae16 100644 --- a/app/widgets/gimpsessioninfo.c +++ b/app/widgets/gimpsessioninfo.c @@ -91,6 +91,9 @@ static void gimp_session_info_dialog_show (GtkWidget *wid GimpSessionInfo *info); static gboolean gimp_session_info_restore_docks (GimpRestoreDocksData *data); +static void gimp_session_info_monitor_invalidate (GdkMonitor *monitor, + GimpSessionInfo *info); + G_DEFINE_TYPE_WITH_CODE (GimpSessionInfo, gimp_session_info, GIMP_TYPE_OBJECT, G_ADD_PRIVATE (GimpSessionInfo) @@ -350,8 +353,18 @@ gimp_session_info_deserialize (GimpConfig *config, token = G_TOKEN_INT; if (gimp_scanner_parse_int (scanner, &dummy)) { + if (info->p->monitor != NULL) + g_signal_handlers_disconnect_by_func (info->p->monitor, + G_CALLBACK (gimp_session_info_monitor_invalidate), + info); + info->p->monitor = gdk_display_get_monitor (gdk_display_get_default (), dummy); + + if (info->p->monitor != NULL) + g_signal_connect_object (info->p->monitor, "invalidate", + G_CALLBACK (gimp_session_info_monitor_invalidate), + info, 0); } else goto error; @@ -548,6 +561,26 @@ gimp_session_info_restore_docks (GimpRestoreDocksData *data) return FALSE; } +static void +gimp_session_info_monitor_invalidate (GdkMonitor *monitor, + GimpSessionInfo *info) +{ + /* When a monitor is disconnected, even if it is connected again, it + * will now be a different object. We need to get rid of the dangling + * pointer. + * + * TODO: maybe storing also the manufacturer/model (and in GTK4, the + * description) may be a good way to retrieve a monitor upon + * reconnection so that a window stay associated to the same monitor, + * even when disconnecting/reconnecting (e.g. a laptop plugged to a + * desktop display). + */ + g_signal_handlers_disconnect_by_func (monitor, + G_CALLBACK (gimp_session_info_monitor_invalidate), + info); + info->p->monitor = DEFAULT_MONITOR; +} + /* public functions */ @@ -809,10 +842,20 @@ gimp_session_info_read_geometry (GimpSessionInfo *info, info->p->height = 0; } + if (info->p->monitor != NULL) + g_signal_handlers_disconnect_by_func (info->p->monitor, + G_CALLBACK (gimp_session_info_monitor_invalidate), + info); + info->p->monitor = DEFAULT_MONITOR; if (monitor != gdk_display_get_primary_monitor (display)) info->p->monitor = monitor; + + if (info->p->monitor != NULL) + g_signal_connect_object (info->p->monitor, "invalidate", + G_CALLBACK (gimp_session_info_monitor_invalidate), + info, 0); } info->p->open = FALSE;