[gnome-software] Marshal GsApp property changes callbacks to the UI thread



commit e4dd977ffc39a325b5731df1c8dfe4ceaec4c012
Author: Kalev Lember <kalevlember gmail com>
Date:   Mon Sep 15 22:25:33 2014 +0200

    Marshal GsApp property changes callbacks to the UI thread
    
    Otherwise we end up calling gtk+ functions in the worker threads and
    occasionally transhing data, leading to crashes.

 src/gs-app-addon-row.c   |   16 +++++++++++++++-
 src/gs-app-tile.c        |   31 ++++++++++++++++++++++---------
 src/gs-feature-tile.c    |   29 ++++++++++++++++++++++-------
 src/gs-popular-tile.c    |   27 ++++++++++++++++++++-------
 src/gs-shell-details.c   |   16 +++++++++++++++-
 src/gs-shell-installed.c |   16 +++++++++++++++-
 6 files changed, 109 insertions(+), 26 deletions(-)
---
diff --git a/src/gs-app-addon-row.c b/src/gs-app-addon-row.c
index 23cd511..dc290dd 100644
--- a/src/gs-app-addon-row.c
+++ b/src/gs-app-addon-row.c
@@ -153,12 +153,26 @@ gs_app_addon_row_get_addon (GsAppAddonRow *row)
        return row->priv->app;
 }
 
+static gboolean
+gs_app_addon_row_refresh_idle (gpointer user_data)
+{
+       GsAppAddonRow *row = GS_APP_ADDON_ROW (user_data);
+
+       gs_app_addon_row_refresh (row);
+
+       g_object_unref (row);
+       return G_SOURCE_REMOVE;
+}
+
 static void
 gs_app_addon_row_notify_props_changed_cb (GsApp *app,
                                           GParamSpec *pspec,
                                           GsAppAddonRow *row)
 {
-       gs_app_addon_row_refresh (row);
+       guint id;
+
+       id = g_idle_add (gs_app_addon_row_refresh_idle, g_object_ref (row));
+       g_source_set_name_by_id (id, "[gnome-software] gs_app_addon_row_refresh_idle");
 }
 
 void
diff --git a/src/gs-app-tile.c b/src/gs-app-tile.c
index eef6882..056aa54 100644
--- a/src/gs-app-tile.c
+++ b/src/gs-app-tile.c
@@ -51,9 +51,10 @@ gs_app_tile_get_app (GsAppTile *tile)
        return priv->app;
 }
 
