From 1e48976ae5c6c02c4d1d80757a14d87502c0eb1d Mon Sep 17 00:00:00 2001 From: bbedward Date: Thu, 19 Mar 2026 14:44:14 -0400 Subject: [PATCH] theme: add matugen contrast slider fixes #2026 --- core/cmd/dms/commands_matugen.go | 4 ++++ core/internal/matugen/matugen.go | 11 +++++++++ core/internal/server/matugen_handler.go | 1 + quickshell/Common/SettingsData.qml | 23 +++++++++++++----- quickshell/Common/Theme.qml | 24 +++++++------------ quickshell/Common/settings/SettingsSpec.js | 9 +++---- .../Modules/Settings/ThemeColorsTab.qml | 19 ++++++++++++++- 7 files changed, 64 insertions(+), 27 deletions(-) diff --git a/core/cmd/dms/commands_matugen.go b/core/cmd/dms/commands_matugen.go index 38ad2965..566f3600 100644 --- a/core/cmd/dms/commands_matugen.go +++ b/core/cmd/dms/commands_matugen.go @@ -57,6 +57,7 @@ func init() { cmd.Flags().Bool("sync-mode-with-portal", false, "Sync color scheme with GNOME portal") cmd.Flags().Bool("terminals-always-dark", false, "Force terminal themes to dark variant") cmd.Flags().String("skip-templates", "", "Comma-separated list of templates to skip") + cmd.Flags().Float64("contrast", 0, "Contrast value from -1 to 1 (0 = standard)") } matugenQueueCmd.Flags().Bool("wait", true, "Wait for completion") @@ -77,6 +78,7 @@ func buildMatugenOptions(cmd *cobra.Command) matugen.Options { syncModeWithPortal, _ := cmd.Flags().GetBool("sync-mode-with-portal") terminalsAlwaysDark, _ := cmd.Flags().GetBool("terminals-always-dark") skipTemplates, _ := cmd.Flags().GetString("skip-templates") + contrast, _ := cmd.Flags().GetFloat64("contrast") return matugen.Options{ StateDir: stateDir, @@ -87,6 +89,7 @@ func buildMatugenOptions(cmd *cobra.Command) matugen.Options { Mode: matugen.ColorMode(mode), IconTheme: iconTheme, MatugenType: matugenType, + Contrast: contrast, RunUserTemplates: runUserTemplates, StockColors: stockColors, SyncModeWithPortal: syncModeWithPortal, @@ -128,6 +131,7 @@ func runMatugenQueue(cmd *cobra.Command, args []string) { "syncModeWithPortal": opts.SyncModeWithPortal, "terminalsAlwaysDark": opts.TerminalsAlwaysDark, "skipTemplates": opts.SkipTemplates, + "contrast": opts.Contrast, "wait": wait, }, } diff --git a/core/internal/matugen/matugen.go b/core/internal/matugen/matugen.go index 0dbc9b93..a29d324f 100644 --- a/core/internal/matugen/matugen.go +++ b/core/internal/matugen/matugen.go @@ -99,6 +99,7 @@ type Options struct { Mode ColorMode IconTheme string MatugenType string + Contrast float64 RunUserTemplates bool ColorsOnly bool StockColors string @@ -228,6 +229,7 @@ func buildOnce(opts *Options) (bool, error) { log.Info("Running matugen color hex with stock color overrides") args := []string{"color", "hex", primaryDark, "-m", string(opts.Mode), "-t", opts.MatugenType, "-c", cfgFile.Name()} + args = appendContrastArg(args, opts.Contrast) args = append(args, importArgs...) if err := runMatugen(args); err != nil { return false, err @@ -264,6 +266,7 @@ func buildOnce(opts *Options) (bool, error) { args = []string{opts.Kind, opts.Value} } args = append(args, "-m", string(opts.Mode), "-t", opts.MatugenType, "-c", cfgFile.Name()) + args = appendContrastArg(args, opts.Contrast) args = append(args, importArgs...) if err := runMatugen(args); err != nil { return false, err @@ -299,6 +302,13 @@ func buildOnce(opts *Options) (bool, error) { return true, nil } +func appendContrastArg(args []string, contrast float64) []string { + if contrast == 0 { + return args + } + return append(args, "--contrast", strconv.FormatFloat(contrast, 'f', -1, 64)) +} + func buildMergedConfig(opts *Options, cfgFile *os.File, tmpDir string) error { userConfigPath := filepath.Join(opts.ConfigDir, "matugen", "config.toml") @@ -687,6 +697,7 @@ func execDryRun(opts *Options, flags matugenFlags) (string, error) { baseArgs = []string{opts.Kind, opts.Value} } baseArgs = append(baseArgs, "-m", "dark", "-t", opts.MatugenType, "--json", "hex", "--dry-run") + baseArgs = appendContrastArg(baseArgs, opts.Contrast) if flags.isV4 { baseArgs = append(baseArgs, "--source-color-index", "0", "--old-json-output") } diff --git a/core/internal/server/matugen_handler.go b/core/internal/server/matugen_handler.go index c59bba0c..73c6ad61 100644 --- a/core/internal/server/matugen_handler.go +++ b/core/internal/server/matugen_handler.go @@ -29,6 +29,7 @@ func handleMatugenQueue(conn net.Conn, req models.Request) { SyncModeWithPortal: models.GetOr(req, "syncModeWithPortal", false), TerminalsAlwaysDark: models.GetOr(req, "terminalsAlwaysDark", false), SkipTemplates: models.GetOr(req, "skipTemplates", ""), + Contrast: models.GetOr(req, "contrast", 0.0), } wait := models.GetOr(req, "wait", true) diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index 7f9f4a3a..5f96dbfd 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -130,6 +130,7 @@ Singleton { property string customThemeFile: "" property var registryThemeVariants: ({}) property string matugenScheme: "scheme-tonal-spot" + property real matugenContrast: 0 property bool runUserMatugenTemplates: true property string matugenTargetMonitor: "" property real popupTransparency: 1.0 @@ -484,9 +485,15 @@ Singleton { property bool matugenTemplateZed: true property var matugenTemplateNeovimSettings: ({ - "dark": { "baseTheme": "github_dark", "harmony": 0.5 }, - "light": { "baseTheme": "github_light", "harmony": 0.5 } - }) + "dark": { + "baseTheme": "github_dark", + "harmony": 0.5 + }, + "light": { + "baseTheme": "github_light", + "harmony": 0.5 + } + }) property bool showDock: false property bool dockAutoHide: false @@ -1320,9 +1327,7 @@ Singleton { return true; const msg = String(error || "").toLowerCase(); - return msg.indexOf("file does not exist") !== -1 - || msg.indexOf("no such file") !== -1 - || msg.indexOf("enoent") !== -1; + return msg.indexOf("file does not exist") !== -1 || msg.indexOf("no such file") !== -1 || msg.indexOf("enoent") !== -1; } function loadPluginSettings() { @@ -1942,6 +1947,12 @@ Singleton { } } + function setMatugenContrast(value) { + if (matugenContrast === value) + return; + set("matugenContrast", value); + } + function setRunUserMatugenTemplates(enabled) { if (runUserMatugenTemplates === enabled) return; diff --git a/quickshell/Common/Theme.qml b/quickshell/Common/Theme.qml index f5f22e52..fc0b663e 100644 --- a/quickshell/Common/Theme.qml +++ b/quickshell/Common/Theme.qml @@ -1249,10 +1249,7 @@ Singleton { const defaults = themeData.variants.defaults || {}; const modeDefaults = defaults[colorMode] || defaults.dark || {}; const isGreeterMode = typeof SessionData !== "undefined" && SessionData.isGreeterMode; - const stored = isGreeterMode ? - (GreetdSettings.registryThemeVariants[themeId]?.[colorMode] || modeDefaults) : - (typeof SettingsData !== "undefined" ? - SettingsData.getRegistryThemeMultiVariant(themeId, modeDefaults, colorMode) : modeDefaults); + const stored = isGreeterMode ? (GreetdSettings.registryThemeVariants[themeId]?.[colorMode] || modeDefaults) : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeMultiVariant(themeId, modeDefaults, colorMode) : modeDefaults); var flavorId = stored.flavor || modeDefaults.flavor || ""; const accentId = stored.accent || modeDefaults.accent || ""; var flavor = findVariant(themeData.variants.flavors, flavorId); @@ -1279,9 +1276,7 @@ Singleton { if (themeData.variants.options && themeData.variants.options.length > 0) { const isGreeterMode = typeof SessionData !== "undefined" && SessionData.isGreeterMode; - const selectedVariantId = isGreeterMode - ? (typeof GreetdSettings.registryThemeVariants[themeId] === "string" ? GreetdSettings.registryThemeVariants[themeId] : themeData.variants.default) - : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeVariant(themeId, themeData.variants.default) : themeData.variants.default); + const selectedVariantId = isGreeterMode ? (typeof GreetdSettings.registryThemeVariants[themeId] === "string" ? GreetdSettings.registryThemeVariants[themeId] : themeData.variants.default) : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeVariant(themeId, themeData.variants.default) : themeData.variants.default); const variant = findVariant(themeData.variants.options, selectedVariantId); if (variant) { const variantColors = variant[colorMode] || variant.dark || variant.light || {}; @@ -1554,6 +1549,9 @@ Singleton { if (typeof SettingsData !== "undefined" && SettingsData.terminalsAlwaysDark) { args.push("--terminals-always-dark"); } + if (typeof SettingsData !== "undefined" && SettingsData.matugenContrast !== 0) { + args.push("--contrast", SettingsData.matugenContrast.toString()); + } if (typeof SettingsData !== "undefined") { const skipTemplates = []; @@ -1654,12 +1652,8 @@ Singleton { const darkDefaults = defaults.dark || {}; const lightDefaults = defaults.light || defaults.dark || {}; const isGreeterMode = typeof SessionData !== "undefined" && SessionData.isGreeterMode; - const storedDark = isGreeterMode - ? (GreetdSettings.registryThemeVariants[themeId]?.dark || darkDefaults) - : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeMultiVariant(themeId, darkDefaults, "dark") : darkDefaults); - const storedLight = isGreeterMode - ? (GreetdSettings.registryThemeVariants[themeId]?.light || lightDefaults) - : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeMultiVariant(themeId, lightDefaults, "light") : lightDefaults); + const storedDark = isGreeterMode ? (GreetdSettings.registryThemeVariants[themeId]?.dark || darkDefaults) : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeMultiVariant(themeId, darkDefaults, "dark") : darkDefaults); + const storedLight = isGreeterMode ? (GreetdSettings.registryThemeVariants[themeId]?.light || lightDefaults) : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeMultiVariant(themeId, lightDefaults, "light") : lightDefaults); const darkFlavorId = storedDark.flavor || darkDefaults.flavor || ""; const lightFlavorId = storedLight.flavor || lightDefaults.flavor || ""; const accentId = storedDark.accent || darkDefaults.accent || ""; @@ -1678,9 +1672,7 @@ Singleton { } } else if (customThemeRawData.variants.options) { const isGreeterMode = typeof SessionData !== "undefined" && SessionData.isGreeterMode; - const selectedVariantId = isGreeterMode - ? (typeof GreetdSettings.registryThemeVariants[themeId] === "string" ? GreetdSettings.registryThemeVariants[themeId] : customThemeRawData.variants.default) - : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeVariant(themeId, customThemeRawData.variants.default) : customThemeRawData.variants.default); + const selectedVariantId = isGreeterMode ? (typeof GreetdSettings.registryThemeVariants[themeId] === "string" ? GreetdSettings.registryThemeVariants[themeId] : customThemeRawData.variants.default) : (typeof SettingsData !== "undefined" ? SettingsData.getRegistryThemeVariant(themeId, customThemeRawData.variants.default) : customThemeRawData.variants.default); const variant = findVariant(customThemeRawData.variants.options, selectedVariantId); if (variant) { darkTheme = mergeColors(darkTheme, variant.dark || {}); diff --git a/quickshell/Common/settings/SettingsSpec.js b/quickshell/Common/settings/SettingsSpec.js index 4bffbfbb..44bd17d6 100644 --- a/quickshell/Common/settings/SettingsSpec.js +++ b/quickshell/Common/settings/SettingsSpec.js @@ -11,6 +11,7 @@ var SPEC = { customThemeFile: { def: "" }, registryThemeVariants: { def: {} }, matugenScheme: { def: "scheme-tonal-spot", onChange: "regenSystemThemes" }, + matugenContrast: { def: 0, onChange: "regenSystemThemes" }, runUserMatugenTemplates: { def: true, onChange: "regenSystemThemes" }, matugenTargetMonitor: { def: "", onChange: "regenSystemThemes" }, @@ -299,10 +300,10 @@ var SPEC = { matugenTemplateZed: { def: true }, matugenTemplateNeovimSettings: { - def: { - dark: { baseTheme: "github_dark", harmony: 0.5 }, - light: { baseTheme: "github_light", harmony: 0.5 } - } + def: { + dark: { baseTheme: "github_dark", harmony: 0.5 }, + light: { baseTheme: "github_light", harmony: 0.5 } + } }, showDock: { def: false }, diff --git a/quickshell/Modules/Settings/ThemeColorsTab.qml b/quickshell/Modules/Settings/ThemeColorsTab.qml index 1708e500..6ffb4512 100644 --- a/quickshell/Modules/Settings/ThemeColorsTab.qml +++ b/quickshell/Modules/Settings/ThemeColorsTab.qml @@ -517,7 +517,24 @@ Item { font.pixelSize: Theme.fontSizeSmall color: Theme.surfaceVariantText wrapMode: Text.WordWrap - width: parent.width + width: parent.width - Theme.spacingM * 2 + x: Theme.spacingM + } + + SettingsSliderRow { + tab: "theme" + tags: ["matugen", "contrast", "dynamic"] + settingKey: "matugenContrast" + text: I18n.tr("Matugen Contrast") + description: I18n.tr("Adjusts contrast of generated colors (-100 = minimum, 0 = standard, 100 = maximum)") + value: Math.round(SettingsData.matugenContrast * 100) + minimum: -100 + maximum: 100 + unit: "%" + defaultValue: 0 + enabled: Theme.matugenAvailable + opacity: enabled ? 1 : 0.4 + onSliderDragFinished: finalValue => SettingsData.setMatugenContrast(finalValue / 100) } }