package screenshot import ( "encoding/json" "os" "os/exec" "path/filepath" "strings" ) type ThemeColors struct { Background string `json:"surface"` OnSurface string `json:"on_surface"` Primary string `json:"primary"` } type ColorScheme struct { Dark ThemeColors `json:"dark"` Light ThemeColors `json:"light"` } type ColorsFile struct { Colors ColorScheme `json:"colors"` } var cachedStyle *OverlayStyle func LoadOverlayStyle() OverlayStyle { if cachedStyle != nil { return *cachedStyle } style := DefaultOverlayStyle colors := loadColorsFile() if colors == nil { cachedStyle = &style return style } theme := &colors.Dark if isLightMode() { theme = &colors.Light } if bg, ok := parseHexColor(theme.Background); ok { style.BackgroundR, style.BackgroundG, style.BackgroundB = bg[0], bg[1], bg[2] } if text, ok := parseHexColor(theme.OnSurface); ok { style.TextR, style.TextG, style.TextB = text[0], text[1], text[2] } if accent, ok := parseHexColor(theme.Primary); ok { style.AccentR, style.AccentG, style.AccentB = accent[0], accent[1], accent[2] } cachedStyle = &style return style } func loadColorsFile() *ColorScheme { path := getColorsFilePath() data, err := os.ReadFile(path) if err != nil { return nil } var file ColorsFile if err := json.Unmarshal(data, &file); err != nil { return nil } return &file.Colors } func getColorsFilePath() string { cacheDir := os.Getenv("XDG_CACHE_HOME") if cacheDir == "" { home := os.Getenv("HOME") if home == "" { return "" } cacheDir = filepath.Join(home, ".cache") } return filepath.Join(cacheDir, "DankMaterialShell", "dms-colors.json") } func isLightMode() bool { out, err := exec.Command("gsettings", "get", "org.gnome.desktop.interface", "color-scheme").Output() if err != nil { return false } scheme := strings.TrimSpace(string(out)) switch scheme { case "'prefer-light'", "'default'": return true } return false } func parseHexColor(hex string) ([3]uint8, bool) { hex = strings.TrimPrefix(hex, "#") if len(hex) != 6 { return [3]uint8{}, false } var r, g, b uint8 for i, ptr := range []*uint8{&r, &g, &b} { val := 0 for j := 0; j < 2; j++ { c := hex[i*2+j] val *= 16 switch { case c >= '0' && c <= '9': val += int(c - '0') case c >= 'a' && c <= 'f': val += int(c - 'a' + 10) case c >= 'A' && c <= 'F': val += int(c - 'A' + 10) default: return [3]uint8{}, false } } *ptr = uint8(val) } return [3]uint8{r, g, b}, true }