diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 55d5239ac558..952cf8275763 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -77,6 +77,8 @@
/modules/programs/git.nix @rycee
+/modules/programs/gnome-shell.nix @tadfisher
+
/modules/programs/gnome-terminal.nix @rycee
/modules/programs/go.nix @rvolosatovs
diff --git a/modules/misc/news.nix b/modules/misc/news.nix
index a94fa6c0e250..9c7730f48b41 100644
--- a/modules/misc/news.nix
+++ b/modules/misc/news.nix
@@ -2084,6 +2084,14 @@ in
A new module is available: 'programs.mangohud'.
'';
}
+
+ {
+ time = "2021-06-13T21:40:02+00:00";
+ condition = hostPlatform.isLinux;
+ message = ''
+ A new module is available: 'programs.gnome-shell'.
+ '';
+ }
];
};
}
diff --git a/modules/modules.nix b/modules/modules.nix
index 0e9c4327b85e..1720c30ac926 100644
--- a/modules/modules.nix
+++ b/modules/modules.nix
@@ -74,6 +74,7 @@ let
(loadModule ./programs/getmail.nix { condition = hostPlatform.isLinux; })
(loadModule ./programs/gh.nix { })
(loadModule ./programs/git.nix { })
+ (loadModule ./programs/gnome-shell.nix { condition = hostPlatform.isLinux; })
(loadModule ./programs/gnome-terminal.nix { })
(loadModule ./programs/go.nix { })
(loadModule ./programs/gpg.nix { })
diff --git a/modules/programs/gnome-shell.nix b/modules/programs/gnome-shell.nix
new file mode 100644
index 000000000000..9d8ed9add822
--- /dev/null
+++ b/modules/programs/gnome-shell.nix
@@ -0,0 +1,114 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.programs.gnome-shell;
+
+ extensionOpts = { config, ... }: {
+ options = {
+ id = mkOption {
+ type = types.str;
+ example = "user-theme@gnome-shell-extensions.gcampax.github.com";
+ description = ''
+ ID of the gnome-shell extension. If not provided, it
+ will be obtained from package.uuid.
+ '';
+ };
+
+ package = mkOption {
+ type = types.package;
+ example = "pkgs.gnome3.gnome-shell-extensions";
+ description = ''
+ Package providing a gnome-shell extension in
+ $out/share/gnome-shell/extensions/''${id}.
+ '';
+ };
+ };
+
+ config = mkIf (hasAttr "uuid" config.package) {
+ id = mkDefault config.package.uuid;
+ };
+ };
+
+ themeOpts = {
+ options = {
+ name = mkOption {
+ type = types.str;
+ example = "Plata-Noir";
+ description = ''
+ Name of the gnome-shell theme.
+ '';
+ };
+ package = mkOption {
+ type = types.nullOr types.package;
+ default = null;
+ example = literalExample "pkgs.plata-theme";
+ description = ''
+ Package providing a gnome-shell theme in
+ $out/share/themes/''${name}/gnome-shell.
+ '';
+ };
+ };
+ };
+
+in {
+ meta.maintainers = [ maintainers.tadfisher ];
+
+ options.programs.gnome-shell = {
+ enable = mkEnableOption "gnome-shell customization";
+
+ extensions = mkOption {
+ type = types.listOf (types.submodule extensionOpts);
+ default = [ ];
+ example = literalExample ''
+ [
+ { package = pkgs.gnomeExtensions.dash-to-panel; }
+ {
+ id = "user-theme@gnome-shell-extensions.gcampax.github.com";
+ package = pkgs.gnome3.gnome-shell-extensions;
+ }
+ ]
+ '';
+ description = ''
+ List of gnome-shell extensions.
+ '';
+ };
+
+ theme = mkOption {
+ type = types.nullOr (types.submodule themeOpts);
+ default = null;
+ example = literalExample ''
+ {
+ name = "Plata-Noir";
+ package = [ pkgs.plata-theme ];
+ }
+ '';
+ description = ''
+ Theme to use for gnome-shell.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable (mkMerge [
+ (mkIf (cfg.extensions != [ ]) {
+ dconf.settings."org/gnome/shell" = {
+ disable-user-extensions = false;
+ enabled-extensions = catAttrs "id" cfg.extensions;
+ };
+
+ home.packages = catAttrs "package" cfg.extensions;
+ })
+
+ (mkIf (cfg.theme != null) {
+ dconf.settings."org/gnome/shell/extensions/user-theme".name =
+ cfg.theme.name;
+
+ programs.gnome-shell.extensions = [{
+ id = "user-theme@gnome-shell-extensions.gcampax.github.com";
+ package = pkgs.gnome3.gnome-shell-extensions;
+ }];
+
+ home.packages = [ cfg.theme.package ];
+ })
+ ]);
+}
diff --git a/tests/default.nix b/tests/default.nix
index 4ec787280bbc..7b6ce7a94174 100644
--- a/tests/default.nix
+++ b/tests/default.nix
@@ -100,6 +100,7 @@ import nmt {
./modules/programs/firefox
./modules/programs/foot
./modules/programs/getmail
+ ./modules/programs/gnome-shell
./modules/programs/i3status-rust
./modules/programs/mangohud
./modules/programs/ncmpcpp-linux
diff --git a/tests/modules/programs/gnome-shell/default.nix b/tests/modules/programs/gnome-shell/default.nix
new file mode 100644
index 000000000000..58e4598f8e26
--- /dev/null
+++ b/tests/modules/programs/gnome-shell/default.nix
@@ -0,0 +1 @@
+{ gnome-shell = ./gnome-shell.nix; }
diff --git a/tests/modules/programs/gnome-shell/gnome-shell.nix b/tests/modules/programs/gnome-shell/gnome-shell.nix
new file mode 100644
index 000000000000..f29b2db17260
--- /dev/null
+++ b/tests/modules/programs/gnome-shell/gnome-shell.nix
@@ -0,0 +1,91 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ dummy-gnome-shell-extensions = pkgs.runCommand "dummy-package" { } ''
+ mkdir -p $out/share/gnome-shell/extensions/dummy-package
+ touch $out/share/gnome-shell/extensions/dummy-package/test
+ '';
+
+ test-extension = pkgs.runCommand "test-extension" { } ''
+ mkdir -p $out/share/gnome-shell/extensions/test-extension
+ touch $out/share/gnome-shell/extensions/test-extension/test
+ '';
+
+ test-extension-uuid =
+ pkgs.runCommand "test-extension-uuid" { uuid = "test-extension-uuid"; } ''
+ mkdir -p $out/share/gnome-shell/extensions/test-extension-uuid
+ touch $out/share/gnome-shell/extensions/test-extension-uuid/test
+ '';
+
+ test-theme = pkgs.runCommand "test-theme" { } ''
+ mkdir -p $out/share/themes/Test/gnome-shell
+ touch $out/share/themes/Test/gnome-shell/test
+ '';
+
+ expectedEnabledExtensions = [
+ "user-theme@gnome-shell-extensions.gcampax.github.com"
+ "test-extension"
+ "test-extension-uuid"
+ ];
+
+ actualEnabledExtensions =
+ catAttrs "value" config.dconf.settings."org/gnome/shell".enabled-extensions;
+
+in {
+ nixpkgs.overlays = [
+ (self: super: {
+ gnome3 = super.gnome3.overrideScope' (gself: gsuper: {
+ gnome-shell-extensions = dummy-gnome-shell-extensions;
+ });
+ })
+ ];
+
+ programs.gnome-shell.enable = true;
+
+ programs.gnome-shell.extensions = [
+ {
+ id = "test-extension";
+ package = test-extension;
+ }
+ { package = test-extension-uuid; }
+ ];
+
+ programs.gnome-shell.theme = {
+ name = "Test";
+ package = test-theme;
+ };
+
+ assertions = [
+ {
+ assertion =
+ config.dconf.settings."org/gnome/shell".disable-user-extensions
+ == false;
+ message = "Expected disable-user-extensions to be false.";
+ }
+ {
+ assertion =
+ all (e: elem e actualEnabledExtensions) expectedEnabledExtensions;
+ message = ''
+ Expected enabled-extensions to contain all of:
+ ${toString expectedEnabledExtensions}
+ But it was:
+ ${toString actualEnabledExtensions}
+ '';
+ }
+ {
+ assertion =
+ config.dconf.settings."org/gnome/shell/extensions/user-theme".name
+ == "Test";
+ message = "Expected extensions/user-theme/name to be 'Test'.";
+ }
+ ];
+
+ nmt.script = ''
+ assertFileExists home-path/share/gnome-shell/extensions/dummy-package/test
+ assertFileExists home-path/share/gnome-shell/extensions/test-extension/test
+ assertFileExists home-path/share/gnome-shell/extensions/test-extension-uuid/test
+ assertFileExists home-path/share/themes/Test/gnome-shell/test
+ '';
+}