After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 773636 - Overriding a .desktop file does no refresh the applications list
Overriding a .desktop file does no refresh the applications list
Status: RESOLVED FIXED
Product: gnome-shell
Classification: Core
Component: app-switcher
3.12.x
Other Linux
: Normal normal
: ---
Assigned To: gnome-shell-maint
gnome-shell-maint
Depends on:
Blocks:
 
 
Reported: 2016-10-28 14:54 UTC by Adrian Perez
Modified: 2017-01-23 23:26 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Crude patch to always refresh info from .desktop files (1.12 KB, patch)
2016-11-07 16:33 UTC, Adrian Perez
none Details | Review
Properly detect changes in .desktop files (2.76 KB, patch)
2016-11-07 19:06 UTC, Adrian Perez
none Details | Review
Properly detect changes in .desktop files (v2) (2.42 KB, patch)
2016-11-07 23:50 UTC, Adrian Perez
none Details | Review
Properly detect changes in .desktop files (v3) (2.33 KB, patch)
2016-11-11 23:26 UTC, Adrian Perez
accepted-commit_now Details | Review
Properly detect changes in .desktop files (v4) (2.28 KB, patch)
2017-01-23 19:36 UTC, Adrian Perez
committed Details | Review

Description Adrian Perez 2016-10-28 14:54:21 UTC
According to the XDG desktop file specification, a .desktop file in
the user directory at “~/.local/share/applications/” with the same name
as the one in the at “/usr/share/applications” must override the one
provided by the system. So far, so good, and GNOME Shell does that, with
one issue: copying a system .destop file, editing it, and then putting the
copy in the user directory does not work, and the Shell keeps using the
information from the system-wide file.

Steps to reproduce
------------------

1. Run the following command:
   % sed -e 's/^Exec=/Exec=zenity --error --text=ItWorks/' \
         /usr/share/applications/inkscape.desktop \
      > ~/.local/share/applications/inkscape.desktop

2. Open the overview, search fo InkScape.

3. Click on the InkScape icon.


Expected Outcome
----------------

The modified command is used, and an error window is shown by Zenity
with the “ItWorks” text in it.


Actual Outcome
--------------

InkScape is executed normally.


Additional Information
----------------------

After restarting the shell (e.g. with Alt-F2 + “r”, or logging out and
in again), the modified .desktop file is used from the home directory.
In general, any edition in the user directory is missed by the Shell.
Comment 1 Adrian Perez 2016-10-28 15:27:14 UTC
For the sake of completeness: editing the file in some other location
and then moving it into the destination (to ensure that the shell never
sees a half-written, broken file) does no work either — that would be:

  % sed -e 's/^Exec=/Exec=zenity --error --text=ItWorks' \
        /usr/share/applications/inkscape.desktop > ~/inkscape.desktop
  % mv ~/inkscape.desktop ~/.local/share/applications

(Renaming a file inside the same file system is an atomic operation.)
Comment 2 Adrian Perez 2016-10-28 15:45:09 UTC
Interestingly enough, changing the “Icon=” field makes the Shell notice
invalidate its cache of applications, and the icon shows changed in the
overview. I am looking at making a patch for this, so changes in other
fields also cause the Shell to invalidate all the cached data for a
modified “.desktop” file.
Comment 3 Adrian Perez 2016-11-07 16:33:31 UTC
Created attachment 339260 [details] [review]
Crude patch to always refresh info from .desktop files

I have been investigating this, and the problem is that the cached
application infos in ShellAppSystem (src/shell-app-system.c) are not
properly invalidated when “.desktop” files which override the system
ones are moved into/out of “~/.local/share/applications”, or when the
“Exec=” line changes.

The attached patch is very crude and probably we don't want to merge
it as-is, but when applied it makes the shell pick all changes properly
because it completely nukes the cache when changes are detected.
Comment 4 Adrian Perez 2016-11-07 19:06:34 UTC
Created attachment 339271 [details] [review]
Properly detect changes in .desktop files

Instead of nuking the whole hash table like the old patch did, this just
causes removal of the ShellApp objects for which one of the following has
changed:

 * Filename of the .desktop file (covers the case of overriding with a
   file in ~/.local/share/applications).
 * Visibility of the application (g_app_info_should_show()).
 * Executable.
 * Command line.
 * Application name.
 * Displayed name.
 * Application description.
 * Application icon.
Comment 5 Michael Catanzaro 2016-11-07 20:39:37 UTC
Review of attachment 339271 [details] [review]:

Thanks for working on this.

This is just a couple preliminary comments; you'll need to wait for a shell maintainer to review it as well:

::: src/shell-app-system.c
@@ +112,3 @@
+/* Same as g_str_equal(), but NULLs are taken into account. */
+static inline gboolean
+nullable_str_equal (const gchar *a, const gchar *b)

You should use g_strcmp0

