summary refs log tree commit diff
path: root/pkgs/development/libraries/glib
diff options
context:
space:
mode:
authorMax <max@privatevoid.net>2021-03-30 20:46:10 +0200
committergithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>2021-03-31 00:37:57 +0000
commit5b3f9e0d4135e622200fdcb1da773eb282e40a1d (patch)
tree5bef71eaf03a0e022e630236b1ce19c766466e30 /pkgs/development/libraries/glib
parentf3b5f40c81c084ab191e9af97f1e143adc599c7b (diff)
downloadnixpkgs-5b3f9e0d4135e622200fdcb1da773eb282e40a1d.tar
nixpkgs-5b3f9e0d4135e622200fdcb1da773eb282e40a1d.tar.gz
nixpkgs-5b3f9e0d4135e622200fdcb1da773eb282e40a1d.tar.bz2
nixpkgs-5b3f9e0d4135e622200fdcb1da773eb282e40a1d.tar.lz
nixpkgs-5b3f9e0d4135e622200fdcb1da773eb282e40a1d.tar.xz
nixpkgs-5b3f9e0d4135e622200fdcb1da773eb282e40a1d.tar.zst
nixpkgs-5b3f9e0d4135e622200fdcb1da773eb282e40a1d.zip
glib: follow profile updates when searching apps
GNOME Shell monitors XDG_DATA_DIRS for changes using inotify for the
purpose of updating the list of applications displayed in the overview
as they are installed or removed. Because the relevant directories are
symlinks under NixOS and are swapped on change, Shell never notices it.
To remedy this, also monitor various profile directories to signal an
update whenever profiles are changed.

