diff --git a/core/cmd/dms/commands_doctor.go b/core/cmd/dms/commands_doctor.go index 206a8597..7a792136 100644 --- a/core/cmd/dms/commands_doctor.go +++ b/core/cmd/dms/commands_doctor.go @@ -557,6 +557,8 @@ func detectRunningWM() string { return "Hyprland" case os.Getenv("NIRI_SOCKET") != "": return "niri" + case os.Getenv("MANGO_INSTANCE_SIGNATURE") != "": + return "MangoWC" case os.Getenv("MIRACLESOCK") != "": return "Miracle WM" case os.Getenv("XDG_CURRENT_DESKTOP") != "": diff --git a/core/internal/matugen/matugen.go b/core/internal/matugen/matugen.go index bdf84673..245eb1b2 100644 --- a/core/internal/matugen/matugen.go +++ b/core/internal/matugen/matugen.go @@ -47,13 +47,14 @@ type TemplateDef struct { ConfigFile string Kind TemplateKind RunUnconditionally bool + RequiredEnv string } var templateRegistry = []TemplateDef{ {ID: "gtk", Kind: TemplateKindGTK, RunUnconditionally: true}, {ID: "niri", Commands: []string{"niri"}, ConfigFile: "niri.toml"}, {ID: "hyprland", Commands: []string{"Hyprland"}, ConfigFile: "hyprland.toml"}, - {ID: "mangowc", Commands: []string{"mango"}, ConfigFile: "mangowc.toml"}, + {ID: "mangowc", Commands: []string{"mango"}, ConfigFile: "mangowc.toml", RequiredEnv: "MANGO_INSTANCE_SIGNATURE"}, {ID: "qt5ct", Commands: []string{"qt5ct"}, ConfigFile: "qt5ct.toml"}, {ID: "qt6ct", Commands: []string{"qt6ct"}, ConfigFile: "qt6ct.toml"}, {ID: "firefox", Commands: []string{"firefox"}, ConfigFile: "firefox.toml"}, @@ -356,6 +357,9 @@ output_path = '%s' if opts.ShouldSkipTemplate(tmpl.ID) { continue } + if !templateSessionActive(tmpl) { + continue + } switch tmpl.Kind { case TemplateKindGTK: @@ -489,6 +493,18 @@ func appendTerminalConfig(opts *Options, cfgFile *os.File, tmpDir string, checkC cfgFile.WriteString("\n") } +func templateSessionActive(tmpl TemplateDef) bool { + if tmpl.RequiredEnv == "" { + return true + } + socket := os.Getenv(tmpl.RequiredEnv) + if socket == "" { + return false + } + _, err := os.Stat(socket) + return err == nil +} + func appExists(checker utils.AppChecker, checkCmd []string, checkFlatpaks []string) bool { // Both nil is treated as "skip check" / unconditionally run if checkCmd == nil && checkFlatpaks == nil { @@ -951,7 +967,7 @@ func CheckTemplates(checker utils.AppChecker) []TemplateCheck { case tmpl.Kind == TemplateKindEmacs: detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks) && utils.EmacsConfigDir() != "" default: - detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks) + detected = appExists(checker, tmpl.Commands, tmpl.Flatpaks) && templateSessionActive(tmpl) } checks = append(checks, TemplateCheck{ID: tmpl.ID, Detected: detected}) diff --git a/core/internal/matugen/matugen_test.go b/core/internal/matugen/matugen_test.go index 48880df2..a42638a9 100644 --- a/core/internal/matugen/matugen_test.go +++ b/core/internal/matugen/matugen_test.go @@ -441,3 +441,49 @@ func TestBuildMergedConfigColorsOnly(t *testing.T) { assert.NotContains(t, content, "[templates.gtk]") assert.False(t, strings.Contains(content, "output_path = 'CONFIG_DIR/"), "colors-only config should not emit app template outputs") } + +func TestBuildMergedConfigSkipsMangowcWithoutActiveSession(t *testing.T) { + t.Setenv("MANGO_INSTANCE_SIGNATURE", "") + + tempDir := t.TempDir() + shellDir := filepath.Join(tempDir, "shell") + configsDir := filepath.Join(shellDir, "matugen", "configs") + if err := os.MkdirAll(configsDir, 0o755); err != nil { + t.Fatalf("failed to create configs dir: %v", err) + } + + if err := os.WriteFile(filepath.Join(configsDir, "base.toml"), []byte("[config]\n"), 0o644); err != nil { + t.Fatalf("failed to write base config: %v", err) + } + mangowcConfig := "[templates.dmsmango]\ninput_path = 'in'\noutput_path = 'out'\n" + if err := os.WriteFile(filepath.Join(configsDir, "mangowc.toml"), []byte(mangowcConfig), 0o644); err != nil { + t.Fatalf("failed to write mangowc config: %v", err) + } + + cfgFile, err := os.CreateTemp(tempDir, "merged-*.toml") + if err != nil { + t.Fatalf("failed to create temp config: %v", err) + } + defer os.Remove(cfgFile.Name()) + defer cfgFile.Close() + + opts := &Options{ + ShellDir: shellDir, + ConfigDir: filepath.Join(tempDir, "config"), + StateDir: filepath.Join(tempDir, "state"), + SkipTemplates: "gtk,niri,hyprland,qt5ct,qt6ct,firefox,pywalfox,zenbrowser,vesktop,vencord,equibop,ghostty,kitty,foot,alacritty,wezterm,nvim,dgop,kcolorscheme,vscode,emacs,zed", + } + + if err := buildMergedConfig(opts, cfgFile, filepath.Join(tempDir, "templates")); err != nil { + t.Fatalf("buildMergedConfig failed: %v", err) + } + if err := cfgFile.Close(); err != nil { + t.Fatalf("failed to close merged config: %v", err) + } + + output, err := os.ReadFile(cfgFile.Name()) + if err != nil { + t.Fatalf("failed to read merged config: %v", err) + } + assert.NotContains(t, string(output), "[templates.dmsmango]") +} diff --git a/quickshell/Common/SettingsData.qml b/quickshell/Common/SettingsData.qml index 356ded1b..e7d97a2b 100644 --- a/quickshell/Common/SettingsData.qml +++ b/quickshell/Common/SettingsData.qml @@ -1372,7 +1372,14 @@ Singleton { } } + function cosmicIntegrationAvailable() { + const desktop = (Quickshell.env("XDG_CURRENT_DESKTOP") || "").toUpperCase(); + return desktop.includes("COSMIC"); + } + function updateCosmicIconTheme() { + if (!cosmicIntegrationAvailable()) + return; const resolved = resolveIconTheme(); let cosmicThemeName = (resolved === "System Default") ? systemDefaultIconTheme : resolved; if (!cosmicThemeName || cosmicThemeName === "System Default") { @@ -1403,6 +1410,8 @@ Singleton { } function updateCosmicThemeMode(isLightMode) { + if (!cosmicIntegrationAvailable()) + return; const isDark = isLightMode ? "false" : "true"; const script = `mkdir -p ${_configDir}/cosmic/com.system76.CosmicTheme.Mode/v1 printf '%s\\n' ${isDark} > ${_configDir}/cosmic/com.system76.CosmicTheme.Mode/v1/is_dark 2>/dev/null || true`; diff --git a/quickshell/Services/MangoService.qml b/quickshell/Services/MangoService.qml index 795ab00b..f8303df2 100644 --- a/quickshell/Services/MangoService.qml +++ b/quickshell/Services/MangoService.qml @@ -414,6 +414,8 @@ Singleton { } function reloadConfig(showToast, suppressWatch) { + if (!CompositorService.isMango || !root.available) + return; const shouldShowToast = showToast !== false; const shouldSuppressWatch = suppressWatch !== false; if (shouldSuppressWatch) diff --git a/quickshell/matugen/configs/mangowc.toml b/quickshell/matugen/configs/mangowc.toml index fd51da21..1bb41591 100644 --- a/quickshell/matugen/configs/mangowc.toml +++ b/quickshell/matugen/configs/mangowc.toml @@ -1,4 +1,4 @@ [templates.dmsmango] input_path = 'SHELL_DIR/matugen/templates/mango-colors.conf' output_path = 'CONFIG_DIR/mango/dms/colors.conf' -post_hook = 'sh -c "mmsg dispatch reload_config 2>&1 || true"' +post_hook = 'sh -c "[ -n \"$MANGO_INSTANCE_SIGNATURE\" ] && mmsg dispatch reload_config || true"'