diff options
Diffstat (limited to 'internal/notify/icons.go')
| -rw-r--r-- | internal/notify/icons.go | 96 |
1 files changed, 82 insertions, 14 deletions
diff --git a/internal/notify/icons.go b/internal/notify/icons.go index b874581..d68c171 100644 --- a/internal/notify/icons.go +++ b/internal/notify/icons.go @@ -95,22 +95,12 @@ func lookupThemeIcon(name, theme string) string { return "" } -// findInTheme prefers scalable then the largest raster under apps/. +// findInTheme prefers scalable, then the largest raster. It searches both the +// KDE/Papirus apps/<size> layout and the freedesktop <size>/apps layout. func findInTheme(base, name string) string { - sizes := []string{"scalable"} - matches, _ := filepath.Glob(filepath.Join(base, "apps", "[0-9]*")) - for _, m := range matches { - sizes = append(sizes, filepath.Base(m)) - } - numeric := sizes[1:] - sort.Slice(numeric, func(i, j int) bool { - a, _ := strconv.Atoi(strings.TrimSuffix(numeric[i], "@2x")) - b, _ := strconv.Atoi(strings.TrimSuffix(numeric[j], "@2x")) - return a > b - }) - for _, size := range sizes { + for _, dir := range themeSizeDirs(base) { for _, ext := range []string{"svg", "png", "xpm"} { - p := filepath.Join(base, "apps", size, name+"."+ext) + p := filepath.Join(dir, name+"."+ext) if fileExists(p) { return p } @@ -119,6 +109,84 @@ func findInTheme(base, name string) string { return "" } +// sizeDir is one candidate icon directory inside a theme. +type sizeDir struct { + path string + scalable bool + size int + name string +} + +// themeSizeDirs lists a theme's candidate directories, scalable first, then +// rasters by effective pixel size descending, name as a deterministic +// tie-break. Both icon layouts are covered. +func themeSizeDirs(base string) []string { + var found []sizeDir + add := func(name, path string) { + if name == "scalable" { + found = append(found, sizeDir{path: path, scalable: true, name: name}) + return + } + if n, ok := pixelSize(name); ok { + found = append(found, sizeDir{path: path, size: n, name: name}) + } + } + // KDE/Papirus: apps/<size>/ + if entries, err := os.ReadDir(filepath.Join(base, "apps")); err == nil { + for _, e := range entries { + if e.IsDir() { + add(e.Name(), filepath.Join(base, "apps", e.Name())) + } + } + } + // freedesktop: <size>/apps/ + if entries, err := os.ReadDir(base); err == nil { + for _, e := range entries { + if !e.IsDir() { + continue + } + apps := filepath.Join(base, e.Name(), "apps") + if info, err := os.Stat(apps); err == nil && info.IsDir() { + add(e.Name(), apps) + } + } + } + sort.Slice(found, func(i, j int) bool { + a, b := found[i], found[j] + if a.scalable != b.scalable { + return a.scalable + } + if a.size != b.size { + return a.size > b.size + } + return a.name < b.name + }) + dirs := make([]string, len(found)) + for i, d := range found { + dirs[i] = d.path + } + return dirs +} + +// pixelSize turns a size directory name into its effective pixel size. "48" +// and "48x48" styles are recognised, and a trailing @2x doubles the size. +func pixelSize(name string) (int, bool) { + s := name + mult := 1 + if strings.HasSuffix(s, "@2x") { + s = strings.TrimSuffix(s, "@2x") + mult = 2 + } + if i := strings.IndexByte(s, 'x'); i >= 0 { + s = s[:i] + } + n, err := strconv.Atoi(s) + if err != nil { + return 0, false + } + return n * mult, true +} + func inheritsOf(base string) string { v := iniValue(filepath.Join(base, "index.theme"), "Inherits") if i := strings.IndexByte(v, ','); i >= 0 { |
