[gnome-shell/benzea/fix-shell-app-fallback-icon] shell/app: Correctly track the window used for the fallback icon




commit ce0fdb6111da74a4fd25a01326b871fdc955406b
Author: Benjamin Berg <bberg redhat com>
Date:   Wed Dec 15 16:03:52 2021 +0100

    shell/app: Correctly track the window used for the fallback icon
    
    We were not properly tracking the window used for the fallback icon.
    This could trigger a crash, as disconnection of the signal handler might
    happen on the wrong window, which in turn could cause the icon change
    notification to happen on a destroyed ShellApp instance.
    
    Fix this by tracking the window used for the fallback icon. Disconnect
    the icon notify callback explicitly for this window only when it is
    removed.
    
    Also, just to be extra safe, make sure that the icon is never NULL even
    if x11_window_create_fallback_gicon should return NULL for some reason.

 src/shell-app.c | 36 ++++++++++++++++++++++--------------
 1 file changed, 22 insertions(+), 14 deletions(-)
---
diff --git a/src/shell-app.c b/src/shell-app.c
index 1e3b53257f..f8e29184c6 100644
--- a/src/shell-app.c
+++ b/src/shell-app.c
@@ -38,8 +38,6 @@ typedef struct {
   /* Signal connection to dirty window sort list on workspace changes */
   gulong workspace_switch_id;
 
-  gulong icon_changed_id;
-
   GSList *windows;
 
   guint interesting_windows;
@@ -81,6 +79,7 @@ struct _ShellApp
                           * the way shell-window-tracker.c works).
                           */
   GIcon *fallback_icon;
+  MetaWindow *fallback_icon_window;
 
   ShellAppRunningState *running_state;
 
@@ -206,11 +205,15 @@ on_window_icon_changed (GObject          *object,
 {
   MetaWindow *window = META_WINDOW (object);
   ShellApp *app = user_data;
+  GIcon *new;
 
+  new = x11_window_create_fallback_gicon (window);
   g_clear_object (&app->fallback_icon);
-  app->fallback_icon = x11_window_create_fallback_gicon (window);
-
-  g_object_notify (G_OBJECT (app), "icon");
+  if (new)
+    {
+      app->fallback_icon = new;
+      g_object_notify (G_OBJECT (app), "icon");
+    }
 }
 
 /**
@@ -243,16 +246,15 @@ shell_app_get_icon (ShellApp *app)
   if (window &&
       meta_window_get_client_type (window) == META_WINDOW_CLIENT_TYPE_X11)
     {
+      app->fallback_icon_window = window;
       app->fallback_icon = x11_window_create_fallback_gicon (window);
-      app->running_state->icon_changed_id =
-        g_signal_connect (G_OBJECT (window),
-                         "notify::icon", G_CALLBACK (on_window_icon_changed), app);
-    }
-  else
-    {
-      app->fallback_icon = g_themed_icon_new ("application-x-executable");
+      g_signal_connect (G_OBJECT (window),
+                        "notify::icon", G_CALLBACK (on_window_icon_changed), app);
     }
 
+  if (!app->fallback_icon)
+    app->fallback_icon = g_themed_icon_new ("application-x-executable");
+
   return app->fallback_icon;
 }
 
@@ -1147,9 +1149,15 @@ _shell_app_remove_window (ShellApp   *app,
   g_signal_handlers_disconnect_by_func (window, G_CALLBACK(shell_app_on_unmanaged), app);
   g_signal_handlers_disconnect_by_func (window, G_CALLBACK(shell_app_on_user_time_changed), app);
   g_signal_handlers_disconnect_by_func (window, G_CALLBACK(shell_app_on_skip_taskbar_changed), app);
-  app->running_state->windows = g_slist_remove (app->running_state->windows, window);
+  if (window == app->fallback_icon_window)
+    {
+      g_signal_handlers_disconnect_by_func (window, G_CALLBACK(on_window_icon_changed), app);
+      app->fallback_icon_window = NULL;
 
-  g_clear_signal_handler (&app->running_state->icon_changed_id, window);
+      /* Select a new icon from a different window. */
+      g_clear_object (&app->fallback_icon);
+    }
+  app->running_state->windows = g_slist_remove (app->running_state->windows, window);
 
   if (!meta_window_is_skip_taskbar (window))
     app->running_state->interesting_windows--;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]