diff --git a/quickshell/Common/CacheData.qml b/quickshell/Common/CacheData.qml index 8c9835a3c..e440cb16d 100644 --- a/quickshell/Common/CacheData.qml +++ b/quickshell/Common/CacheData.qml @@ -24,12 +24,13 @@ Singleton { readonly property var _pinKeys: ["brightnessDevicePins", "wifiNetworkPins", "bluetoothDevicePins", "audioInputDevicePins", "audioOutputDevicePins"] readonly property var _historyKeys: ["browserUsageHistory", "filePickerUsageHistory"] - readonly property var _dataKeys: ["fileBrowserSettings", "processFilterTypes", "pluginViewSort", "pluginViewFilter", "dashFocusCardId", "mediaLyricsOpen", "matugenPreviews"].concat(_pinKeys, _historyKeys) + readonly property var _dataKeys: ["fileBrowserSettings", "processFilterTypes", "pluginViewSort", "pluginViewFilter", "dashFocusCardId", "mediaLyricsOpen", "matugenPreviews", "matugenAppliedKey"].concat(_pinKeys, _historyKeys) property string pluginViewFilter: "enabled" property string dashFocusCardId: "" property bool mediaLyricsOpen: false property var matugenPreviews: ({}) + property string matugenAppliedKey: "" property var pluginViewSort: ({ by: "modified", descending: true @@ -131,6 +132,7 @@ Singleton { dashFocusCardId = typeof cache.dashFocusCardId === "string" ? cache.dashFocusCardId : ""; mediaLyricsOpen = cache.mediaLyricsOpen === true; matugenPreviews = typeof cache.matugenPreviews?.key === "string" ? cache.matugenPreviews : {}; + matugenAppliedKey = typeof cache.matugenAppliedKey === "string" ? cache.matugenAppliedKey : ""; const pluginSort = cache.pluginViewSort; pluginViewSort = { by: ["name", "author", "modified"].includes(pluginSort?.by) ? pluginSort.by : "modified", @@ -209,6 +211,7 @@ Singleton { "dashFocusCardId": dashFocusCardId, "mediaLyricsOpen": mediaLyricsOpen, "matugenPreviews": matugenPreviews, + "matugenAppliedKey": matugenAppliedKey, "fileBrowserSettings": fileBrowserSettings, "configVersion": cacheConfigVersion }; diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index 58ffcf35e..5c7ce8d04 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -164,6 +164,7 @@ Singleton { property string currentThemeCategory: Spec.SPEC.currentThemeCategory.def property string customThemeFile: Spec.SPEC.customThemeFile.def property var registryThemeVariants: Spec.SPEC.registryThemeVariants.def + property bool generateThemeAtStartup: Spec.SPEC.generateThemeAtStartup.def property string matugenScheme: Spec.SPEC.matugenScheme.def property bool matugenSmartMode: Spec.SPEC.matugenSmartMode.def property string matugenSourceMode: Spec.SPEC.matugenSourceMode.def diff --git a/quickshell/Common/Theme.qml b/quickshell/Common/Theme.qml index 4f0cf20c1..8b79a4cde 100644 --- a/quickshell/Common/Theme.qml +++ b/quickshell/Common/Theme.qml @@ -111,6 +111,7 @@ Singleton { property var _pendingGenerateParams: null property int _colorsRetryCount: 0 property double _lastGenerateMs: 0 + property string _matugenRunKey: "" property bool blurLayersActive: false property bool matugenToastSuppressed: false @@ -161,46 +162,7 @@ Singleton { Quickshell.execDetached(["mkdir", "-p", stateDir]); Proc.runCommand("matugenCheck", ["sh", "-c", "command -v matugen"], (output, code) => { matugenAvailable = (code === 0) && !envDisableMatugen; - const isGreeterMode = (typeof SessionData !== "undefined" && SessionData.isGreeterMode); - - if (!matugenAvailable || isGreeterMode) { - return; - } - - if (colorsFileLoadFailed && currentTheme === dynamic && rawWallpaperPath) { - log.info("Matugen now available, regenerating colors for dynamic theme"); - const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode); - const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"; - const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"; - if (rawWallpaperPath.startsWith("#")) { - setDesiredTheme("hex", rawWallpaperPath, isLight, iconTheme, selectedMatugenType); - } else { - setDesiredTheme("image", rawWallpaperPath, isLight, iconTheme, selectedMatugenType); - } - return; - } - - const isLight = (typeof SessionData !== "undefined" && SessionData.isLightMode); - const iconTheme = (typeof SettingsData !== "undefined" && SettingsData.iconTheme) ? SettingsData.iconTheme : "System Default"; - - if (currentTheme === dynamic) { - if (rawWallpaperPath) { - const selectedMatugenType = (typeof SettingsData !== "undefined" && SettingsData.matugenScheme) ? SettingsData.matugenScheme : "scheme-tonal-spot"; - if (rawWallpaperPath.startsWith("#")) { - setDesiredTheme("hex", rawWallpaperPath, isLight, iconTheme, selectedMatugenType); - } else { - setDesiredTheme("image", rawWallpaperPath, isLight, iconTheme, selectedMatugenType); - } - } - } else if (currentTheme !== "custom") { - const darkTheme = StockThemes.getThemeByName(currentTheme, false); - const lightTheme = StockThemes.getThemeByName(currentTheme, true); - if (darkTheme && darkTheme.primary) { - const stockColors = buildMatugenColorsFromTheme(darkTheme, lightTheme); - const themeData = isLight ? lightTheme : darkTheme; - setDesiredTheme("hex", themeData.primary, isLight, iconTheme, themeData.matugen_type, stockColors); - } - } + generateSystemThemesFromCurrentTheme(); }, 0); if (typeof SessionData !== "undefined") { SessionData.isLightModeChanged.connect(root.onLightModeChanged); @@ -1763,10 +1725,6 @@ Singleton { return; } - log.info("Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", stockColors ? "(stock colors)" : "(dynamic)"); - - themeGenerationStarting(); - const desired = { "kind": kind, "value": value, @@ -1776,9 +1734,6 @@ Singleton { "runUserTemplates": (typeof SettingsData !== "undefined") ? SettingsData.runUserMatugenTemplates : true }; - log.debug("Starting matugen worker"); - workerRunning = true; - const args = ["dms", "matugen", "queue", "--state-dir", stateDir, "--shell-dir", shellDir, "--config-dir", configDir, "--kind", desired.kind, "--value", desired.value, "--mode", desired.mode, "--icon-theme", desired.iconTheme, "--matugen-type", desired.matugenType,]; if (!desired.runUserTemplates) { @@ -1871,6 +1826,20 @@ Singleton { } } + const runKey = Qt.md5(JSON.stringify(args)); + const skipUnchanged = !_matugenRunKey && !colorsFileLoadFailed && typeof SettingsData !== "undefined" && !SettingsData.generateThemeAtStartup; + if (skipUnchanged && runKey === CacheData.matugenAppliedKey) { + log.info("Theme inputs unchanged since the last run, skipping startup generation"); + return; + } + + log.info("Setting desired theme -", kind, "mode:", isLight ? "light" : "dark", stockColors ? "(stock colors)" : "(dynamic)"); + themeGenerationStarting(); + + log.debug("Starting matugen worker"); + workerRunning = true; + _matugenRunKey = runKey; + _lastGenerateMs = Date.now(); systemThemeGenerator.command = args; systemThemeGenerator.running = true; } @@ -1880,7 +1849,6 @@ Singleton { if (!matugenAvailable || isGreeterMode) return; - _lastGenerateMs = Date.now(); _pendingGenerateParams = true; _themeGenerateDebounce.restart(); } @@ -2287,6 +2255,10 @@ Singleton { root.matugenCompleted(currentMode, "error"); } + const appliedKey = (exitCode === 0 || exitCode === 2) ? _matugenRunKey : ""; + if (CacheData.matugenAppliedKey !== appliedKey) + CacheData.set("matugenAppliedKey", appliedKey); + if (!pendingThemeRequest) { if (SettingsData.matugenTemplateGtk) patchGtk3colors(); diff --git a/quickshell/Common/settings/SettingsSpec.js b/quickshell/Common/settings/SettingsSpec.js index 194b056f1..fc9660c27 100644 --- a/quickshell/Common/settings/SettingsSpec.js +++ b/quickshell/Common/settings/SettingsSpec.js @@ -42,6 +42,9 @@ var LOCAL_SPEC = { def: "", onChange: "regenSystemThemes" }, + generateThemeAtStartup: { + def: true + }, popupTransparency: { def: 1.0, coerce: Util.percentToUnit diff --git a/quickshell/Modules/Settings/ThemeColorsTab.qml b/quickshell/Modules/Settings/ThemeColorsTab.qml index 6e77370fb..01d44daf5 100644 --- a/quickshell/Modules/Settings/ThemeColorsTab.qml +++ b/quickshell/Modules/Settings/ThemeColorsTab.qml @@ -962,6 +962,25 @@ Item { } } } + + SettingsCard { + tab: "theme" + tags: ["matugen", "startup", "theming"] + title: I18n.tr("Startup Behavior", "settings card title") + settingKey: "themeStartupBehavior" + iconName: "power_settings_new" + visible: Theme.matugenAvailable + + SettingsToggleRow { + tab: "theme" + tags: ["matugen", "startup", "generate"] + settingKey: "generateThemeAtStartup" + text: I18n.tr("Generate Theme at Startup", "toggle label") + description: I18n.tr("Regenerate matugen colors when DMS starts, even if nothing changed.", "toggle description") + checked: SettingsData.generateThemeAtStartup + onToggled: checked => SettingsData.set("generateThemeAtStartup", checked) + } + } } FileBrowserModal { diff --git a/quickshell/translations/settings_search_index.json b/quickshell/translations/settings_search_index.json index 0325ba07c..b1b06c24b 100644 --- a/quickshell/translations/settings_search_index.json +++ b/quickshell/translations/settings_search_index.json @@ -6034,6 +6034,44 @@ ], "parentLabel": "Wallpaper & colors" }, + { + "section": "generateThemeAtStartup", + "label": "Generate Theme at Startup", + "tabIndex": 10, + "category": "Theme & colors", + "keywords": [ + "appearance", + "background", + "bg", + "changed", + "colors", + "colour", + "colours", + "desktop", + "dynamic", + "even", + "generate", + "hue", + "image", + "look", + "material", + "matugen", + "nothing", + "palette", + "picture", + "regenerate", + "scheme", + "starts", + "startup", + "style", + "theme", + "tint", + "wallpaper", + "wallpaper colors" + ], + "parentLabel": "Wallpaper & colors", + "description": "Regenerate matugen colors when DMS starts, even if nothing changed." + }, { "section": "matugenSpec", "label": "Material palette", @@ -6130,6 +6168,47 @@ ], "parentLabel": "Wallpaper & colors" }, + { + "section": "themeStartupBehavior", + "label": "Startup Behavior", + "tabIndex": 10, + "category": "Theme & colors", + "keywords": [ + "appearance", + "background", + "behavior", + "bg", + "changed", + "colors", + "colour", + "colours", + "desktop", + "dynamic", + "even", + "hue", + "image", + "look", + "material", + "matugen", + "nothing", + "palette", + "picture", + "regenerate", + "scheme", + "starts", + "startup", + "style", + "theme", + "theming", + "tint", + "wallpaper", + "wallpaper colors" + ], + "parentLabel": "Wallpaper & colors", + "icon": "power_settings_new", + "description": "Regenerate matugen colors when DMS starts, even if nothing changed.", + "conditionKey": "matugenAvailable" + }, { "section": "themeColor", "label": "Theme",