@@ +138,1 @@
+  old = shell_app_get_app_info (app);

This is leaked
Comment 6 Adrian Perez 2016-11-07 22:17:52 UTC
(In reply to Michael Catanzaro from comment #5)
> Review of attachment 339271 [details] [review] [review]:
> 
> Thanks for working on this.
> 
> This is just a couple preliminary comments; you'll need to wait for a shell
> maintainer to review it as well:
> 
> ::: src/shell-app-system.c
> @@ +112,3 @@
> +/* Same as g_str_equal(), but NULLs are taken into account. */
> +static inline gboolean
> +nullable_str_equal (const gchar *a, const gchar *b)
> 
> You should use g_strcmp0

Ah, nice one, I didn't know tht GLib already had such an utility function.
I will update the patch to use it :-)
 
> @@ +138,1 @@
> +  old = shell_app_get_app_info (app);
> 
> This is leaked

Not quite: If you check “src/shell-app.c” (lines 1276-1287), you will
see that the return value for “shell_app_get_app_info()” is annotated as
“transfer none” — and indeed its code returns the pointer directly.
Comment 7 Adrian Perez 2016-11-07 23:50:35 UTC
Created attachment 339291 [details] [review]
Properly detect changes in .desktop files (v2)

Updated patch to use “strcmp()” and “g_strcmp0()” as suggested by
Michael. Also, I moved the function to compare icons inline, as it
used only once.
Comment 8 Cosimo Cecchi 2016-11-08 02:03:17 UTC
Review of attachment 339291 [details] [review]:

::: src/shell-app-system.c
@@ +132,1 @@
+  is_unchanged =

There's a part of me that wishes g_app_info_equal() did all of these checks instead...
Comment 9 Adrian Perez 2016-11-08 11:02:23 UTC
(In reply to Cosimo Cecchi from comment #8)
> Review of attachment 339291 [details] [review] [review]:
> 
> ::: src/shell-app-system.c
> @@ +132,1 @@
> +  is_unchanged =
> 
> There's a part of me that wishes g_app_info_equal() did all of these checks
> instead...

That was my first attempt, to end up noticing that it didn't work, then
checking its implementation it turned out that g_app_info_equal() only
compares the application identifier :-\
Comment 10 Florian Müllner 2016-11-10 15:36:59 UTC
Review of attachment 339291 [details] [review]:

::: src/shell-app-system.c
@@ +133,3 @@
+    g_app_info_should_show (old_info) == g_app_info_should_show (new_info) &&
+    strcmp (g_desktop_app_info_get_filename (old),
+            g_desktop_app_info_get_filename (info)) == 0 &&

Clearly not wrong, but do we care?

@@ +135,3 @@
+            g_desktop_app_info_get_filename (info)) == 0 &&
+    strcmp (g_app_info_get_executable (old_info),
+            g_app_info_get_executable (new_info)) == 0 &&

Should use g_strcmp0 (the property is set from the commandline if available, so if you account for the latter being unset, you should do the same here)

@@ +141,3 @@
+            g_app_info_get_name (new_info)) == 0 &&
+    strcmp (g_app_info_get_display_name (old_info),
+            g_app_info_get_display_name (new_info)) == 0 &&

OK, though not actually used

@@ +143,3 @@
+            g_app_info_get_display_name (new_info)) == 0 &&
+    g_strcmp0 (g_app_info_get_description (old_info),
+               g_app_info_get_description (new_info)) == 0 &&

Dto.

@@ +144,3 @@
+    g_strcmp0 (g_app_info_get_description (old_info),
+               g_app_info_get_description (new_info)) == 0 &&
+    (old_icon == new_icon || (old_icon && g_icon_equal (old_icon, new_icon)));

It is odd to handle old_icon == NULL, but not new_icon == NULL. This should really just be g_icon_equal (old_icon, new_icon) though, as the method handles NULL just fine (https://git.gnome.org//browse/glib/tree/gio/gicon.c#n121)
Comment 11 Adrian Perez 2016-11-10 16:06:14 UTC
(In reply to Florian Müllner from comment #10)
> Review of attachment 339291 [details] [review] [review]:
> 
> ::: src/shell-app-system.c
> @@ +133,3 @@
> +    g_app_info_should_show (old_info) == g_app_info_should_show (new_info)
> &&
> +    strcmp (g_desktop_app_info_get_filename (old),
> +            g_desktop_app_info_get_filename (info)) == 0 &&
> 
> Clearly not wrong, but do we care?

Yes, this covers the case in which a file with the same identifier (for
example “inkscape.desktop”) gets copied over ~/.local/share/applications
with the intention of overriding some field from the system-installed
version. Of course if some other field changed, the info will be updated
anyway because some other comparison should fail, but if the file in the
user directory is a copy of the system-wide one, it still feels to me
more correct to have the Shell pointing to the version in the user
directory.

I guess we could drop this check, if you would prefer that.

> @@ +135,3 @@
> +            g_desktop_app_info_get_filename (info)) == 0 &&
> +    strcmp (g_app_info_get_executable (old_info),
> +            g_app_info_get_executable (new_info)) == 0 &&
> 
> Should use g_strcmp0 (the property is set from the commandline if available,
> so if you account for the latter being unset, you should do the same here)

Ack, I'll update the patch.

> @@ +141,3 @@
> +            g_app_info_get_name (new_info)) == 0 &&
> +    strcmp (g_app_info_get_display_name (old_info),
> +            g_app_info_get_display_name (new_info)) == 0 &&
> 
> OK, though not actually used

