1{
2 config,
3 lib,
4 utils,
5 pkgs,
6 ...
7}:
8
9with lib;
10
11let
12
13 cfg = config.services.desktopManager.pantheon;
14 serviceCfg = config.services.pantheon;
15
16 nixos-gsettings-desktop-schemas = pkgs.pantheon.elementary-gsettings-schemas.override {
17 extraGSettingsOverridePackages = cfg.extraGSettingsOverridePackages;
18 extraGSettingsOverrides = cfg.extraGSettingsOverrides;
19 };
20
21 notExcluded = pkg: utils.disablePackageByName pkg config.environment.pantheon.excludePackages;
22in
23
24{
25
26 meta = {
27 doc = ./pantheon.md;
28 maintainers = teams.pantheon.members;
29 };
30
31 imports = [
32 (lib.mkRenamedOptionModule
33 [ "services" "xserver" "desktopManager" "pantheon" ]
34 [ "services" "desktopManager" "pantheon" ]
35 )
36 ];
37
38 options = {
39
40 services.pantheon = {
41
42 contractor = {
43 enable = mkEnableOption "contractor, a desktop-wide extension service used by Pantheon";
44 };
45
46 apps.enable = mkEnableOption "Pantheon default applications";
47
48 };
49
50 services.desktopManager.pantheon = {
51 enable = mkOption {
52 type = types.bool;
53 default = false;
54 description = "Enable the pantheon desktop manager";
55 };
56
57 sessionPath = mkOption {
58 default = [ ];
59 type = types.listOf types.package;
60 example = literalExpression "[ pkgs.gpaste ]";
61 description = ''
62 Additional list of packages to be added to the session search path.
63 Useful for GSettings-conditional autostart.
64
65 Note that this should be a last resort; patching the package is preferred (see GPaste).
66 '';
67 };
68
69 extraWingpanelIndicators = mkOption {
70 default = null;
71 type = with types; nullOr (listOf package);
72 description = "Indicators to add to Wingpanel.";
73 };
74
75 extraSwitchboardPlugs = mkOption {
76 default = null;
77 type = with types; nullOr (listOf package);
78 description = "Plugs to add to Switchboard.";
79 };
80
81 extraGSettingsOverrides = mkOption {
82 default = "";
83 type = types.lines;
84 description = "Additional gsettings overrides.";
85 };
86
87 extraGSettingsOverridePackages = mkOption {
88 default = [ ];
89 type = types.listOf types.path;
90 description = "List of packages for which gsettings are overridden.";
91 };
92
93 debug = mkEnableOption "gnome-session debug messages";
94
95 };
96
97 environment.pantheon.excludePackages = mkOption {
98 default = [ ];
99 example = literalExpression "[ pkgs.pantheon.elementary-camera ]";
100 type = types.listOf types.package;
101 description = "Which packages pantheon should exclude from the default environment";
102 };
103
104 };
105
106 config = mkMerge [
107 (mkIf cfg.enable {
108 services.desktopManager.pantheon.sessionPath = utils.removePackagesByName [
109 pkgs.pantheon.pantheon-agent-geoclue2
110 ] config.environment.pantheon.excludePackages;
111
112 services.displayManager.sessionPackages = [ pkgs.pantheon.elementary-session-settings ];
113
114 # Ensure lightdm is used when Pantheon is enabled
115 # Without it screen locking will be nonfunctional because of the use of lightlocker
116 warnings = optional (config.services.xserver.displayManager.lightdm.enable != true) ''
117 Using Pantheon without LightDM as a displayManager will break screenlocking from the UI.
118 '';
119
120 services.xserver.displayManager.lightdm.greeters.pantheon.enable = mkDefault true;
121
122 # Without this, elementary LightDM greeter will pre-select non-existent `default` session
123 # https://github.com/elementary/greeter/issues/368
124 services.displayManager.defaultSession = mkDefault "pantheon-wayland";
125 programs.dconf.profiles.user.databases = [
126 {
127 settings."io/elementary/greeter" = {
128 last-session-type = "pantheon-wayland";
129 };
130 }
131 ];
132
133 environment.extraInit = ''
134 ${concatMapStrings (p: ''
135 if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
136 export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
137 fi
138
139 if [ -d "${p}/lib/girepository-1.0" ]; then
140 export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
141 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
142 fi
143 '') cfg.sessionPath}
144 '';
145
146 # Default services
147 hardware.bluetooth.enable = mkDefault true;
148 security.polkit.enable = true;
149 services.accounts-daemon.enable = true;
150 services.colord.enable = mkDefault true;
151 services.fwupd.enable = mkDefault true;
152 # TODO: Enable once #177946 is resolved
153 # services.packagekit.enable = mkDefault true;
154 services.power-profiles-daemon.enable = mkDefault true;
155 services.touchegg.enable = mkDefault true;
156 services.touchegg.package = pkgs.pantheon.touchegg;
157 services.tumbler.enable = mkDefault true;
158 services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
159 services.dbus.packages = with pkgs.pantheon; [
160 switchboard-plug-power
161 elementary-default-settings # accountsservice extensions
162 ];
163 services.pantheon.apps.enable = mkDefault true;
164 services.pantheon.contractor.enable = mkDefault true;
165 services.gnome.at-spi2-core.enable = true;
166 services.gnome.evolution-data-server.enable = true;
167 services.gnome.glib-networking.enable = true;
168 services.gnome.gnome-keyring.enable = true;
169 services.gnome.gcr-ssh-agent.enable = mkDefault true;
170 services.gvfs.enable = true;
171 services.gnome.rygel.enable = mkDefault true;
172 services.udisks2.enable = true;
173 services.upower.enable = config.powerManagement.enable;
174 services.libinput.enable = mkDefault true;
175 services.switcherooControl.enable = mkDefault true;
176 services.zeitgeist.enable = mkDefault true;
177 services.geoclue2.enable = mkDefault true;
178 # pantheon has pantheon-agent-geoclue2
179 services.geoclue2.enableDemoAgent = false;
180 services.geoclue2.appConfig."io.elementary.desktop.agent-geoclue2" = {
181 isAllowed = true;
182 isSystem = true;
183 };
184 services.udev.packages = [
185 pkgs.pantheon.gnome-settings-daemon
186 # Force enable KMS modifiers for devices that require them.
187 # https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1443
188 pkgs.pantheon.mutter
189 ];
190 services.orca.enable = mkDefault (notExcluded pkgs.orca);
191 systemd.packages = with pkgs; [
192 gnome-session
193 pantheon.gala
194 pantheon.gnome-settings-daemon
195 pantheon.elementary-session-settings
196 ];
197 programs.dconf.enable = true;
198 networking.networkmanager.enable = mkDefault true;
199
200 systemd.user.targets."gnome-session-x11-services".wants = [
201 "org.gnome.SettingsDaemon.XSettings.service"
202 ];
203 systemd.user.targets."gnome-session-x11-services-ready".wants = [
204 "org.gnome.SettingsDaemon.XSettings.service"
205 ];
206
207 # Global environment
208 environment.systemPackages =
209 (with pkgs.pantheon; [
210 elementary-bluetooth-daemon
211 elementary-session-settings
212 elementary-settings-daemon
213 gala
214 gnome-settings-daemon
215 (switchboard-with-plugs.override {
216 plugs = cfg.extraSwitchboardPlugs;
217 })
218 (wingpanel-with-indicators.override {
219 indicators = cfg.extraWingpanelIndicators;
220 })
221 ])
222 ++ utils.removePackagesByName (
223 (with pkgs; [
224 desktop-file-utils
225 glib # for gsettings program
226 gnome-menus
227 adwaita-icon-theme
228 gtk3.out # for gtk-launch program
229 onboard
230 sound-theme-freedesktop
231 xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
232 ])
233 ++ (with pkgs.pantheon; [
234 # Artwork
235 elementary-gtk-theme
236 elementary-icon-theme
237 elementary-sound-theme
238 elementary-wallpapers
239
240 # Desktop
241 elementary-default-settings
242 elementary-dock
243 elementary-shortcut-overlay
244
245 # Services
246 elementary-capnet-assist
247 elementary-notifications
248 pantheon-agent-geoclue2
249 pantheon-agent-polkit
250 ])
251 ) config.environment.pantheon.excludePackages;
252
253 # Settings from elementary-default-settings
254 # GTK4 will try both $XDG_CONFIG_DIRS/gtk-4.0 and ${gtk4}/etc/gtk-4.0, but not /etc/gtk-4.0.
255 environment.etc."xdg/gtk-4.0/settings.ini".source =
256 "${pkgs.pantheon.elementary-default-settings}/etc/gtk-4.0/settings.ini";
257
258 xdg.mime.enable = true;
259 xdg.icons.enable = true;
260
261 xdg.portal.enable = true;
262 xdg.portal.extraPortals = [
263 pkgs.xdg-desktop-portal-gtk
264 ]
265 ++ (with pkgs.pantheon; [
266 elementary-files
267 elementary-settings-daemon
268 xdg-desktop-portal-pantheon
269 ]);
270
271 xdg.portal.configPackages = mkDefault [ pkgs.pantheon.elementary-default-settings ];
272
273 # Override GSettings schemas
274 environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
275
276 environment.sessionVariables.GNOME_SESSION_DEBUG = mkIf cfg.debug "1";
277
278 environment.pathsToLink = [
279 # FIXME: modules should link subdirs of `/share` rather than relying on this
280 "/share"
281 ];
282
283 # Otherwise you can't store NetworkManager Secrets with
284 # "Store the password only for this user"
285 programs.nm-applet.enable = true;
286 # Pantheon has its own network indicator
287 programs.nm-applet.indicator = false;
288
289 # Shell integration for VTE terminals
290 programs.bash.vteIntegration = mkDefault true;
291 programs.zsh.vteIntegration = mkDefault true;
292
293 # Default Fonts
294 fonts.packages = with pkgs; [
295 inter
296 open-dyslexic
297 open-sans
298 roboto-mono
299 ];
300
301 fonts.fontconfig.defaultFonts = {
302 monospace = [ "Roboto Mono" ];
303 sansSerif = [ "Inter" ];
304 };
305 })
306
307 (mkIf serviceCfg.apps.enable {
308 programs.evince.enable = mkDefault (notExcluded pkgs.evince);
309 programs.file-roller.enable = mkDefault (notExcluded pkgs.file-roller);
310
311 environment.systemPackages = utils.removePackagesByName (
312 [
313 pkgs.gnome-font-viewer
314 ]
315 ++ (
316 with pkgs.pantheon;
317 [
318 elementary-calculator
319 elementary-calendar
320 elementary-camera
321 elementary-code
322 elementary-files
323 elementary-mail
324 elementary-maps
325 elementary-music
326 elementary-photos
327 elementary-screenshot
328 elementary-tasks
329 elementary-terminal
330 elementary-videos
331 epiphany
332 ]
333 ++ lib.optionals config.services.flatpak.enable [
334 # Only install appcenter if flatpak is enabled before
335 # https://github.com/NixOS/nixpkgs/issues/15932 is resolved.
336 appcenter
337 sideload
338 ]
339 )
340 ) config.environment.pantheon.excludePackages;
341
342 # needed by screenshot
343 fonts.packages = [
344 pkgs.pantheon.elementary-redacted-script
345 ];
346 })
347
348 (mkIf serviceCfg.contractor.enable {
349 environment.systemPackages = with pkgs.pantheon; [
350 contractor
351 file-roller-contract
352 ];
353
354 environment.pathsToLink = [
355 "/share/contractor"
356 ];
357 })
358
359 ];
360}