P5: per-platform transparent, size-appropriate window/tray icons

Give the window titlebar, taskbar, and tray a size-appropriate icon with a
transparent boundary on both Windows and Linux, instead of scaling one PNG to
every size.

Assets:
- Regenerate the PNGs and gosentry.ico with feathered color-to-alpha so the
  rounded-tile boundary is transparent; a binary white-key had left an opaque
  halo that read as a border on dark taskbars/trays.
- Rebuild gosentry.ico as multi-size (16 hand-tuned + 32/48/256 from big) and
  add a single-frame 16x16 gosentry-icon-16x16.ico for the Windows tray.
- assets.go: add IconSmall() and IconSmallICO().

Wiring:
- Windows window/taskbar: embed gosentry.ico under the GLFW_ICON resource and
  skip a.SetIcon so GLFW selects the right frame per size (hand-tuned 16 for the
  titlebar, a larger frame for the taskbar).
- Windows tray: SetSystemTrayIcon(IconSmallICO()), a 16x16 ICO frame.
- Linux window titlebar: a.SetIcon(IconSmall()) for a crisp ~16px _NET_WM_ICON;
  tray uses the big PNG since StatusNotifierItem renders larger.

Also bump Fyne 2.6.3 -> 2.7.4 (systray 1.11.0 -> 1.12.1) and document the full
cross-platform icon strategy in assets.go, gosentry.rc, run.go, and tray.go.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
mixeme
2026-06-23 22:09:04 +03:00
parent 6136bb645b
commit f533739d6e
10 changed files with 146 additions and 44 deletions
+15 -5
View File
@@ -1,6 +1,7 @@
package ui
import (
"runtime"
"time"
"gitea.mixdep.ru/mix/gosentry/assets"
@@ -30,7 +31,20 @@ func Run(startInTray bool) {
// A stable app ID lets Fyne persist desktop preferences consistently across
// launches and gives tray/window integration a predictable identity.
a := fyneapp.NewWithID(appID)
a.SetIcon(loadAppIcon())
// On Windows the multi-resolution gosentry.ico (embedded under the GLFW_ICON
// resource name) drives the window: GLFW picks the hand-tuned 16x16 for the
// titlebar and the large artwork for the bigger taskbar icon — size-appropriate
// in a way a single Fyne SetIcon resource cannot be, since one PNG would be
// scaled to both sizes.
//
// Other platforms have no PE icon. Fyne's single SetIcon resource feeds
// _NET_WM_ICON, which the window manager renders small (~16px) in the titlebar,
// so use the hand-tuned small icon there to keep it crisp. The larger
// dock/launcher icon comes from the .desktop entry installed by
// InstallDesktopIcon, which uses the big artwork.
if runtime.GOOS != "windows" {
a.SetIcon(assets.IconSmall())
}
w := a.NewWindow("GoSentry " + app.Version)
configureSystemTray(a, w)
@@ -54,7 +68,3 @@ func Run(startInTray bool) {
recordStartup(time.Since(started), true)
a.Run()
}
func loadAppIcon() fyne.Resource {
return assets.Icon()
}