diff --git a/modules/misc/gtk.nix b/modules/misc/gtk.nix index 0287342e005d..d3f1c40f8011 100644 --- a/modules/misc/gtk.nix +++ b/modules/misc/gtk.nix @@ -2,9 +2,9 @@ let inherit (lib) - literalExpression + mkEnableOption + mkIf mkOption - optionalAttrs types ; @@ -13,313 +13,74 @@ let cfg3 = config.gtk.gtk3; cfg4 = config.gtk.gtk4; - toGtk3Ini = lib.generators.toINI { - mkKeyValue = - key: value: - let - value' = if lib.isBool value then lib.boolToString value else toString value; - in - "${lib.escape [ "=" ] key}=${value'}"; - }; - - formatGtk2Option = - n: v: - let - v' = - if lib.isBool v then - lib.boolToString lib.value - else if lib.isString v then - ''"${v}"'' - else - toString v; - in - "${lib.escape [ "=" ] n} = ${v'}"; - - themeType = types.submodule { - options = { - package = mkOption { - type = types.nullOr types.package; - default = null; - example = literalExpression "pkgs.gnome.gnome-themes-extra"; - description = '' - Package providing the theme. This package will be installed - to your profile. If `null` then the theme - is assumed to already be available in your profile. + gtkLib = import ./gtk/lib.nix { inherit lib; }; - For the theme to apply to GTK 4, this option is mandatory. - ''; - }; - - name = mkOption { - type = types.str; - example = "Adwaita"; - description = "The name of the theme within the package."; - }; - }; + themeType = gtkLib.mkThemeType { + typeName = "theme"; + packageExample = "pkgs.gnome.gnome-themes-extra"; }; - iconThemeType = types.submodule { - options = { - package = mkOption { - type = types.nullOr types.package; - default = null; - example = literalExpression "pkgs.adwaita-icon-theme"; - description = '' - Package providing the icon theme. This package will be installed - to your profile. If `null` then the theme - is assumed to already be available in your profile. - ''; - }; - - name = mkOption { - type = types.str; - example = "Adwaita"; - description = "The name of the icon theme within the package."; - }; - }; + iconThemeType = gtkLib.mkThemeType { + typeName = "icon theme"; + packageExample = "pkgs.adwaita-icon-theme"; }; - cursorThemeType = types.submodule { - options = { - package = mkOption { - type = types.nullOr types.package; - default = null; - example = literalExpression "pkgs.vanilla-dmz"; - description = '' - Package providing the cursor theme. This package will be installed - to your profile. If `null` then the theme - is assumed to already be available in your profile. - ''; - }; - - name = mkOption { - type = types.str; - example = "Vanilla-DMZ"; - description = "The name of the cursor theme within the package."; - }; - - size = mkOption { - type = types.nullOr types.int; - default = null; - example = 16; - description = '' - The size of the cursor. - ''; - }; - }; + cursorThemeType = gtkLib.mkThemeType { + typeName = "cursor theme"; + hasSize = true; + packageExample = "pkgs.vanilla-dmz"; + nameExample = "Vanilla-DMZ"; }; in + { - meta.maintainers = [ lib.maintainers.rycee ]; + meta.maintainers = with lib.maintainers; [ + khaneliman + rycee + ]; imports = [ - (lib.mkRemovedOptionModule [ "gtk" "gtk3" "waylandSupport" ] '' - This options is not longer needed and can be removed. - '') + ./gtk/gtk2.nix + ./gtk/gtk3.nix + ./gtk/gtk4.nix ]; - options = { - gtk = { - enable = lib.mkEnableOption "GTK 2/3 configuration"; - - font = mkOption { - type = types.nullOr lib.hm.types.fontType; - default = null; - description = '' - The font to use in GTK+ 2/3 applications. - ''; - }; - - cursorTheme = mkOption { - type = types.nullOr cursorThemeType; - default = null; - description = "The cursor theme to use."; - }; - - iconTheme = mkOption { - type = types.nullOr iconThemeType; - default = null; - description = "The icon theme to use."; - }; - - theme = mkOption { - type = types.nullOr themeType; - default = null; - description = "The GTK+2/3 theme to use."; - }; - - gtk2 = { - extraConfig = mkOption { - type = types.lines; - default = ""; - example = "gtk-can-change-accels = 1"; - description = '' - Extra configuration lines to add verbatim to - {file}`~/.gtkrc-2.0`. - ''; - }; - - configLocation = mkOption { - type = types.path; - default = "${config.home.homeDirectory}/.gtkrc-2.0"; - defaultText = literalExpression ''"''${config.home.homeDirectory}/.gtkrc-2.0"''; - example = literalExpression ''"''${config.xdg.configHome}/gtk-2.0/gtkrc"''; - description = '' - The location to put the GTK configuration file. - ''; - }; + options.gtk = { + enable = mkEnableOption "GTK theming and configuration"; - force = lib.mkEnableOption "GTK 2 config force overwrite without creating a backup"; - }; - - gtk3 = { - bookmarks = mkOption { - type = types.listOf types.str; - default = [ ]; - example = [ "file:///home/jane/Documents" ]; - description = "Bookmarks in the sidebar of the GTK file browser"; - }; - - extraConfig = mkOption { - type = - with types; - attrsOf (oneOf [ - bool - int - str - ]); - default = { }; - example = { - gtk-cursor-blink = false; - gtk-recent-files-limit = 20; - }; - description = '' - Extra configuration options to add to - {file}`$XDG_CONFIG_HOME/gtk-3.0/settings.ini`. - ''; - }; + # Global settings that act as defaults for version-specific settings + font = mkOption { + type = types.nullOr lib.hm.types.fontType; + default = null; + description = "Default font for all GTK versions."; + }; - extraCss = mkOption { - type = types.lines; - default = ""; - description = '' - Extra configuration lines to add verbatim to - {file}`$XDG_CONFIG_HOME/gtk-3.0/gtk.css`. - ''; - }; - }; + theme = mkOption { + type = types.nullOr themeType; + default = null; + description = "Default theme for all GTK versions."; + }; - gtk4 = { - extraConfig = mkOption { - type = with types; attrsOf (either bool (either int str)); - default = { }; - example = { - gtk-cursor-blink = false; - gtk-recent-files-limit = 20; - }; - description = '' - Extra configuration options to add to - {file}`$XDG_CONFIG_HOME/gtk-4.0/settings.ini`. - ''; - }; + iconTheme = mkOption { + type = types.nullOr iconThemeType; + default = null; + description = "Default icon theme for all GTK versions."; + }; - extraCss = mkOption { - type = types.lines; - default = ""; - description = '' - Extra configuration lines to add verbatim to - {file}`$XDG_CONFIG_HOME/gtk-4.0/gtk.css`. - ''; - }; - }; + cursorTheme = mkOption { + type = types.nullOr cursorThemeType; + default = null; + description = "Default cursor theme for all GTK versions."; }; }; - config = lib.mkIf cfg.enable ( - let - gtkIni = - optionalAttrs (cfg.font != null) { - gtk-font-name = - let - fontSize = if cfg.font.size != null then cfg.font.size else 10; - in - "${cfg.font.name} ${toString fontSize}"; - } - // optionalAttrs (cfg.theme != null) { gtk-theme-name = cfg.theme.name; } - // optionalAttrs (cfg.iconTheme != null) { - gtk-icon-theme-name = cfg.iconTheme.name; - } - // optionalAttrs (cfg.cursorTheme != null) { - gtk-cursor-theme-name = cfg.cursorTheme.name; - } - // optionalAttrs (cfg.cursorTheme != null && cfg.cursorTheme.size != null) { - gtk-cursor-theme-size = cfg.cursorTheme.size; - }; - - gtk4Css = - lib.optionalString (cfg.theme != null && cfg.theme.package != null) '' - /** - * GTK 4 reads the theme configured by gtk-theme-name, but ignores it. - * It does however respect user CSS, so import the theme from here. - **/ - @import url("file://${cfg.theme.package}/share/themes/${cfg.theme.name}/gtk-4.0/gtk.css"); - '' - + cfg4.extraCss; - - dconfIni = - optionalAttrs (cfg.font != null) { - font-name = - let - fontSize = if cfg.font.size != null then cfg.font.size else 10; - in - "${cfg.font.name} ${toString fontSize}"; - } - // optionalAttrs (cfg.theme != null) { gtk-theme = cfg.theme.name; } - // optionalAttrs (cfg.iconTheme != null) { - icon-theme = cfg.iconTheme.name; - } - // optionalAttrs (cfg.cursorTheme != null) { - cursor-theme = cfg.cursorTheme.name; - } - // optionalAttrs (cfg.cursorTheme != null && cfg.cursorTheme.size != null) { - cursor-size = cfg.cursorTheme.size; - }; - - optionalPackage = opt: lib.optional (opt != null && opt.package != null) opt.package; - in - { - home.packages = lib.concatMap optionalPackage [ - cfg.font - cfg.theme - cfg.iconTheme - cfg.cursorTheme - ]; - - home.file.${cfg2.configLocation} = { - text = - lib.concatMapStrings (l: l + "\n") (lib.mapAttrsToList formatGtk2Option gtkIni) - + cfg2.extraConfig - + "\n"; - - inherit (cfg2) force; - }; - - home.sessionVariables.GTK2_RC_FILES = cfg2.configLocation; - - xdg.configFile."gtk-3.0/settings.ini".text = toGtk3Ini { Settings = gtkIni // cfg3.extraConfig; }; - - xdg.configFile."gtk-3.0/gtk.css" = lib.mkIf (cfg3.extraCss != "") { text = cfg3.extraCss; }; - - xdg.configFile."gtk-3.0/bookmarks" = lib.mkIf (cfg3.bookmarks != [ ]) { - text = lib.concatMapStrings (l: l + "\n") cfg3.bookmarks; - }; - - xdg.configFile."gtk-4.0/settings.ini".text = toGtk3Ini { Settings = gtkIni // cfg4.extraConfig; }; - - xdg.configFile."gtk-4.0/gtk.css" = lib.mkIf (gtk4Css != "") { text = gtk4Css; }; - - dconf.settings."org/gnome/desktop/interface" = dconfIni; - } - ); + config = mkIf cfg.enable { + # Collect packages from all GTK versions + home.packages = gtkLib.collectGtkPackages [ + cfg2 + cfg3 + cfg4 + ]; + }; } diff --git a/modules/misc/gtk/gtk2.nix b/modules/misc/gtk/gtk2.nix new file mode 100644 index 000000000000..452f8272cd19 --- /dev/null +++ b/modules/misc/gtk/gtk2.nix @@ -0,0 +1,121 @@ +{ config, lib, ... }: + +let + inherit (lib) + literalExpression + mkEnableOption + mkIf + mkOption + types + ; + + cfg = config.gtk; + cfg2 = config.gtk.gtk2; + + gtkLib = import ./lib.nix { inherit lib; }; + + formatGtk2Option = + n: v: + let + v' = + if lib.isBool v then + lib.boolToString v + else if lib.isString v then + ''"${v}"'' + else + toString v; + in + "${lib.escape [ "=" ] n} = ${v'}"; + +in + +{ + options.gtk.gtk2 = { + enable = mkEnableOption "GTK 2 configuration" // { + default = true; + }; + + font = mkOption { + type = types.nullOr lib.hm.types.fontType; + default = cfg.font; + defaultText = literalExpression "config.gtk.font"; + description = "Font for GTK 2 applications."; + }; + + theme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "theme"; + packageExample = "pkgs.gnome.gnome-themes-extra"; + } + ); + default = cfg.theme; + defaultText = literalExpression "config.gtk.theme"; + description = "Theme for GTK 2 applications."; + }; + + iconTheme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "icon theme"; + packageExample = "pkgs.adwaita-icon-theme"; + } + ); + default = cfg.iconTheme; + defaultText = literalExpression "config.gtk.iconTheme"; + description = "Icon theme for GTK 2 applications."; + }; + + cursorTheme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "cursor theme"; + hasSize = true; + packageExample = "pkgs.vanilla-dmz"; + nameExample = "Vanilla-DMZ"; + } + ); + default = cfg.cursorTheme; + defaultText = literalExpression "config.gtk.cursorTheme"; + description = "Cursor theme for GTK 2 applications."; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + example = "gtk-can-change-accels = 1"; + description = "Extra lines to add to {file}`~/.gtkrc-2.0`."; + }; + + configLocation = mkOption { + type = types.path; + default = "${config.home.homeDirectory}/.gtkrc-2.0"; + defaultText = literalExpression ''"''${config.home.homeDirectory}/.gtkrc-2.0"''; + example = literalExpression ''"''${config.xdg.configHome}/gtk-2.0/gtkrc"''; + description = "The location of the GTK 2 configuration file."; + }; + }; + + config = mkIf (cfg.enable && cfg2.enable) { + home.file.${cfg2.configLocation} = { + text = + let + settings = gtkLib.mkGtkSettings { + inherit (cfg2) + font + theme + iconTheme + cursorTheme + ; + }; + settingsText = lib.concatMapStrings (n: "${formatGtk2Option n settings.${n}}\n") ( + lib.attrNames settings + ); + in + '' + ${settingsText}${cfg2.extraConfig} + ''; + }; + home.sessionVariables.GTK2_RC_FILES = cfg2.configLocation; + }; +} diff --git a/modules/misc/gtk/gtk3.nix b/modules/misc/gtk/gtk3.nix new file mode 100644 index 000000000000..a085a2cc15e7 --- /dev/null +++ b/modules/misc/gtk/gtk3.nix @@ -0,0 +1,153 @@ +{ config, lib, ... }: + +let + inherit (lib) + literalExpression + mkEnableOption + mkIf + mkOption + types + ; + + cfg = config.gtk; + cfg3 = config.gtk.gtk3; + + gtkLib = import ./lib.nix { inherit lib; }; + + toIni = lib.generators.toINI { + mkKeyValue = + key: value: + let + value' = if lib.isBool value then lib.boolToString value else toString value; + in + "${lib.escape [ "=" ] key}=${value'}"; + }; + +in + +{ + options.gtk.gtk3 = { + enable = mkEnableOption "GTK 3 configuration" // { + default = true; + }; + + font = mkOption { + type = types.nullOr lib.hm.types.fontType; + default = cfg.font; + defaultText = literalExpression "config.gtk.font"; + description = "Font for GTK 3 applications."; + }; + + theme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "theme"; + packageExample = "pkgs.gnome.gnome-themes-extra"; + } + ); + default = cfg.theme; + defaultText = literalExpression "config.gtk.theme"; + description = "Theme for GTK 3 applications."; + }; + + iconTheme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "icon theme"; + packageExample = "pkgs.adwaita-icon-theme"; + } + ); + default = cfg.iconTheme; + defaultText = literalExpression "config.gtk.iconTheme"; + description = "Icon theme for GTK 3 applications."; + }; + + cursorTheme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "cursor theme"; + hasSize = true; + packageExample = "pkgs.vanilla-dmz"; + nameExample = "Vanilla-DMZ"; + } + ); + default = cfg.cursorTheme; + defaultText = literalExpression "config.gtk.cursorTheme"; + description = "Cursor theme for GTK 3 applications."; + }; + + extraConfig = mkOption { + type = + with types; + attrsOf (oneOf [ + bool + int + str + ]); + default = { }; + example = { + gtk-cursor-blink = false; + gtk-recent-files-limit = 20; + }; + description = "Extra settings for {file}`$XDG_CONFIG_HOME/gtk-3.0/settings.ini`."; + }; + + extraCss = mkOption { + type = types.lines; + default = ""; + description = "Extra CSS for {file}`$XDG_CONFIG_HOME/gtk-3.0/gtk.css`."; + }; + + bookmarks = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "file:///home/jane/Documents" ]; + description = "File browser bookmarks."; + }; + }; + + config = mkIf (cfg.enable && cfg3.enable) { + xdg.configFile = { + "gtk-3.0/settings.ini" = { + text = toIni { + Settings = + gtkLib.mkGtkSettings { + inherit (cfg3) + font + theme + iconTheme + cursorTheme + ; + } + // cfg3.extraConfig; + }; + }; + "gtk-3.0/gtk.css" = mkIf (cfg3.extraCss != "") { + text = cfg3.extraCss; + }; + "gtk-3.0/bookmarks" = mkIf (cfg3.bookmarks != [ ]) { + text = lib.concatMapStrings (l: l + "\n") cfg3.bookmarks; + }; + }; + + # DConf settings are primarily for GNOME/GTK3/4 apps + dconf.settings."org/gnome/desktop/interface" = + let + settings = gtkLib.mkGtkSettings { + inherit (cfg3) + font + theme + iconTheme + cursorTheme + ; + }; + in + lib.filterAttrs (_: v: v != null) { + "font-name" = settings."gtk-font-name" or null; + "gtk-theme" = settings."gtk-theme-name" or null; + "icon-theme" = settings."gtk-icon-theme-name" or null; + "cursor-theme" = settings."gtk-cursor-theme-name" or null; + "cursor-size" = settings."gtk-cursor-theme-size" or null; + }; + }; +} diff --git a/modules/misc/gtk/gtk4.nix b/modules/misc/gtk/gtk4.nix new file mode 100644 index 000000000000..a8d72cdb7121 --- /dev/null +++ b/modules/misc/gtk/gtk4.nix @@ -0,0 +1,133 @@ +{ config, lib, ... }: + +let + inherit (lib) + literalExpression + mkEnableOption + mkIf + mkOption + types + ; + + cfg = config.gtk; + cfg4 = config.gtk.gtk4; + + gtkLib = import ./lib.nix { inherit lib; }; + + toIni = lib.generators.toINI { + mkKeyValue = + key: value: + let + value' = if lib.isBool value then lib.boolToString value else toString value; + in + "${lib.escape [ "=" ] key}=${value'}"; + }; + +in + +{ + options.gtk.gtk4 = { + enable = mkEnableOption "GTK 4 configuration" // { + default = true; + }; + + font = mkOption { + type = types.nullOr lib.hm.types.fontType; + default = cfg.font; + defaultText = literalExpression "config.gtk.font"; + description = "Font for GTK 4 applications."; + }; + + theme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "theme"; + packageExample = "pkgs.gnome.gnome-themes-extra"; + } + ); + default = cfg.theme; + defaultText = literalExpression "config.gtk.theme"; + description = "Theme for GTK 4 applications."; + }; + + iconTheme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "icon theme"; + packageExample = "pkgs.adwaita-icon-theme"; + } + ); + default = cfg.iconTheme; + defaultText = literalExpression "config.gtk.iconTheme"; + description = "Icon theme for GTK 4 applications."; + }; + + cursorTheme = mkOption { + type = types.nullOr ( + gtkLib.mkThemeType { + typeName = "cursor theme"; + hasSize = true; + packageExample = "pkgs.vanilla-dmz"; + nameExample = "Vanilla-DMZ"; + } + ); + default = cfg.cursorTheme; + defaultText = literalExpression "config.gtk.cursorTheme"; + description = "Cursor theme for GTK 4 applications."; + }; + + extraConfig = mkOption { + type = + with types; + attrsOf (oneOf [ + bool + int + str + ]); + default = { }; + example = { + gtk-cursor-blink = false; + gtk-recent-files-limit = 20; + }; + description = "Extra settings for {file}`$XDG_CONFIG_HOME/gtk-4.0/settings.ini`."; + }; + + extraCss = mkOption { + type = types.lines; + default = ""; + description = "Extra CSS for {file}`$XDG_CONFIG_HOME/gtk-4.0/gtk.css`."; + }; + }; + + config = mkIf (cfg.enable && cfg4.enable) { + xdg.configFile = { + "gtk-4.0/settings.ini" = { + text = toIni { + Settings = + gtkLib.mkGtkSettings { + inherit (cfg4) + font + theme + iconTheme + cursorTheme + ; + } + // cfg4.extraConfig; + }; + }; + "gtk-4.0/gtk.css" = + mkIf (cfg4.extraCss != "" || (cfg4.theme != null && cfg4.theme.package != null)) + { + text = + lib.optionalString (cfg4.theme != null && cfg4.theme.package != null) '' + /** + * GTK 4 reads the theme configured by gtk-theme-name, but ignores it. + * It does however respect user CSS, so import the theme from here. + **/ + @import url("file://${cfg4.theme.package}/share/themes/${cfg4.theme.name}/gtk-4.0/gtk.css"); + '' + + cfg4.extraCss; + }; + }; + }; +} diff --git a/modules/misc/gtk/lib.nix b/modules/misc/gtk/lib.nix new file mode 100644 index 000000000000..5a6e645037c8 --- /dev/null +++ b/modules/misc/gtk/lib.nix @@ -0,0 +1,96 @@ +{ lib }: + +let + inherit (lib) + literalExpression + mkOption + optionalAttrs + optionalString + types + ; +in + +{ + # Generic theme type factory function + mkThemeType = + { + typeName, + hasSize ? false, + packageExample, + nameExample ? "Adwaita", + }: + types.submodule { + options = + { + package = mkOption { + type = types.nullOr types.package; + default = null; + example = literalExpression packageExample; + description = + '' + Package providing the ${typeName}. This package will be installed + to your profile. If `null` then the ${typeName} + is assumed to already be available in your profile. + '' + + optionalString (typeName == "theme") '' + + For the theme to apply to GTK 4, this option is mandatory. + ''; + }; + + name = mkOption { + type = types.str; + example = nameExample; + description = "The name of the ${typeName} within the package."; + }; + } + // optionalAttrs hasSize { + size = mkOption { + type = types.nullOr types.int; + default = null; + example = 16; + description = "The size of the cursor."; + }; + }; + }; + + # Helper function to generate the settings attribute set for a given version + mkGtkSettings = + { + font, + theme, + iconTheme, + cursorTheme, + }: + optionalAttrs (font != null) { + gtk-font-name = + let + fontSize = if font.size != null then font.size else 11; + in + "${font.name} ${toString fontSize}"; + } + // optionalAttrs (theme != null) { "gtk-theme-name" = theme.name; } + // optionalAttrs (iconTheme != null) { "gtk-icon-theme-name" = iconTheme.name; } + // optionalAttrs (cursorTheme != null) { "gtk-cursor-theme-name" = cursorTheme.name; } + // optionalAttrs (cursorTheme != null && cursorTheme.size != null) { + "gtk-cursor-theme-size" = cursorTheme.size; + }; + + # Package collection helper for all GTK versions + collectGtkPackages = + versionConfigs: + let + collectPackages = + cfgVersion: + lib.filter (pkg: pkg != null) ( + lib.optionals cfgVersion.enable ( + lib.optionals (cfgVersion.theme != null) [ cfgVersion.theme.package ] + ++ lib.optionals (cfgVersion.iconTheme != null) [ cfgVersion.iconTheme.package ] + ++ lib.optionals (cfgVersion.cursorTheme != null) [ cfgVersion.cursorTheme.package ] + ++ lib.optionals (cfgVersion.font != null) [ cfgVersion.font.package ] + ) + ); + allPackages = lib.concatMap collectPackages versionConfigs; + in + lib.unique allPackages; +} diff --git a/tests/modules/misc/gtk/default.nix b/tests/modules/misc/gtk/default.nix index cebbfad5f1d5..016658a69a90 100644 --- a/tests/modules/misc/gtk/default.nix +++ b/tests/modules/misc/gtk/default.nix @@ -1,5 +1,17 @@ { - gtk2-basic-config = ./gtk2-basic-config.nix; - gtk2-config-file-location = ./gtk2-config-file-location.nix; - gtk3-basic-settings = ./gtk3-basic-settings.nix; + gtk-global-inheritance = ./gtk-global-inheritance.nix; + gtk-per-version-override = ./gtk-per-version-override.nix; + gtk-selective-enable = ./gtk-selective-enable.nix; + + # GTK2 + gtk2-basic-config = ./gtk2/gtk2-basic-config.nix; + gtk2-config-file-location = ./gtk2/gtk2-config-file-location.nix; + + # GTK3 + gtk3-basic-settings = ./gtk3/gtk3-basic-settings.nix; + + # GTK4 + gtk4-basic-settings = ./gtk4/gtk4-basic-settings.nix; + gtk4-theme-css-injection = ./gtk4/gtk4-theme-css-injection.nix; + gtk4-no-theme-css-injection = ./gtk4/gtk4-no-theme-css-injection.nix; } diff --git a/tests/modules/misc/gtk/gtk-global-inheritance-gtk2-expected.conf b/tests/modules/misc/gtk/gtk-global-inheritance-gtk2-expected.conf new file mode 100644 index 000000000000..4844a49b8c36 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-global-inheritance-gtk2-expected.conf @@ -0,0 +1,6 @@ +gtk-cursor-theme-name = "Adwaita" +gtk-cursor-theme-size = 24 +gtk-font-name = "Ubuntu 12" +gtk-icon-theme-name = "Adwaita" +gtk-theme-name = "Adwaita-dark" + diff --git a/tests/modules/misc/gtk/gtk-global-inheritance-gtk3-expected.ini b/tests/modules/misc/gtk/gtk-global-inheritance-gtk3-expected.ini new file mode 100644 index 000000000000..5ab5e63c47f5 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-global-inheritance-gtk3-expected.ini @@ -0,0 +1,6 @@ +[Settings] +gtk-cursor-theme-name=Adwaita +gtk-cursor-theme-size=24 +gtk-font-name=Ubuntu 12 +gtk-icon-theme-name=Adwaita +gtk-theme-name=Adwaita-dark diff --git a/tests/modules/misc/gtk/gtk-global-inheritance-gtk4-css-expected.css b/tests/modules/misc/gtk/gtk-global-inheritance-gtk4-css-expected.css new file mode 100644 index 000000000000..a8f04a5ca3f8 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-global-inheritance-gtk4-css-expected.css @@ -0,0 +1,5 @@ +/** + * GTK 4 reads the theme configured by gtk-theme-name, but ignores it. + * It does however respect user CSS, so import the theme from here. +**/ +@import url("file://@gnome-themes-extra@/share/themes/Adwaita-dark/gtk-4.0/gtk.css"); diff --git a/tests/modules/misc/gtk/gtk-global-inheritance-gtk4-expected.ini b/tests/modules/misc/gtk/gtk-global-inheritance-gtk4-expected.ini new file mode 100644 index 000000000000..5ab5e63c47f5 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-global-inheritance-gtk4-expected.ini @@ -0,0 +1,6 @@ +[Settings] +gtk-cursor-theme-name=Adwaita +gtk-cursor-theme-size=24 +gtk-font-name=Ubuntu 12 +gtk-icon-theme-name=Adwaita +gtk-theme-name=Adwaita-dark diff --git a/tests/modules/misc/gtk/gtk-global-inheritance.nix b/tests/modules/misc/gtk/gtk-global-inheritance.nix new file mode 100644 index 000000000000..8ad2edc22684 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-global-inheritance.nix @@ -0,0 +1,44 @@ +{ pkgs, ... }: +{ + gtk = { + enable = true; + font = { + name = "Ubuntu"; + size = 12; + package = pkgs.ubuntu_font_family; + }; + theme = { + name = "Adwaita-dark"; + package = pkgs.gnome-themes-extra; + }; + iconTheme = { + name = "Adwaita"; + package = pkgs.adwaita-icon-theme; + }; + cursorTheme = { + name = "Adwaita"; + size = 24; + }; + }; + + nmt.script = '' + # Check GTK2 inherits global settings + assertFileExists home-files/.gtkrc-2.0 + assertFileContent home-files/.gtkrc-2.0 \ + ${./gtk-global-inheritance-gtk2-expected.conf} + + # Check GTK3 inherits global settings + assertFileExists home-files/.config/gtk-3.0/settings.ini + assertFileContent home-files/.config/gtk-3.0/settings.ini \ + ${./gtk-global-inheritance-gtk3-expected.ini} + + # Check GTK4 inherits global settings + assertFileExists home-files/.config/gtk-4.0/settings.ini + assertFileContent home-files/.config/gtk-4.0/settings.ini \ + ${./gtk-global-inheritance-gtk4-expected.ini} + + # Check GTK4 CSS with theme import + assertFileExists home-files/.config/gtk-4.0/gtk.css + assertFileContent home-files/.config/gtk-4.0/gtk.css ${./gtk-global-inheritance-gtk4-css-expected.css} + ''; +} diff --git a/tests/modules/misc/gtk/gtk-per-version-override-gtk2-expected.conf b/tests/modules/misc/gtk/gtk-per-version-override-gtk2-expected.conf new file mode 100644 index 000000000000..28e4ce54a451 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-per-version-override-gtk2-expected.conf @@ -0,0 +1,5 @@ +gtk-cursor-theme-name = "Global-Cursor" +gtk-font-name = "GTK2-Font 11" +gtk-icon-theme-name = "Global-Icons" +gtk-theme-name = "GTK2-Theme" +gtk-can-change-accels = 1 diff --git a/tests/modules/misc/gtk/gtk-per-version-override-gtk3-css-expected.css b/tests/modules/misc/gtk/gtk-per-version-override-gtk3-css-expected.css new file mode 100644 index 000000000000..50581c0b7a6b --- /dev/null +++ b/tests/modules/misc/gtk/gtk-per-version-override-gtk3-css-expected.css @@ -0,0 +1 @@ +window { border: 1px solid red; } \ No newline at end of file diff --git a/tests/modules/misc/gtk/gtk-per-version-override-gtk3-expected.ini b/tests/modules/misc/gtk/gtk-per-version-override-gtk3-expected.ini new file mode 100644 index 000000000000..60faf91723fb --- /dev/null +++ b/tests/modules/misc/gtk/gtk-per-version-override-gtk3-expected.ini @@ -0,0 +1,6 @@ +[Settings] +gtk-cursor-theme-name=GTK3-Cursor +gtk-font-name=Global Font 11 +gtk-icon-theme-name=GTK3-Icons +gtk-recent-files-limit=10 +gtk-theme-name=Global-Theme diff --git a/tests/modules/misc/gtk/gtk-per-version-override-gtk4-css-expected.css b/tests/modules/misc/gtk/gtk-per-version-override-gtk4-css-expected.css new file mode 100644 index 000000000000..5c6a5cd74365 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-per-version-override-gtk4-css-expected.css @@ -0,0 +1 @@ +window { border: 2px solid blue; } \ No newline at end of file diff --git a/tests/modules/misc/gtk/gtk-per-version-override-gtk4-expected.ini b/tests/modules/misc/gtk/gtk-per-version-override-gtk4-expected.ini new file mode 100644 index 000000000000..25b6ea043061 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-per-version-override-gtk4-expected.ini @@ -0,0 +1,6 @@ +[Settings] +gtk-cursor-theme-name=Global-Cursor +gtk-font-name=GTK4-Font 11 +gtk-icon-theme-name=Global-Icons +gtk-recent-files-limit=20 +gtk-theme-name=Global-Theme diff --git a/tests/modules/misc/gtk/gtk-per-version-override.nix b/tests/modules/misc/gtk/gtk-per-version-override.nix new file mode 100644 index 000000000000..0273de70949c --- /dev/null +++ b/tests/modules/misc/gtk/gtk-per-version-override.nix @@ -0,0 +1,57 @@ +{ + gtk = { + enable = true; + # Global defaults + font.name = "Global Font"; + theme.name = "Global-Theme"; + iconTheme.name = "Global-Icons"; + cursorTheme.name = "Global-Cursor"; + + # Per-version overrides + gtk2 = { + font.name = "GTK2-Font"; + theme.name = "GTK2-Theme"; + extraConfig = "gtk-can-change-accels = 1"; + }; + + gtk3 = { + iconTheme.name = "GTK3-Icons"; + cursorTheme.name = "GTK3-Cursor"; + extraConfig = { + gtk-recent-files-limit = 10; + }; + extraCss = "window { border: 1px solid red; }"; + }; + + gtk4 = { + font.name = "GTK4-Font"; + extraConfig = { + gtk-recent-files-limit = 20; + }; + extraCss = "window { border: 2px solid blue; }"; + }; + }; + + nmt.script = '' + # GTK2 should use overridden font/theme, global icons/cursor + assertFileExists home-files/.gtkrc-2.0 + assertFileContent home-files/.gtkrc-2.0 \ + ${./gtk-per-version-override-gtk2-expected.conf} + + # GTK3 should use global font/theme, overridden icons/cursor + assertFileExists home-files/.config/gtk-3.0/settings.ini + assertFileContent home-files/.config/gtk-3.0/settings.ini \ + ${./gtk-per-version-override-gtk3-expected.ini} + assertFileExists home-files/.config/gtk-3.0/gtk.css + assertFileContent home-files/.config/gtk-3.0/gtk.css \ + ${./gtk-per-version-override-gtk3-css-expected.css} + + # GTK4 should use overridden font, global theme/icons/cursor + assertFileExists home-files/.config/gtk-4.0/settings.ini + assertFileContent home-files/.config/gtk-4.0/settings.ini \ + ${./gtk-per-version-override-gtk4-expected.ini} + assertFileExists home-files/.config/gtk-4.0/gtk.css + assertFileContent home-files/.config/gtk-4.0/gtk.css \ + ${./gtk-per-version-override-gtk4-css-expected.css} + ''; +} diff --git a/tests/modules/misc/gtk/gtk-selective-enable-gtk3-expected.ini b/tests/modules/misc/gtk/gtk-selective-enable-gtk3-expected.ini new file mode 100644 index 000000000000..5b16ed39a101 --- /dev/null +++ b/tests/modules/misc/gtk/gtk-selective-enable-gtk3-expected.ini @@ -0,0 +1,2 @@ +[Settings] +gtk-theme-name=Test-Theme diff --git a/tests/modules/misc/gtk/gtk-selective-enable.nix b/tests/modules/misc/gtk/gtk-selective-enable.nix new file mode 100644 index 000000000000..95bb66244f2e --- /dev/null +++ b/tests/modules/misc/gtk/gtk-selective-enable.nix @@ -0,0 +1,29 @@ +{ + # Test that individual GTK versions can be selectively disabled + gtk = { + enable = true; + theme.name = "Test-Theme"; + + # Only enable GTK3, disable others + gtk2.enable = false; + gtk3.enable = true; + gtk4.enable = false; + }; + + nmt.script = '' + # GTK2 should not be configured + assertPathNotExists home-files/.gtkrc-2.0 + + # GTK3 should be configured + assertFileExists home-files/.config/gtk-3.0/settings.ini + assertFileContent home-files/.config/gtk-3.0/settings.ini \ + ${./gtk-selective-enable-gtk3-expected.ini} + + # GTK4 should not be configured + assertPathNotExists home-files/.config/gtk-4.0/settings.ini + assertPathNotExists home-files/.config/gtk-4.0/gtk.css + + # DConf should still be configured from GTK3 + echo \"DConf generation depends on having actual theme/font/icon settings\" + ''; +} diff --git a/tests/modules/misc/gtk/gtk2-basic-config-expected.conf b/tests/modules/misc/gtk/gtk2/gtk2-basic-config-expected.conf similarity index 100% rename from tests/modules/misc/gtk/gtk2-basic-config-expected.conf rename to tests/modules/misc/gtk/gtk2/gtk2-basic-config-expected.conf diff --git a/tests/modules/misc/gtk/gtk2-basic-config.nix b/tests/modules/misc/gtk/gtk2/gtk2-basic-config.nix similarity index 100% rename from tests/modules/misc/gtk/gtk2-basic-config.nix rename to tests/modules/misc/gtk/gtk2/gtk2-basic-config.nix diff --git a/tests/modules/misc/gtk/gtk2-config-file-location.nix b/tests/modules/misc/gtk/gtk2/gtk2-config-file-location.nix similarity index 100% rename from tests/modules/misc/gtk/gtk2-config-file-location.nix rename to tests/modules/misc/gtk/gtk2/gtk2-config-file-location.nix diff --git a/tests/modules/misc/gtk/gtk3-basic-settings-expected.ini b/tests/modules/misc/gtk/gtk3/gtk3-basic-settings-expected.ini similarity index 100% rename from tests/modules/misc/gtk/gtk3-basic-settings-expected.ini rename to tests/modules/misc/gtk/gtk3/gtk3-basic-settings-expected.ini diff --git a/tests/modules/misc/gtk/gtk3-basic-settings.nix b/tests/modules/misc/gtk/gtk3/gtk3-basic-settings.nix similarity index 100% rename from tests/modules/misc/gtk/gtk3-basic-settings.nix rename to tests/modules/misc/gtk/gtk3/gtk3-basic-settings.nix diff --git a/tests/modules/misc/gtk/gtk4/gtk4-basic-settings-expected.css b/tests/modules/misc/gtk/gtk4/gtk4-basic-settings-expected.css new file mode 100644 index 000000000000..7d27b3119394 --- /dev/null +++ b/tests/modules/misc/gtk/gtk4/gtk4-basic-settings-expected.css @@ -0,0 +1,5 @@ +/** + * GTK 4 reads the theme configured by gtk-theme-name, but ignores it. + * It does however respect user CSS, so import the theme from here. +**/ +@import url("file://@catppuccin-gtk@/share/themes/catppuccin-macchiato-blue-standard/gtk-4.0/gtk.css"); diff --git a/tests/modules/misc/gtk/gtk4/gtk4-basic-settings-expected.ini b/tests/modules/misc/gtk/gtk4/gtk4-basic-settings-expected.ini new file mode 100644 index 000000000000..978299e23552 --- /dev/null +++ b/tests/modules/misc/gtk/gtk4/gtk4-basic-settings-expected.ini @@ -0,0 +1,4 @@ +[Settings] +gtk-cursor-blink=false +gtk-recent-files-limit=20 +gtk-theme-name=catppuccin-macchiato-blue-standard diff --git a/tests/modules/misc/gtk/gtk4/gtk4-basic-settings.nix b/tests/modules/misc/gtk/gtk4/gtk4-basic-settings.nix new file mode 100644 index 000000000000..101cb0258564 --- /dev/null +++ b/tests/modules/misc/gtk/gtk4/gtk4-basic-settings.nix @@ -0,0 +1,30 @@ +{ pkgs, ... }: +{ + gtk = { + enable = true; + theme = { + name = "catppuccin-macchiato-blue-standard"; + package = pkgs.catppuccin-gtk; + }; + gtk4 = { + extraConfig = { + gtk-cursor-blink = false; + gtk-recent-files-limit = 20; + }; + }; + }; + + nmt.script = + let + gtk4Path = "home-files/.config/gtk-4.0"; + in + '' + assertFileExists ${gtk4Path}/settings.ini + assertFileContent ${gtk4Path}/settings.ini \ + ${./gtk4-basic-settings-expected.ini} + + assertFileExists ${gtk4Path}/gtk.css + assertFileContent ${gtk4Path}/gtk.css \ + ${./gtk4-basic-settings-expected.css} + ''; +} diff --git a/tests/modules/misc/gtk/gtk4/gtk4-no-theme-css-injection-expected.css b/tests/modules/misc/gtk/gtk4/gtk4-no-theme-css-injection-expected.css new file mode 100644 index 000000000000..1afa2c2d13ae --- /dev/null +++ b/tests/modules/misc/gtk/gtk4/gtk4-no-theme-css-injection-expected.css @@ -0,0 +1,8 @@ +/* Custom user CSS */ +window { + background-color: #2d2d2d; +} + +button { + border-radius: 8px; +} diff --git a/tests/modules/misc/gtk/gtk4/gtk4-no-theme-css-injection.nix b/tests/modules/misc/gtk/gtk4/gtk4-no-theme-css-injection.nix new file mode 100644 index 000000000000..6cb3ce5d4eba --- /dev/null +++ b/tests/modules/misc/gtk/gtk4/gtk4-no-theme-css-injection.nix @@ -0,0 +1,25 @@ +{ + # Test GTK4 theme CSS injection with both theme and custom CSS + gtk = { + enable = true; + + gtk4 = { + extraCss = '' + /* Custom user CSS */ + window { + background-color: #2d2d2d; + } + + button { + border-radius: 8px; + } + ''; + }; + }; + + nmt.script = '' + # GTK4 CSS should exist and contain no theme import and only custom CSS + assertFileExists home-files/.config/gtk-4.0/gtk.css + assertFileContent home-files/.config/gtk-4.0/gtk.css ${./gtk4-no-theme-css-injection-expected.css} + ''; +} diff --git a/tests/modules/misc/gtk/gtk4/gtk4-theme-css-injection-expected.css b/tests/modules/misc/gtk/gtk4/gtk4-theme-css-injection-expected.css new file mode 100644 index 000000000000..626fbe2e8446 --- /dev/null +++ b/tests/modules/misc/gtk/gtk4/gtk4-theme-css-injection-expected.css @@ -0,0 +1,13 @@ +/** + * GTK 4 reads the theme configured by gtk-theme-name, but ignores it. + * It does however respect user CSS, so import the theme from here. +**/ +@import url("file://@gnome-themes-extra@/share/themes/Adwaita-dark/gtk-4.0/gtk.css"); +/* Custom user CSS */ +window { + background-color: #2d2d2d; +} + +button { + border-radius: 8px; +} diff --git a/tests/modules/misc/gtk/gtk4/gtk4-theme-css-injection.nix b/tests/modules/misc/gtk/gtk4/gtk4-theme-css-injection.nix new file mode 100644 index 000000000000..e8dec1463d4e --- /dev/null +++ b/tests/modules/misc/gtk/gtk4/gtk4-theme-css-injection.nix @@ -0,0 +1,30 @@ +{ pkgs, ... }: +{ + # Test GTK4 theme CSS injection with both theme and custom CSS + gtk = { + enable = true; + + gtk4 = { + theme = { + name = "Adwaita-dark"; + package = pkgs.gnome-themes-extra; + }; + extraCss = '' + /* Custom user CSS */ + window { + background-color: #2d2d2d; + } + + button { + border-radius: 8px; + } + ''; + }; + }; + + nmt.script = '' + # GTK4 CSS should exist and contain both theme import and custom CSS + assertFileExists home-files/.config/gtk-4.0/gtk.css + assertFileContent home-files/.config/gtk-4.0/gtk.css ${./gtk4-theme-css-injection-expected.css} + ''; +}