1 { config, lib, pkgs, utils, ... }:
4 inherit (lib) mkOption types mkDefault mkEnableOption literalExpression;
6 cfg = config.services.xserver.desktopManager.gnome;
7 serviceCfg = config.services.gnome;
9 # Prioritize nautilus by default when opening directories
10 mimeAppsList = pkgs.writeTextFile {
11 name = "gnome-mimeapps";
12 destination = "/share/applications/mimeapps.list";
14 [Default Applications]
15 inode/directory=nautilus.desktop;org.gnome.Nautilus.desktop
19 defaultFavoriteAppsOverride = ''
21 favorite-apps=[ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Calendar.desktop', 'org.gnome.Music.desktop', 'org.gnome.Nautilus.desktop' ]
24 nixos-background-light = pkgs.nixos-artwork.wallpapers.simple-blue;
25 nixos-background-dark = pkgs.nixos-artwork.wallpapers.simple-dark-gray;
27 # TODO: Having https://github.com/NixOS/nixpkgs/issues/54150 would supersede this
28 nixos-gsettings-desktop-schemas = pkgs.gnome.nixos-gsettings-overrides.override {
29 inherit (cfg) extraGSettingsOverrides extraGSettingsOverridePackages favoriteAppsOverride;
30 inherit flashbackEnabled nixos-background-dark nixos-background-light;
33 nixos-background-info = pkgs.writeTextFile rec {
34 name = "nixos-background-info";
37 <!DOCTYPE wallpapers SYSTEM "gnome-wp-list.dtd">
39 <wallpaper deleted="false">
41 <filename>${nixos-background-light.gnomeFilePath}</filename>
42 <filename-dark>${nixos-background-dark.gnomeFilePath}</filename-dark>
43 <options>zoom</options>
44 <shade_type>solid</shade_type>
45 <pcolor>#3a4ba0</pcolor>
46 <scolor>#2f302f</scolor>
50 destination = "/share/gnome-background-properties/nixos.xml";
53 flashbackEnabled = cfg.flashback.enableMetacity || lib.length cfg.flashback.customSessions > 0;
54 flashbackWms = lib.optional cfg.flashback.enableMetacity {
57 wmCommand = "${pkgs.metacity}/bin/metacity";
58 enableGnomePanel = true;
59 } ++ cfg.flashback.customSessions;
61 notExcluded = pkg: mkDefault (!(lib.elem pkg config.environment.gnome.excludePackages));
69 maintainers = lib.teams.gnome.members;
75 core-os-services.enable = mkEnableOption "essential services for GNOME3";
76 core-shell.enable = mkEnableOption "GNOME Shell services";
77 core-utilities.enable = mkEnableOption "GNOME core utilities";
78 core-developer-tools.enable = mkEnableOption "GNOME core developer tools";
79 games.enable = mkEnableOption "GNOME games";
82 services.xserver.desktopManager.gnome = {
86 description = "Enable GNOME desktop manager.";
89 sessionPath = mkOption {
91 type = types.listOf types.package;
92 example = literalExpression "[ pkgs.gpaste ]";
94 Additional list of packages to be added to the session search path.
95 Useful for GNOME Shell extensions or GSettings-conditional autostart.
97 Note that this should be a last resort; patching the package is preferred (see GPaste).
101 favoriteAppsOverride = mkOption {
102 internal = true; # this is messy
103 default = defaultFavoriteAppsOverride;
105 example = literalExpression ''
108 favorite-apps=[ 'firefox.desktop', 'org.gnome.Calendar.desktop' ]
111 description = "List of desktop files to put as favorite apps into pkgs.gnome-shell. These need to be installed somehow globally.";
114 extraGSettingsOverrides = mkOption {
117 description = "Additional gsettings overrides.";
120 extraGSettingsOverridePackages = mkOption {
122 type = types.listOf types.path;
123 description = "List of packages for which gsettings are overridden.";
126 debug = mkEnableOption "pkgs.gnome-session debug messages";
129 enableMetacity = mkEnableOption "the standard GNOME Flashback session with Metacity";
131 customSessions = mkOption {
132 type = types.listOf (types.submodule {
135 type = types.strMatching "[a-zA-Z0-9_-]+";
136 description = "A unique identifier for the window manager.";
142 description = "The name of the window manager to show in the session chooser.";
146 wmCommand = mkOption {
148 description = "The executable of the window manager to use.";
149 example = literalExpression ''"''${pkgs.haskellPackages.xmonad}/bin/xmonad"'';
152 enableGnomePanel = mkOption {
156 description = "Whether to enable the GNOME panel in this session.";
161 description = "Other GNOME Flashback sessions to enable.";
164 panelModulePackages = mkOption {
165 default = [ pkgs.gnome-applets ];
166 defaultText = literalExpression "[ pkgs.gnome-applets ]";
167 type = types.listOf types.package;
169 Packages containing modules that should be made available to `pkgs.gnome-panel` (usually for applets).
171 If you're packaging something to use here, please install the modules in `$out/lib/gnome-panel/modules`.
177 environment.gnome.excludePackages = mkOption {
179 example = literalExpression "[ pkgs.totem ]";
180 type = types.listOf types.package;
181 description = "Which packages gnome should exclude from the default environment";
186 config = lib.mkMerge [
187 (lib.mkIf (cfg.enable || flashbackEnabled) {
188 # Seed our configuration into nixos-generate-config
189 system.nixos-generate-config.desktopConfiguration = [''
190 # Enable the GNOME Desktop Environment.
191 services.xserver.displayManager.gdm.enable = true;
192 services.xserver.desktopManager.gnome.enable = true;
195 services.gnome.core-os-services.enable = true;
196 services.gnome.core-shell.enable = true;
197 services.gnome.core-utilities.enable = mkDefault true;
199 services.displayManager.sessionPackages = [ pkgs.gnome-session.sessions ];
201 environment.extraInit = ''
202 ${lib.concatMapStrings (p: ''
203 if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
204 export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
207 if [ -d "${p}/lib/girepository-1.0" ]; then
208 export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
209 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
214 environment.systemPackages = cfg.sessionPath;
216 environment.sessionVariables.GNOME_SESSION_DEBUG = lib.mkIf cfg.debug "1";
218 # Override GSettings schemas
219 environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
222 (lib.mkIf flashbackEnabled {
223 services.displayManager.sessionPackages =
225 wmNames = map (wm: wm.wmName) flashbackWms;
226 namesAreUnique = lib.unique wmNames == wmNames;
228 assert (lib.assertMsg namesAreUnique "Flashback WM names must be unique.");
231 pkgs.gnome-flashback.mkSessionForWm {
232 inherit (wm) wmName wmLabel wmCommand;
236 security.pam.services.gnome-flashback = {
237 enableGnomeKeyring = true;
242 ] ++ map pkgs.gnome-flashback.mkSystemdTargetForWm flashbackWms;
244 environment.systemPackages = [
246 (pkgs.gnome-panel-with-modules.override {
247 panelModulePackages = cfg.flashback.panelModulePackages;
250 # For /share/applications/${wmName}.desktop
251 ++ (map (wm: pkgs.gnome-flashback.mkWmApplication { inherit (wm) wmName wmLabel wmCommand; }) flashbackWms)
252 # For /share/pkgs.gnome-session/sessions/gnome-flashback-${wmName}.session
253 ++ (map (wm: pkgs.gnome-flashback.mkGnomeSession { inherit (wm) wmName wmLabel enableGnomePanel; }) flashbackWms);
256 (lib.mkIf serviceCfg.core-os-services.enable {
257 hardware.bluetooth.enable = mkDefault true;
258 programs.dconf.enable = true;
259 security.polkit.enable = true;
260 services.accounts-daemon.enable = true;
261 services.dleyna-renderer.enable = mkDefault true;
262 services.dleyna-server.enable = mkDefault true;
263 services.power-profiles-daemon.enable = mkDefault true;
264 services.gnome.at-spi2-core.enable = true;
265 services.gnome.evolution-data-server.enable = true;
266 services.gnome.gnome-keyring.enable = true;
267 services.gnome.gnome-online-accounts.enable = mkDefault true;
268 services.gnome.tracker-miners.enable = mkDefault true;
269 services.gnome.tracker.enable = mkDefault true;
270 services.hardware.bolt.enable = mkDefault true;
271 # TODO: Enable once #177946 is resolved
272 # services.packagekit.enable = mkDefault true;
273 services.udisks2.enable = true;
274 services.upower.enable = config.powerManagement.enable;
275 services.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
277 # Explicitly enabled since GNOME will be severely broken without these.
278 xdg.mime.enable = true;
279 xdg.icons.enable = true;
281 xdg.portal.enable = true;
282 xdg.portal.extraPortals = [
283 pkgs.xdg-desktop-portal-gnome
284 (pkgs.xdg-desktop-portal-gtk.override {
285 # Do not build portals that we already have.
286 buildPortalsInGnome = false;
289 xdg.portal.configPackages = mkDefault [ pkgs.gnome-session ];
291 networking.networkmanager.enable = mkDefault true;
293 services.xserver.updateDbusEnvironment = true;
295 # gnome has a custom alert theme but it still
296 # inherits from the freedesktop theme.
297 environment.systemPackages = with pkgs; [
298 sound-theme-freedesktop
301 # Needed for themes and backgrounds
302 environment.pathsToLink = [
303 "/share" # TODO: https://github.com/NixOS/nixpkgs/issues/47173
307 (lib.mkIf serviceCfg.core-shell.enable {
308 services.xserver.desktopManager.gnome.sessionPath =
310 mandatoryPackages = [
314 pkgs.gnome-shell-extensions
318 ++ utils.removePackagesByName optionalPackages config.environment.gnome.excludePackages;
320 services.colord.enable = mkDefault true;
321 services.gnome.glib-networking.enable = true;
322 services.gnome.gnome-browser-connector.enable = mkDefault true;
323 services.gnome.gnome-initial-setup.enable = mkDefault true;
324 services.gnome.gnome-remote-desktop.enable = mkDefault true;
325 services.gnome.gnome-settings-daemon.enable = true;
326 services.gnome.gnome-user-share.enable = mkDefault true;
327 services.gnome.rygel.enable = mkDefault true;
328 services.gvfs.enable = true;
329 services.system-config-printer.enable = (lib.mkIf config.services.printing.enable (mkDefault true));
336 services.udev.packages = [
337 # Force enable KMS modifiers for devices that require them.
338 # https://gitlab.gnome.org/GNOME/pkgs.mutter/-/merge_requests/1443
342 services.avahi.enable = mkDefault true;
344 services.geoclue2.enable = mkDefault true;
345 services.geoclue2.enableDemoAgent = false; # GNOME has its own geoclue agent
347 services.geoclue2.appConfig.gnome-datetime-panel = {
351 services.geoclue2.appConfig.gnome-color-panel = {
355 services.geoclue2.appConfig."org.gnome.Shell" = {
360 services.orca.enable = notExcluded pkgs.orca;
362 fonts.packages = with pkgs; [
365 source-code-pro # Default monospace font in 3.32
369 # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-3-38/elements/core/meta-gnome-core-shell.bst
370 environment.systemPackages =
372 mandatoryPackages = [
376 pkgs.adwaita-icon-theme
377 nixos-background-info
378 pkgs.gnome-backgrounds
380 pkgs.gnome-color-manager
381 pkgs.gnome-control-center
382 pkgs.gnome-shell-extensions
383 pkgs.gnome-tour # GNOME Shell detects the .desktop file on first log-in.
385 pkgs.glib # for gsettings program
387 pkgs.gtk3.out # for gtk-launch program
388 pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
392 ++ utils.removePackagesByName optionalPackages config.environment.gnome.excludePackages;
395 # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-45/elements/core/meta-gnome-core-utilities.bst
396 (lib.mkIf serviceCfg.core-utilities.enable {
397 environment.systemPackages =
398 utils.removePackagesByName
402 pkgs.gnome-text-editor
403 pkgs.gnome-calculator
405 pkgs.gnome-characters
409 pkgs.gnome-font-viewer
413 pkgs.gnome-system-monitor
417 pkgs.gnome-connections
422 ] ++ lib.optionals config.services.flatpak.enable [
423 # Since PackageKit Nix support is not there yet,
424 # only install gnome-software if flatpak is enabled.
427 config.environment.gnome.excludePackages;
429 # Enable default program modules
430 # Since some of these have a corresponding package, we only
431 # enable that program module if the package hasn't been excluded
432 # through `environment.gnome.excludePackages`
433 programs.evince.enable = notExcluded pkgs.evince;
434 programs.file-roller.enable = notExcluded pkgs.file-roller;
435 programs.geary.enable = notExcluded pkgs.geary;
436 programs.gnome-disks.enable = notExcluded pkgs.gnome-disk-utility;
437 programs.seahorse.enable = notExcluded pkgs.seahorse;
438 services.gnome.sushi.enable = notExcluded pkgs.sushi;
440 # VTE shell integration for gnome-console
441 programs.bash.vteIntegration = mkDefault true;
442 programs.zsh.vteIntegration = mkDefault true;
444 # Let nautilus find extensions
445 # TODO: Create nautilus-with-extensions package
446 environment.sessionVariables.NAUTILUS_4_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-4";
448 # Override default mimeapps for nautilus
449 environment.sessionVariables.XDG_DATA_DIRS = [ "${mimeAppsList}/share" ];
451 environment.pathsToLink = [
452 "/share/nautilus-python/extensions"
456 (lib.mkIf serviceCfg.games.enable {
457 environment.systemPackages = utils.removePackagesByName [
478 ] config.environment.gnome.excludePackages;
481 # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/3.38.0/elements/core/meta-gnome-core-developer-tools.bst
482 (lib.mkIf serviceCfg.core-developer-tools.enable {
483 environment.systemPackages = utils.removePackagesByName [
487 # boxes would make sense in this option, however
488 # it doesn't function well enough to be included
489 # in default configurations.
490 # https://github.com/NixOS/nixpkgs/issues/60908
491 /* pkgs.gnome-boxes */
492 ] config.environment.gnome.excludePackages;
494 services.sysprof.enable = notExcluded pkgs.sysprof;