-static void
-app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
+static gboolean
+app_state_changed_idle (gpointer user_data)
 {
+       GsAppTile *tile = GS_APP_TILE (user_data);
        AtkObject *accessible;
        GsAppTilePrivate *priv;
        GtkWidget *label;
@@ -64,11 +65,11 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
         accessible = gtk_widget_get_accessible (GTK_WIDGET (tile));
 
        label = gtk_bin_get_child (GTK_BIN (priv->eventbox));
-       switch (gs_app_get_state (app)) {
+       switch (gs_app_get_state (priv->app)) {
        case AS_APP_STATE_INSTALLED:
                installed = TRUE;
                name = g_strdup_printf ("%s (%s)",
-                                       gs_app_get_name (app),
+                                       gs_app_get_name (priv->app),
                                        _("Installed"));
                /* TRANSLATORS: this is the small blue label on the tile
                 * that tells the user the application is installed */
@@ -77,7 +78,7 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
        case AS_APP_STATE_INSTALLING:
                installed = TRUE;
                name = g_strdup_printf ("%s (%s)",
-                                       gs_app_get_name (app),
+                                       gs_app_get_name (priv->app),
                                        _("Installing"));
                /* TRANSLATORS: this is the small blue label on the tile
                 * that tells the user the application is being installing */
@@ -86,7 +87,7 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
        case AS_APP_STATE_REMOVING:
                installed = TRUE;
                name = g_strdup_printf ("%s (%s)",
-                                       gs_app_get_name (app),
+                                       gs_app_get_name (priv->app),
                                        _("Removing"));
                /* TRANSLATORS: this is the small blue label on the tile
                 * that tells the user the application is being removed */
@@ -95,7 +96,7 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
        case AS_APP_STATE_UPDATABLE:
                installed = TRUE;
                name = g_strdup_printf ("%s (%s)",
-                                       gs_app_get_name (app),
+                                       gs_app_get_name (priv->app),
                                        _("Updates"));
                /* TRANSLATORS: this is the small blue label on the tile
                 * that tells the user there is an update for the installed
@@ -106,7 +107,7 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
         case AS_APP_STATE_AVAILABLE:
         default:
                installed = FALSE;
-               name = g_strdup (gs_app_get_name (app));
+               name = g_strdup (gs_app_get_name (priv->app));
                 break;
         }
 
@@ -114,9 +115,21 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
 
        if (GTK_IS_ACCESSIBLE (accessible)) {
                atk_object_set_name (accessible, name);
-               atk_object_set_description (accessible, gs_app_get_summary (app));
+               atk_object_set_description (accessible, gs_app_get_summary (priv->app));
        }
        g_free (name);
+
+       g_object_unref (tile);
+       return G_SOURCE_REMOVE;
+}
+
+static void
+app_state_changed (GsApp *app, GParamSpec *pspec, GsAppTile *tile)
+{
+       guint id;
+
+       id = g_idle_add (app_state_changed_idle, g_object_ref (tile));
+       g_source_set_name_by_id (id, "[gnome-software] app_state_changed_idle");
 }
 
 void
diff --git a/src/gs-feature-tile.c b/src/gs-feature-tile.c
index dba10f6..f8d4f6d 100644
--- a/src/gs-feature-tile.c
+++ b/src/gs-feature-tile.c
@@ -49,38 +49,53 @@ gs_feature_tile_get_app (GsFeatureTile *tile)
        return priv->app;
 }
 
-static void
-app_state_changed (GsApp *app, GParamSpec *pspec, GsFeatureTile *tile)
+static gboolean
+app_state_changed_idle (gpointer user_data)
 {
+        GsFeatureTile *tile = GS_FEATURE_TILE (user_data);
+        GsFeatureTilePrivate *priv;
         AtkObject *accessible;
         gchar *name;
 
+        priv = gs_feature_tile_get_instance_private (tile);
         accessible = gtk_widget_get_accessible (GTK_WIDGET (tile));
 
-        switch (gs_app_get_state (app)) {
+        switch (gs_app_get_state (priv->app)) {
         case AS_APP_STATE_INSTALLED:
         case AS_APP_STATE_INSTALLING:
         case AS_APP_STATE_REMOVING:
                 name = g_strdup_printf ("%s (%s)",
-                                        gs_app_get_name (app),
+                                        gs_app_get_name (priv->app),
                                         _("Installed"));
                 break;
         case AS_APP_STATE_UPDATABLE:
                 name = g_strdup_printf ("%s (%s)",
-                                        gs_app_get_name (app),
+                                        gs_app_get_name (priv->app),
                                         _("Updates"));
                 break;
         case AS_APP_STATE_AVAILABLE:
         default:
-                name = g_strdup (gs_app_get_name (app));
+                name = g_strdup (gs_app_get_name (priv->app));
                 break;
         }
 
         if (GTK_IS_ACCESSIBLE (accessible)) {
                 atk_object_set_name (accessible, name);
-                atk_object_set_description (accessible, gs_app_get_summary (app));
+                atk_object_set_description (accessible, gs_app_get_summary (priv->app));
         }
         g_free (name);
+
+        g_object_unref (tile);
+        return G_SOURCE_REMOVE;
+}
+
+static void
+app_state_changed (GsApp *app, GParamSpec *pspec, GsFeatureTile *tile)
+{
+       guint id;
+
+       id = g_idle_add (app_state_changed_idle, g_object_ref (tile));
+       g_source_set_name_by_id (id, "[gnome-software] app_state_changed_idle");
 }
 
 void
diff --git a/src/gs-popular-tile.c b/src/gs-popular-tile.c
index 8f4768e..712a08f 100644
--- a/src/gs-popular-tile.c
+++ b/src/gs-popular-tile.c
@@ -50,9 +50,10 @@ gs_popular_tile_get_app (GsPopularTile *tile)
        return priv->app;
 }
 
-static void
-app_state_changed (GsApp *app, GParamSpec *pspec, GsPopularTile *tile)
+static gboolean
+app_state_changed_idle (gpointer user_data)
 {
+       GsPopularTile *tile = GS_POPULAR_TILE (user_data);
        AtkObject *accessible;
        GsPopularTilePrivate *priv;
        GtkWidget *label;
@@ -63,13 +64,13 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsPopularTile *tile)
        accessible = gtk_widget_get_accessible (GTK_WIDGET (tile));
 
        label = gtk_bin_get_child (GTK_BIN (priv->eventbox));
-       switch (gs_app_get_state (app)) {
+       switch (gs_app_get_state (priv->app)) {
        case AS_APP_STATE_INSTALLED:
        case AS_APP_STATE_INSTALLING:
        case AS_APP_STATE_REMOVING:
                installed = TRUE;
                name = g_strdup_printf ("%s (%s)",
-                                       gs_app_get_name (app),
+                                       gs_app_get_name (priv->app),
                                        _("Installed"));
                /* TRANSLATORS: this is the small blue label on the tile
                 * that tells the user the application is installed */
@@ -78,7 +79,7 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsPopularTile *tile)
        case AS_APP_STATE_UPDATABLE:
                installed = TRUE;
                name = g_strdup_printf ("%s (%s)",
-                                       gs_app_get_name (app),
+                                       gs_app_get_name (priv->app),
                                        _("Updates"));
                /* TRANSLATORS: this is the small blue label on the tile
                 * that tells the user there is an update for the installed
@@ -88,7 +89,7 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsPopularTile *tile)
        case AS_APP_STATE_AVAILABLE:
        default:
                installed = FALSE;
-               name = g_strdup (gs_app_get_name (app));
+               name = g_strdup (gs_app_get_name (priv->app));
                break;
        }
 
@@ -96,9 +97,21 @@ app_state_changed (GsApp *app, GParamSpec *pspec, GsPopularTile *tile)
 
        if (GTK_IS_ACCESSIBLE (accessible)) {
                atk_object_set_name (accessible, name);
-               atk_object_set_description (accessible, gs_app_get_summary (app));
+               atk_object_set_description (accessible, gs_app_get_summary (priv->app));
        }
        g_free (name);
+
+       g_object_unref (tile);
+       return G_SOURCE_REMOVE;
+}
+
+static void
+app_state_changed (GsApp *app, GParamSpec *pspec, GsPopularTile *tile)
+{
+       guint id;
+
+       id = g_idle_add (app_state_changed_idle, g_object_ref (tile));
+       g_source_set_name_by_id (id, "[gnome-software] app_state_changed_idle");
 }
 
 void
diff --git a/src/gs-shell-details.c b/src/gs-shell-details.c
index 0f3c996..06d7ca9 100644
--- a/src/gs-shell-details.c
+++ b/src/gs-shell-details.c
@@ -272,6 +272,17 @@ gs_shell_details_switch_to (GsShellDetails *shell_details)
        gs_grab_focus_when_mapped (priv->scrolledwindow_details);
 }
 
+static gboolean
+gs_shell_details_switch_to_idle (gpointer user_data)
+{
+       GsShellDetails *shell_details = GS_SHELL_DETAILS (user_data);
+
+       gs_shell_details_switch_to (shell_details);
+
+       g_object_unref (shell_details);
+       return G_SOURCE_REMOVE;
+}
+
 /**
  * gs_shell_details_notify_state_changed_cb:
  **/
@@ -280,7 +291,10 @@ gs_shell_details_notify_state_changed_cb (GsApp *app,
                                          GParamSpec *pspec,
                                          GsShellDetails *shell_details)
 {
-       gs_shell_details_switch_to (shell_details);
+       guint id;
+
+       id = g_idle_add (gs_shell_details_switch_to_idle, g_object_ref (shell_details));
+       g_source_set_name_by_id (id, "[gnome-software] gs_shell_details_switch_to_idle");
 }
 
 static void
diff --git a/src/gs-shell-installed.c b/src/gs-shell-installed.c
index 0695993..8dd2d03 100644
--- a/src/gs-shell-installed.c
+++ b/src/gs-shell-installed.c
@@ -200,6 +200,17 @@ gs_shell_installed_app_remove_cb (GsAppRow *app_row,
        gtk_widget_destroy (dialog);
 }
 
+static gboolean
+gs_shell_installed_invalidate_sort_idle (gpointer user_data)
+{
+       GsShellInstalled *shell = GS_SHELL_INSTALLED (user_data);
+
+       gtk_list_box_invalidate_sort (GTK_LIST_BOX (shell->priv->list_box_install));
+
+       g_object_unref (shell);
+       return G_SOURCE_REMOVE;
+}
+
 /**
  * gs_shell_installed_notify_state_changed_cb:
  **/
@@ -208,7 +219,10 @@ gs_shell_installed_notify_state_changed_cb (GsApp *app,
                                            GParamSpec *pspec,
                                            GsShellInstalled *shell)
 {
-       gtk_list_box_invalidate_sort (GTK_LIST_BOX (shell->priv->list_box_install));
+       guint id;
+
+       id = g_idle_add (gs_shell_installed_invalidate_sort_idle, g_object_ref (shell));
+       g_source_set_name_by_id (id, "[gnome-software] gs_shell_installed_invalidate_sort_idle");
 }
 
 static void selection_changed (GsShellInstalled *shell);


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