This uses a patch from Guix, slightly modified to also encompass user
environment profiles (/etc/profiles/per-user/$USER) in addition to the
system profile (/nix/var/nix/profiles/system) as well as regular user
profiles (/nix/var/nix/profiles/per-user/$USER/profile).
Diffstat (limited to 'pkgs/development/libraries/glib')
-rw-r--r--pkgs/development/libraries/glib/default.nix1
-rw-r--r--pkgs/development/libraries/glib/glib-appinfo-watch.patch102
2 files changed, 103 insertions, 0 deletions
diff --git a/pkgs/development/libraries/glib/default.nix b/pkgs/development/libraries/glib/default.nix
index b18ce099dce..d879a0847bd 100644
--- a/pkgs/development/libraries/glib/default.nix
+++ b/pkgs/development/libraries/glib/default.nix
@@ -58,6 +58,7 @@ stdenv.mkDerivation rec {
     ./quark_init_on_demand.patch
     ./gobject_init_on_demand.patch
   ] ++ [
+    ./glib-appinfo-watch.patch
     ./schema-override-variable.patch
 
     # GLib contains many binaries used for different purposes;
diff --git a/pkgs/development/libraries/glib/glib-appinfo-watch.patch b/pkgs/development/libraries/glib/glib-appinfo-watch.patch
new file mode 100644
index 00000000000..cbd78a6db4a
--- /dev/null
+++ b/pkgs/development/libraries/glib/glib-appinfo-watch.patch
@@ -0,0 +1,102 @@
+This patch lets GLib's GDesktopAppInfo API watch and notice changes
+to the Nix user and system profiles.  That way, the list of available
+applications shown by the desktop environment is immediately updated
+when the user installs or removes any
+(see <https://issues.guix.gnu.org/35594>).
+
+It does so by monitoring /nix/var/nix/profiles (for changes to the system
+profile) and /nix/var/nix/profiles/per-user/USER (for changes to the user
+profile) as well as /etc/profiles/per-user (for chanes to the user
+environment profile) and crawling their share/applications sub-directory when
+changes happen.
+
+diff --git a/gio/gdesktopappinfo.c b/gio/gdesktopappinfo.c
+index b779b30..31069f7 100644
+--- a/gio/gdesktopappinfo.c
++++ b/gio/gdesktopappinfo.c
+@@ -150,6 +150,7 @@ typedef struct
+   gchar                      *alternatively_watching;
+   gboolean                    is_config;
+   gboolean                    is_setup;
++  gchar                      *nix_profile_watch_dir;
+   GFileMonitor               *monitor;
+   GHashTable                 *app_names;
+   GHashTable                 *mime_tweaks;
+@@ -181,6 +182,7 @@ desktop_file_dir_unref (DesktopFileDir *dir)
+     {
+       desktop_file_dir_reset (dir);
+       g_free (dir->path);
++      g_free (dir->nix_profile_watch_dir);
+       g_free (dir);
+     }
+ }
+@@ -205,6 +207,14 @@ desktop_file_dir_get_alternative_dir (DesktopFileDir *dir)
+ {
+   gchar *parent;
+ 
++  /* If DIR is a profile, watch the specified directory--e.g.,
++   * /nix/var/nix/profiles/per-user/$USER/ for the user profile.  Do not watch
++   * ~/.nix-profile or /run/current-system/sw because GFileMonitor does
++   * not pass IN_DONT_FOLLOW and thus cannot notice any change.
++   * /etc/profiles/per-user is monitored directly for the same reason. */
++  if (dir->nix_profile_watch_dir != NULL)
++    return g_strdup (dir->nix_profile_watch_dir);
++
+   /* If the directory itself exists then we need no alternative. */
+   if (g_access (dir->path, R_OK | X_OK) == 0)
+     return NULL;
+@@ -250,11 +260,11 @@ desktop_file_dir_changed (GFileMonitor      *monitor,
+    *
+    * If this is a notification for a parent directory (because the
+    * desktop directory didn't exist) then we shouldn't fire the signal
+-   * unless something actually changed.
++   * unless something actually changed or it's part of a Nix profile.
+    */
+   g_mutex_lock (&desktop_file_dir_lock);
+ 
+-  if (dir->alternatively_watching)
++  if (dir->alternatively_watching && dir->nix_profile_watch_dir == NULL)
+     {
+       gchar *alternative_dir;
+ 
+@@ -1556,6 +1566,40 @@ desktop_file_dirs_lock (void)
+       for (i = 0; dirs[i]; i++)
+         g_ptr_array_add (desktop_file_dirs, desktop_file_dir_new (dirs[i]));
+ 
++      {
++        /* Monitor the system and user profile under /nix/var/nix/profiles and
++         * treat modifications to them as if they were modifications to their
++         * /share sub-directory.  */
++        const gchar *user;
++        DesktopFileDir *system_profile_dir, *user_profile_dir, *user_env_dir;
++
++        system_profile_dir =
++          desktop_file_dir_new ("/nix/var/nix/profiles/system/sw/share");
++        system_profile_dir->nix_profile_watch_dir = g_strdup ("/nix/var/nix/profiles");
++        g_ptr_array_add (desktop_file_dirs, desktop_file_dir_ref (system_profile_dir));
++
++        user = g_get_user_name ();
++        if (user != NULL)
++          {
++            gchar *profile_dir, *user_data_dir, *env_dir, *env_data_dir;
++
++            profile_dir = g_build_filename ("/nix/var/nix/profiles/per-user", user, NULL);
++            user_data_dir = g_build_filename (profile_dir, "profile", "share", NULL);
++            user_profile_dir = desktop_file_dir_new (user_data_dir);
++            user_profile_dir->nix_profile_watch_dir = profile_dir;
++            
++            env_dir = g_build_filename ("/etc/profiles/per-user", NULL);
++            env_data_dir = g_build_filename (env_dir, user, "share", NULL);
++            user_env_dir = desktop_file_dir_new (env_data_dir);
++            user_env_dir->nix_profile_watch_dir = env_dir;
++
++            g_ptr_array_add (desktop_file_dirs, desktop_file_dir_ref (user_profile_dir));
++            g_ptr_array_add (desktop_file_dirs, desktop_file_dir_ref (user_env_dir));
++            g_free (user_data_dir);
++            g_free (env_data_dir);
++          }
++      }
++
+       /* The list of directories will never change after this, unless
+        * g_get_user_config_dir() changes due to %G_TEST_OPTION_ISOLATE_DIRS. */
+       desktop_file_dirs_config_dir = user_config_dir;