{ pkgs, lib, config, ... }: with lib; with lib.my; let cfg = config.modules.desktop.themes; in { options.modules.desktop.themes = with types; { active = mkOption { type = types.nullOr types.str; default = null; description = "Name of the theme to apply; see modules/desktop/themes for a list of valid options"; }; rounding = mkOpt int 10; padding = mkOpt int 6; dark = mkOpt bool false; gtkTheme = { name = mkOpt (nullOr str) null; package = mkOpt (nullOr package) null; }; kvantumTheme = { name = mkOpt (nullOr str) null; package = mkOpt (nullOr package) null; }; iconTheme = { name = mkOpt (nullOr str) null; package = mkOpt (nullOr package) null; }; cursorTheme = { name = mkOpt (nullOr str) null; package = mkOpt (nullOr package) null; size = mkOpt int 24; }; editor = { vscode = { colorTheme = { name = mkOpt (nullOr str) null; extension = mkOpt (nullOr package) null; }; iconTheme = { name = mkOpt (nullOr str) null; extension = mkOpt (nullOr package) null; }; }; }; niri = { accent = mkOpt str ""; inactive = mkOpt str ""; shadow = mkOpt str ""; background = mkOpt str ""; }; waybarTop = mkOpt str ""; wob = { borderColor = mkOpt (nullOr str) null; backgroundColor = mkOpt (nullOr str) null; barColor = mkOpt (nullOr str) null; }; rofiTop = mkOpt (nullOr str) null; wezterm = mkOpt (nullOr str) null; vicinae = mkOpt (nullOr str) null; }; config = mkIf (cfg.active != null) { programs.dconf.enable = true; # i think this may be done by home-manager already?? # better safe than sorry hm.dconf = { enable = true; settings."org/gnome/desktop/interface".color-scheme = mkIf cfg.dark "prefer-dark"; settings."org/gnome/desktop/interface".gtk-theme = cfg.gtkTheme.name; settings."org/gnome/desktop/interface".icon-theme = cfg.iconTheme.name; settings."org/gnome/desktop/interface".cursor-theme = cfg.cursorTheme.name; settings."org/gnome/desktop/interface".cursor-size = cfg.cursorTheme.size; settings."org/gnome/shell/extensions/user-theme".name = cfg.gtkTheme.name; }; hm.gtk = { enable = true; cursorTheme = { name = cfg.cursorTheme.name; package = cfg.cursorTheme.package; size = cfg.cursorTheme.size; }; iconTheme = cfg.iconTheme; theme = cfg.gtkTheme; gtk3.extraConfig.gtk-application-prefer-dark-theme = mkIf cfg.dark "1"; gtk4.extraConfig.gtk-application-prefer-dark-theme = mkIf cfg.dark "1"; # https://stopthemingmy.app/ # https://tenor.com/view/blah-bla-gif-23055284 gtk4.theme = cfg.gtkTheme; }; hm.qt = { enable = true; platformTheme.name = if (cfg.kvantumTheme.name != null) then "qtct" else "gtk3"; style.name = mkIf (cfg.kvantumTheme.name != null) "kvantum"; }; hm.home.pointerCursor = { gtk.enable = true; x11.enable = true; name = cfg.cursorTheme.name; package = cfg.cursorTheme.package; size = cfg.cursorTheme.size; }; hm.services.dunst.iconTheme = { name = cfg.iconTheme.name; package = cfg.iconTheme.package; }; programs.regreet = { theme = cfg.gtkTheme; iconTheme = cfg.iconTheme; cursorTheme = { inherit (cfg.cursorTheme) name package; }; }; hm.programs.vscode.profiles.default = { extensions = [ cfg.editor.vscode.colorTheme.extension cfg.editor.vscode.iconTheme.extension ]; userSettings = { "workbench.colorTheme" = cfg.editor.vscode.colorTheme.name; "workbench.iconTheme" = cfg.editor.vscode.iconTheme.name; }; }; hm.programs.waybar.style = (builtins.replaceStrings [ "@rounding" ] [ (builtins.toString cfg.rounding) ] (builtins.concatStringsSep "\n" ([ cfg.waybarTop (lib.readFile ./config/waybar.css) ] ++ lib.zipListsWith (name: hex: "@define-color base${name} #${hex};") (builtins.genList (i: lib.fixedWidthString 2 "0" (lib.toUpper (lib.toHexString i))) 24) config.scheme.toList))); hm.services.wob.settings."" = { border_color = cfg.wob.borderColor; background_color = cfg.wob.backgroundColor; bar_color = cfg.wob.barColor; }; hm.programs.rofi.theme = builtins.toFile "rofi.rasi" (builtins.replaceStrings [ "@rounding" ] [ (builtins.toString cfg.rounding) ] (builtins.concatStringsSep "\n" ([ cfg.rofiTop (lib.readFile ./config/rofi.rasi) ] ++ lib.zipListsWith (name: hex: "* { base${name}: #${hex}; }") (builtins.genList (i: lib.fixedWidthString 2 "0" (lib.toUpper (lib.toHexString i))) 24) config.scheme.toList))); hm.services.vicinae.settings.theme = let themeConf = { name = cfg.vicinae; iconTheme = cfg.iconTheme.name; }; in { light = themeConf; dark = themeConf; }; hm.xdg.configFile = let iniFmt = pkgs.formats.ini {}; # souls are forged in the fires of hell mkQtctConf = version: let zeroCount = if version == 5 then 5 else if version == 6 then 10 else builtins.throw "invalid qtct version"; zeros = builtins.concatStringsSep "," (builtins.genList (_: "0") zeroCount); weight = if version == 5 then 50 else if version == 6 then 400 else builtins.throw "invalid qtct version"; in { Appearance = { icon_theme = cfg.iconTheme.name; standard_dialogs = "xdgdesktopportal"; style = "kvantum"; # its ok if this is always the case, override it anyway }; Fonts = with config.modules.desktop.fonts.fonts; { general = ''"${sansSerif.family},${toString sansSerif.size},-1,5,${toString weight},${zeros},1"''; fixed = ''"${monospace.family},-1,${toString monospace.size},5,${toString weight},${zeros},1"''; }; }; in mkMerge [ { # technically could cause issues with KDE if we use that # not a concern for now "kdeglobals".text = '' [Icons] Theme=${cfg.iconTheme.name} ''; "qt5ct/qt5ct.conf".source = iniFmt.generate "qt5ct.conf" (mkQtctConf 5); "qt6ct/qt6ct.conf".source = iniFmt.generate "qt6ct.conf" (mkQtctConf 6); } (mkIf (cfg.kvantumTheme.name != null) { "Kvantum/${cfg.kvantumTheme.name}".source = "${cfg.kvantumTheme.package}/share/Kvantum/${cfg.kvantumTheme.name}"; "Kvantum/kvantum.kvconfig".text = '' [General] theme=${cfg.kvantumTheme.name} ''; }) ]; }; }