Even if display names are not used by the shell, it seems more correct (and
future proof) to check them. Provided that they are less likely be changed,
maybe it's good to make this comparison the last one.

> @@ +143,3 @@
> +            g_app_info_get_display_name (new_info)) == 0 &&
> +    g_strcmp0 (g_app_info_get_description (old_info),
> +               g_app_info_get_description (new_info)) == 0 &&
> 
> Dto.
> 
> @@ +144,3 @@
> +    g_strcmp0 (g_app_info_get_description (old_info),
> +               g_app_info_get_description (new_info)) == 0 &&
> +    (old_icon == new_icon || (old_icon && g_icon_equal (old_icon,
> new_icon)));
> 
> It is odd to handle old_icon == NULL, but not new_icon == NULL. This should
> really just be g_icon_equal (old_icon, new_icon) though, as the method
> handles NULL just fine
> (https://git.gnome.org//browse/glib/tree/gio/gicon.c#n121)

Good point, I'll change this to just call out to g_icon_equal().

One question: would it make sense to move these comparisons into
g_app_info_equal()? It was shocking to check its code after quite some
debugging to see that it only compares the identifier.
Comment 12 Florian Müllner 2016-11-10 16:17:28 UTC
(In reply to Adrian Perez from comment #11)
> (In reply to Florian Müllner from comment #10)
> > Clearly not wrong, but do we care?
> 
> Yes, this covers the case in which a file with the same identifier (for
> example “inkscape.desktop”) gets copied over ~/.local/share/applications
> with the intention of overriding some field from the system-installed
> version.

I get that, the question is why we care where the information comes from (as long as it's identical). Obviously once you start changing the copy, we want to pick up those changes (which is handled by the remaining bits).

But as I said, I don't really mind the check being there ...


> One question: would it make sense to move these comparisons into
> g_app_info_equal()? It was shocking to check its code after quite some
> debugging to see that it only compares the identifier.

That's what Cosimo was getting at in comment #8.
Comment 13 Adrian Perez 2016-11-11 23:26:56 UTC
Created attachment 339674 [details] [review]
Properly detect changes in .desktop files (v3)

I have posted a patch for “g_app_info_equals()”, in bug #774302.

I am posting here an updated patch for the Shell. We can wait a bit and
see what feedback the GIO patch gets, or have this in the Shell first
and change later to use “g_app_info_equals()” when/if that gets fixed.
Comment 14 Michael Catanzaro 2017-01-20 21:57:22 UTC
It got no reaction. We should probably land this in the meantime, since we're going to need it on GNOME 3.22 anyway as I doubt that commit is going to be backported in GIO.
Comment 15 Adrian Perez 2017-01-21 19:49:33 UTC
(In reply to Michael Catanzaro from comment #14)
> It got no reaction. We should probably land this in the meantime, since
> we're going to need it on GNOME 3.22 anyway as I doubt that commit is going
> to be backported in GIO.

I also think it would be good to have this landed in GNOME Shell while there
is no response from the GIO developers. A version of this patch has been in
eos-desktop since last November, and it has been working perfectly ever since
(https://github.com/endlessm/eos-desktop/pull/196), so there shouldn't be
any risk in landing this in GNOME Shell, too.
Comment 16 Florian Müllner 2017-01-23 16:05:48 UTC
Review of attachment 339674 [details] [review]:

(In reply to Adrian Perez from comment #15)
> I also think it would be good to have this landed in GNOME Shell

Fine by me.

::: src/shell-app-system.c
@@ +121,3 @@
 
+  if (!(info = g_desktop_app_info_new (shell_app_get_id (app))))
+    return TRUE;

I had to read this twice to confirm that there's no memory leak here, so I'd prefer different statements for assignment and NULL check.
Comment 17 Adrian Perez 2017-01-23 19:36:54 UTC
Created attachment 344068 [details] [review]
Properly detect changes in .desktop files (v4)

New patch version uploaded, addresses Florian's comment by splitting
variable initialization out of the condition of the “if” statement.
Comment 18 Florian Müllner 2017-01-23 22:46:58 UTC
In case you are waiting for a comment from me (you already set the patch status), feel free to push to master and gnome-3-22.