Files
netbird/client/ui/tray_theme_linux_test.go
Zoltán Papp 179966b000 [client/ui] Detect KDE panel dark mode from kdeglobals Complementary colour
Split Linux panel-theme detection into two files and fix the KDE case
where the tray icon picked the wrong mono variant.

The freedesktop Settings portal's color-scheme reports the *global*
light/dark preference, but the KDE panel is painted from the
Complementary colour group, which can be dark even when the global
scheme is Light. The tray sits on the panel, so keying its black/white
mono icon off the portal value alone gave the wrong contrast on KDE.

Changes:
  - tray_theme_linux.go keeps the dark/light decision; on KDE it now
    reads the user's kdeglobals [Colors:Complementary] BackgroundNormal
    to determine the actual panel luminance, falling back to the portal
    color-scheme / GTK_THEME chain elsewhere.
  - tray_theme_watcher_linux.go (new) owns the live half: a private
    session-bus connection for the portal SettingChanged signal plus an
    fsnotify watch on kdeglobals, repainting the tray on a panel-theme
    flip.
  - tray_theme_linux_test.go (new) covers the kdeglobals Complementary
    parse against the KDE test-VM's real file layout.
2026-06-02 14:29:45 +02:00

87 lines
2.3 KiB
Go

//go:build linux && !(linux && 386)
package main
import (
"os"
"path/filepath"
"testing"
)
func TestReadKdeComplementaryBackground(t *testing.T) {
// Mirrors the KDE test VM's kdeglobals: Window light, Complementary dark.
// The tray sits on the panel, which Plasma paints from Complementary, so
// the panel is dark even though the global color-scheme is Light.
content := `[Colors:Window]
BackgroundNormal=239,240,241
[Colors:Complementary]
BackgroundAlternate=27,30,32
BackgroundNormal=42,46,50
[General]
ColorSchemeHash=0be804dba87e3512aeb4be3d78ed981f59f0f2f4
`
path := filepath.Join(t.TempDir(), "kdeglobals")
if err := os.WriteFile(path, []byte(content), 0o600); err != nil {
t.Fatal(err)
}
rgb, ok := readKdeComplementaryBackground(path)
if !ok {
t.Fatal("expected to find Complementary BackgroundNormal")
}
if rgb != [3]uint8{42, 46, 50} {
t.Fatalf("rgb = %v, want [42 46 50]", rgb)
}
if !isDarkRGB(rgb[0], rgb[1], rgb[2]) {
t.Fatal("panel colour 42,46,50 should be dark")
}
// The Window background (what color-scheme reflects) is light — the bug
// this fix addresses is picking the icon from that instead of the panel.
if isDarkRGB(239, 240, 241) {
t.Fatal("window colour 239,240,241 should be light")
}
}
func TestReadKdeComplementaryBackgroundMissingGroup(t *testing.T) {
path := filepath.Join(t.TempDir(), "kdeglobals")
if err := os.WriteFile(path, []byte("[Colors:Window]\nBackgroundNormal=1,2,3\n"), 0o600); err != nil {
t.Fatal(err)
}
if _, ok := readKdeComplementaryBackground(path); ok {
t.Fatal("expected not-ok when Complementary group is absent")
}
}
func TestParseRGB(t *testing.T) {
if _, ok := parseRGB("1,2"); ok {
t.Fatal("two components should fail")
}
if _, ok := parseRGB("300,0,0"); ok {
t.Fatal("out-of-range should fail")
}
if _, ok := parseRGB("a,b,c"); ok {
t.Fatal("non-numeric should fail")
}
rgb, ok := parseRGB(" 10 , 20 , 30 ")
if !ok || rgb != [3]uint8{10, 20, 30} {
t.Fatalf("parseRGB = %v ok=%v, want [10 20 30] true", rgb, ok)
}
}
func TestIsDarkRGB(t *testing.T) {
if !isDarkRGB(0, 0, 0) {
t.Fatal("black is dark")
}
if isDarkRGB(255, 255, 255) {
t.Fatal("white is light")
}
if !isDarkRGB(42, 46, 50) {
t.Fatal("Breeze panel grey is dark")
}
if isDarkRGB(239, 240, 241) {
t.Fatal("Breeze window grey is light")
}
}