[gnome-shell/eos3.8: 127/255] appDisplay: compare possibly-changed apps more thoroughly



commit b306020e9831559d91cacc083bad7c5083a42826
Author: Will Thompson <wjt endlessm com>
Date:   Wed Sep 26 15:20:56 2018 +0100

    appDisplay: compare possibly-changed apps more thoroughly
    
    AllView monitors ShellAppSystem::installed-changed, which indicates that
    1 or more .desktop files have been added, removed, or changed, and
    queues a call to _redisplay(). Since no 'force' parameter is
    passed to BaseAppView._redisplay() in this case, it calls
    BaseAppView.iconsNeedRedraw() to decide whether anything has actually
    changed. That method checks for any (re)moved items, and if there are
    none, compares the old and new versions of each item.
    
    However, it previously only compared their name and their icon (name).
    This meant that changes to (for example) the Exec= line of a .desktop
    file would not be picked up until something else (such as a logout and
    login) causes the grid to be refreshed. In the case of a
    backwards-incompatible change to the application's command-line
    arguments, this would break launching the updated app from the icon
    grid.
    
    2019-10-03: adapt checks to new upstream code
    
    https://phabricator.endlessm.com/T23877

 js/ui/appDisplay.js    | 30 +++++++++++++++++++++++++-----
 src/shell-app-system.c | 43 +++++++++++++++++++++++++++++++++++++++++++
 src/shell-app-system.h |  2 ++
 3 files changed, 70 insertions(+), 5 deletions(-)
---
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index d0bf322b81..03b103067f 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -177,13 +177,33 @@ var BaseAppView = GObject.registerClass({
 
     _redisplay() {
         let oldApps = this._orderedItems.slice();
-        let oldAppIds = oldApps.map(icon => icon.id);
-
         let newApps = this._loadApps();
-        let newAppIds = newApps.map(icon => icon.id);
 
-        let addedApps = newApps.filter(icon => !oldAppIds.includes(icon.id));
-        let removedApps = oldApps.filter(icon => !newAppIds.includes(icon.id));
+        let compareIcons = (itemA, itemB) => {
+            if ((itemA instanceof AppIcon) !== (itemB instanceof AppIcon))
+                return false;
+
+            if (itemA.name !== itemB.name)
+                return false;
+
+            if (itemA.id !== itemB.id)
+                return false;
+
+            if ((itemA instanceof AppIcon) &&
+                (itemB instanceof AppIcon) &&
+                !Shell.AppSystem.app_info_equal(itemA.app.get_app_info(), itemB.app.get_app_info()))
+                return false;
+
+            return true;
+        };
+
+        let addedApps = newApps.filter(icon => {
+            return !oldApps.some(oldIcon => compareIcons(oldIcon, icon));
+        });
+
+        let removedApps = oldApps.filter(icon => {
+            return !newApps.some(newIcon => compareIcons(newIcon, icon));
+        });
 
         // Remove old app icons
         removedApps.forEach(icon => {
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index aa957ae575..2794cc3d14 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -206,6 +206,49 @@ scan_startup_wm_class_to_id (ShellAppSystem *self)
     }
 }
 
+/**
+ * shell_app_system_app_info_equal:
+ * @one: (transfer none): a #GDesktopAppInfo
+ * @two: (transfer none): a possibly-different #GDesktopAppInfo
+ *
+ * Returns %TRUE if @one and @two can be treated as equal. Compared to
+ * g_app_info_equal(), which just compares app IDs, this function also compares
+ * fields of interest to the shell: icon, name, description, executable, and
+ * should_show().
+ *
+ * Returns: %TRUE if @one and @two are equivalent; %FALSE otherwise
+ */
+gboolean
+shell_app_system_app_info_equal (GDesktopAppInfo *one,
+                                 GDesktopAppInfo *two)
+{
+  GAppInfo *one_info, *two_info;
+
+  g_return_val_if_fail (G_IS_DESKTOP_APP_INFO (one), FALSE);
+  g_return_val_if_fail (G_IS_DESKTOP_APP_INFO (two), FALSE);
+
+  one_info = G_APP_INFO (one);
+  two_info = G_APP_INFO (two);
+
+  return
+    g_app_info_equal (one_info, two_info) &&
+    g_app_info_should_show (one_info) == g_app_info_should_show (two_info) &&
+    g_strcmp0 (g_desktop_app_info_get_filename (one),
+               g_desktop_app_info_get_filename (two)) == 0 &&
+    g_strcmp0 (g_app_info_get_executable (one_info),
+               g_app_info_get_executable (two_info)) == 0 &&
+    g_strcmp0 (g_app_info_get_commandline (one_info),
+               g_app_info_get_commandline (two_info)) == 0 &&
+    g_strcmp0 (g_app_info_get_name (one_info),
+               g_app_info_get_name (two_info)) == 0 &&
+    g_strcmp0 (g_app_info_get_description (one_info),
+               g_app_info_get_description (two_info)) == 0 &&
+    g_strcmp0 (g_app_info_get_display_name (one_info),
+               g_app_info_get_display_name (two_info)) == 0 &&
+    g_icon_equal (g_app_info_get_icon (one_info),
+                  g_app_info_get_icon (two_info));
+}
+
 static gboolean
 app_is_stale (ShellApp *app)
 {
diff --git a/src/shell-app-system.h b/src/shell-app-system.h
index 7d669745f0..32db6bf3b1 100644
--- a/src/shell-app-system.h
+++ b/src/shell-app-system.h
@@ -33,4 +33,6 @@ GList          *shell_app_system_get_installed             (ShellAppSystem  *sel
 
 gboolean        shell_app_system_has_starting_apps         (ShellAppSystem  *self);
 
+gboolean        shell_app_system_app_info_equal            (GDesktopAppInfo *one,
+                                                            GDesktopAppInfo *two);
 #endif /* __SHELL_APP_SYSTEM_H__ */


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