about summary refs log tree commit diff
path: root/nixpkgs/nixos/modules/config/xdg/portal.nix
blob: 2c4d07c4953cbd4881293d0db4592142003d29dc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
{ config, pkgs, lib, ... }:

let
  inherit (lib)
    mkEnableOption
    mkIf
    mkOption
    mkRenamedOptionModule
    teams
    types;

  associationOptions = with types; attrsOf (
    coercedTo (either (listOf str) str) (x: lib.concatStringsSep ";" (lib.toList x)) str
  );
in

{
  imports = [
    (mkRenamedOptionModule [ "services" "flatpak" "extraPortals" ] [ "xdg" "portal" "extraPortals" ])

    ({ config, lib, options, ... }:
      let
        from = [ "xdg" "portal" "gtkUsePortal" ];
        fromOpt = lib.getAttrFromPath from options;
      in
      {
        warnings = lib.mkIf config.xdg.portal.gtkUsePortal [
          "The option `${lib.showOption from}' defined in ${lib.showFiles fromOpt.files} has been deprecated. Setting the variable globally with `environment.sessionVariables' NixOS option can have unforeseen side-effects."
        ];
      }
    )
  ];

  meta = {
    maintainers = teams.freedesktop.members;
  };

  options.xdg.portal = {
    enable =
      mkEnableOption ''[xdg desktop integration](https://github.com/flatpak/xdg-desktop-portal)'' // {
        default = false;
      };

    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 and KDE already
        adds `xdg-desktop-portal-gtk`; and
        `xdg-desktop-portal-kde` respectively. On other desktop
        environments you probably want to add them yourself.
      '';
    };

    gtkUsePortal = mkOption {
      type = types.bool;
      visible = false;
      default = false;
      description = ''
        Sets environment variable `GTK_USE_PORTAL` to `1`.
        This will force GTK-based programs ran outside Flatpak to respect and use XDG Desktop Portals
        for features like file chooser but it is an unsupported hack that can easily break things.
        Defaults to `false` to respect its opt-in nature.
      '';
    };

    xdgOpenUsePortal = mkOption {
      type = types.bool;
      default = false;
      description = ''
        Sets environment variable `NIXOS_XDG_OPEN_USE_PORTAL` to `1`
        This will make `xdg-open` use the portal to open programs, which resolves bugs involving
        programs opening inside FHS envs or with unexpected env vars set from wrappers.
        See [#160923](https://github.com/NixOS/nixpkgs/issues/160923) for more info.
      '';
    };

    config = mkOption {
      type = types.attrsOf associationOptions;
      default = { };
      example = {
        x-cinnamon = {
          default = [ "xapp" "gtk" ];
        };
        pantheon = {
          default = [ "pantheon" "gtk" ];
          "org.freedesktop.impl.portal.Secret" = [ "gnome-keyring" ];
        };
        common = {
          default = [ "gtk" ];
        };
      };
      description = ''
        Sets which portal backend should be used to provide the implementation
        for the requested interface. For details check {manpage}`portals.conf(5)`.

        Configs will be linked to `/etx/xdg/xdg-desktop-portal/` with the name `$desktop-portals.conf`
        for `xdg.portal.config.$desktop` and `portals.conf` for `xdg.portal.config.common`
        as an exception.
      '';
    };

    configPackages = mkOption {
      type = types.listOf types.package;
      default = [ ];
      example = lib.literalExpression "[ pkgs.gnome.gnome-session ]";
      description = ''
        List of packages that provide XDG desktop portal configuration, usually in
        the form of `share/xdg-desktop-portal/$desktop-portals.conf`.

        Note that configs in `xdg.portal.config` will be preferred if set.
      '';
    };
  };

  config =
    let
      cfg = config.xdg.portal;
      packages = [ pkgs.xdg-desktop-portal ] ++ cfg.extraPortals;
    in
    mkIf cfg.enable {
      warnings = lib.optional (cfg.configPackages == [ ] && cfg.config == { }) ''
        xdg-desktop-portal 1.17 reworked how portal implementations are loaded, you
        should either set `xdg.portal.config` or `xdg.portal.configPackages`
        to specify which portal backend to use for the requested interface.

        https://github.com/flatpak/xdg-desktop-portal/blob/1.18.1/doc/portals.conf.rst.in

        If you simply want to keep the behaviour in < 1.17, which uses the first
        portal implementation found in lexicographical order, use the following:

        xdg.portal.config.common.default = "*";
      '';

      assertions = [
        {
          assertion = cfg.extraPortals != [ ];
          message = "Setting xdg.portal.enable to true requires a portal implementation in xdg.portal.extraPortals such as xdg-desktop-portal-gtk or xdg-desktop-portal-kde.";
        }
      ];

      services.dbus.packages = packages;
      systemd.packages = packages;

      environment = {
        systemPackages = packages ++ cfg.configPackages;
        pathsToLink = [
          # Portal definitions and upstream desktop environment portal configurations.
          "/share/xdg-desktop-portal"
          # .desktop files to register fallback icon and app name.
          "/share/applications"
        ];

        sessionVariables = {
          GTK_USE_PORTAL = mkIf cfg.gtkUsePortal "1";
          NIXOS_XDG_OPEN_USE_PORTAL = mkIf cfg.xdgOpenUsePortal "1";
          NIX_XDG_DESKTOP_PORTAL_DIR = "/run/current-system/sw/share/xdg-desktop-portal/portals";
        };

        etc = lib.concatMapAttrs
          (desktop: conf: lib.optionalAttrs (conf != { }) {
            "xdg/xdg-desktop-portal/${lib.optionalString (desktop != "common") "${desktop}-"}portals.conf".text =
              lib.generators.toINI { } { preferred = conf; };
          }) cfg.config;
      };
    };
}