diff --git a/nixos/modules/services/desktops/flatpak.nix b/nixos/modules/services/desktops/flatpak.nix
index d191eeff990f..23480e652675 100644
--- a/nixos/modules/services/desktops/flatpak.nix
+++ b/nixos/modules/services/desktops/flatpak.nix
@@ -3,26 +3,45 @@
with lib;
-{
+let
+ cfg = config.services.flatpak;
+in {
###### interface
options = {
services.flatpak = {
enable = mkEnableOption "flatpak";
+
+ extraPortals = mkOption {
+ type = types.listOf types.package;
+ default = [];
+ description = ''
+ List of additional portals to add to path. Portals allow interaction
+ with system, like choosing files or taking screenshots. At minimum,
+ a desktop portal implementation should be listed. GNOME already
+ adds xdg-desktop-portal-gtk; for KDE, there
+ is xdg-desktop-portal-kde. Other desktop
+ environments will probably want to do the same.
+ '';
+ };
};
};
###### implementation
- config = mkIf config.services.flatpak.enable {
+ config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.flatpak ];
- services.dbus.packages = [ pkgs.flatpak ];
+ services.dbus.packages = [ pkgs.flatpak pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
- systemd.packages = [ pkgs.flatpak ];
+ systemd.packages = [ pkgs.flatpak pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
- environment.variables.PATH = [
- "$HOME/.local/share/flatpak/exports/bin"
- "/var/lib/flatpak/exports/bin"
- ];
+ environment.variables = {
+ PATH = [
+ "$HOME/.local/share/flatpak/exports/bin"
+ "/var/lib/flatpak/exports/bin"
+ ];
+
+ XDG_DESKTOP_PORTAL_PATH = map (p: "${p}/share/xdg-desktop-portal/portals") cfg.extraPortals;
+ };
};
}
diff --git a/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixos/modules/services/x11/desktop-managers/gnome3.nix
index 10e8ef0ed381..27b62df7097c 100644
--- a/nixos/modules/services/x11/desktop-managers/gnome3.nix
+++ b/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -120,6 +120,7 @@ in {
services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
services.udev.packages = [ pkgs.gnome3.gnome-settings-daemon ];
systemd.packages = [ pkgs.gnome3.vino ];
+ services.flatpak.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
# If gnome3 is installed, build vim for gtk3 too.
nixpkgs.config.vim.gui = "gtk3";
diff --git a/pkgs/development/libraries/xdg-desktop-portal/default.nix b/pkgs/development/libraries/xdg-desktop-portal/default.nix
index 6721d5f00acb..98bd8ba23bb5 100644
--- a/pkgs/development/libraries/xdg-desktop-portal/default.nix
+++ b/pkgs/development/libraries/xdg-desktop-portal/default.nix
@@ -14,6 +14,10 @@ in stdenv.mkDerivation rec {
sha256 = "06gipd51snvlp2jp68v2c8rwbsv36kjzg9xacm81n1w4b2dpz4g0";
};
+ patches = [
+ ./respect-path-env-var.patch
+ ];
+
nativeBuildInputs = [ autoreconfHook pkgconfig libxml2 ];
buildInputs = [ glib pipewire fuse ];
diff --git a/pkgs/development/libraries/xdg-desktop-portal/respect-path-env-var.patch b/pkgs/development/libraries/xdg-desktop-portal/respect-path-env-var.patch
new file mode 100644
index 000000000000..f884899ecd19
--- /dev/null
+++ b/pkgs/development/libraries/xdg-desktop-portal/respect-path-env-var.patch
@@ -0,0 +1,76 @@
+--- a/src/xdg-desktop-portal.c
++++ b/src/xdg-desktop-portal.c
+@@ -177,38 +177,50 @@
+ static void
+ load_installed_portals (void)
+ {
+- const char *portal_dir = PKGDATADIR "/portals";
+- g_autoptr(GFile) dir = g_file_new_for_path (portal_dir);
+- g_autoptr(GFileEnumerator) enumerator = NULL;
+
+- enumerator = g_file_enumerate_children (dir, "*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
++ g_auto(GStrv) portal_dir_list;
++ int i;
++ const char *portal_dir = g_getenv ("XDG_DESKTOP_PORTAL_PATH");
++
++ if (portal_dir == NULL)
++ portal_dir = PKGDATADIR "/portals";
+
+- if (enumerator == NULL)
+- return;
++ portal_dir_list = g_strsplit (portal_dir, G_SEARCHPATH_SEPARATOR_S, 0);
+
+- while (TRUE)
++ for (i = 0; portal_dir_list[i] != NULL; i++)
+ {
+- g_autoptr(GFileInfo) info = g_file_enumerator_next_file (enumerator, NULL, NULL);
+- g_autoptr(GFile) child = NULL;
+- g_autofree char *path = NULL;
+- const char *name;
+- g_autoptr(GError) error = NULL;
++ portal_dir = portal_dir_list[i];
++ g_autoptr(GFile) dir = g_file_new_for_path (portal_dir);
++ g_autoptr(GFileEnumerator) enumerator = NULL;
++ enumerator = g_file_enumerate_children (dir, "*", G_FILE_QUERY_INFO_NONE, NULL, NULL);
+
+- if (info == NULL)
+- break;
++ if (enumerator == NULL)
++ continue;
+
+- name = g_file_info_get_name (info);
++ while (TRUE)
++ {
++ g_autoptr(GFileInfo) info = g_file_enumerator_next_file (enumerator, NULL, NULL);
++ g_autoptr(GFile) child = NULL;
++ g_autofree char *path = NULL;
++ const char *name;
++ g_autoptr(GError) error = NULL;
+
+- if (!g_str_has_suffix (name, ".portal"))
+- continue;
++ if (info == NULL)
++ break;
+
+- child = g_file_enumerator_get_child (enumerator, info);
+- path = g_file_get_path (child);
++ name = g_file_info_get_name (info);
+
+- if (!register_portal (path, &error))
+- {
+- g_warning ("Error loading %s: %s", path, error->message);
+- continue;
++ if (!g_str_has_suffix (name, ".portal"))
++ continue;
++
++ child = g_file_enumerator_get_child (enumerator, info);
++ path = g_file_get_path (child);
++
++ if (!register_portal (path, &error))
++ {
++ g_warning ("Error loading %s: %s", path, error->message);
++ continue;
++ }
+ }
+ }
+