From 3bafd1b89e83341d0aef90f74134f09abfe55df5 Mon Sep 17 00:00:00 2001 From: Leigh Scott Date: Sat, 16 May 2026 00:50:40 +0100 Subject: [PATCH] xapp-status-icon: unrealize GtkStatusIcon before clearing to prevent stale GdkWindow XID mappings crashing during Cinnamon restart --- libxapp/xapp-status-icon.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/libxapp/xapp-status-icon.c b/libxapp/xapp-status-icon.c index a3e3ef23..20203dfe 100644 --- a/libxapp/xapp-status-icon.c +++ b/libxapp/xapp-status-icon.c @@ -113,6 +113,7 @@ G_DEFINE_TYPE_WITH_PRIVATE (XAppStatusIcon, xapp_status_icon, G_TYPE_OBJECT) static void refresh_icon (XAppStatusIcon *self); static void use_gtk_status_icon (XAppStatusIcon *self); static void remove_icon_path_from_bus (XAppStatusIcon *self); +static void hide_and_defer_unref_status_icon (XAppStatusIcon *self, GtkStatusIcon *status_icon); static void cancellable_reset (XAppStatusIcon *self) @@ -805,6 +806,30 @@ on_name_lost (GDBusConnection *connection, g_list_free_full (instances, g_object_unref); } +static gboolean +return_false_cb (gpointer user_data) +{ + (void) user_data; + + return G_SOURCE_REMOVE; +} + +static void +hide_and_defer_unref_status_icon (XAppStatusIcon *self, GtkStatusIcon *status_icon) +{ + if (status_icon == NULL) + return; + + g_signal_handlers_disconnect_by_data (status_icon, self); + + gtk_status_icon_set_visible (status_icon, FALSE); + + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + return_false_cb, + status_icon, + g_object_unref); +} + static void sync_skeleton (XAppStatusIcon *self) { @@ -813,7 +838,8 @@ sync_skeleton (XAppStatusIcon *self) priv->fail_counter = 0; - g_clear_object (&self->priv->gtk_status_icon); + hide_and_defer_unref_status_icon (self, self->priv->gtk_status_icon); + self->priv->gtk_status_icon = NULL; g_object_set (G_OBJECT (priv->interface_skeleton), "name", priv->name, @@ -1047,7 +1073,8 @@ use_gtk_status_icon (XAppStatusIcon *self) remove_icon_path_from_bus (self); // Make sure there wasn't already one - g_clear_object (&self->priv->gtk_status_icon); + hide_and_defer_unref_status_icon (self, self->priv->gtk_status_icon); + self->priv->gtk_status_icon = NULL; self->priv->gtk_status_icon = gtk_status_icon_new (); @@ -1362,9 +1389,7 @@ xapp_status_icon_dispose (GObject *object) if (self->priv->gtk_status_icon != NULL) { - g_signal_handlers_disconnect_by_func (self->priv->gtk_status_icon, on_gtk_status_icon_button_press, self); - g_signal_handlers_disconnect_by_func (self->priv->gtk_status_icon, on_gtk_status_icon_button_release, self); - g_object_unref (self->priv->gtk_status_icon); + hide_and_defer_unref_status_icon (self, self->priv->gtk_status_icon); self->priv->gtk_status_icon = NULL; }