Release 3.8.2.7: Windows taskbar/tray sea-wave icon when connected.
ci / test (macos-latest) (push) Waiting to run
ci / test (ubuntu-latest) (push) Waiting to run
ci / test (windows-latest) (push) Waiting to run

Match macOS Dock behavior using the same idle/connected glyph assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
M4
2026-08-01 16:45:55 +03:00
co-authored by Cursor
parent 5d7c96f7fc
commit fed1ace33e
20 changed files with 395 additions and 24 deletions
+53 -2
View File
@@ -4,8 +4,11 @@ package trayhost
import (
"runtime"
"sync"
"unsafe"
"vpnclient/internal/dockicon"
"golang.org/x/sys/windows"
)
@@ -90,6 +93,12 @@ type msg struct {
Pt point
}
var (
trayMu sync.Mutex
trayNID *notifyIconData
trayLastUp *bool
)
func start(appName string, h Hooks) bool {
if h.Quit == nil {
return false
@@ -102,6 +111,35 @@ func start(appName string, h Hooks) bool {
return true
}
// SetConnectedIcon updates the tray glyph (sea-wave N when connected).
func SetConnectedIcon(connected bool) {
trayMu.Lock()
nid := trayNID
if trayLastUp != nil && *trayLastUp == connected {
trayMu.Unlock()
return
}
v := connected
trayLastUp = &v
trayMu.Unlock()
if nid == nil {
return
}
icon := dockicon.StatusIcon(connected)
if icon == 0 {
return
}
trayMu.Lock()
if trayNID == nil {
trayMu.Unlock()
return
}
trayNID.HIcon = icon
trayNID.UFlags = nifMessage | nifIcon | nifTip
procShellNotify.Call(nimModify, uintptr(unsafe.Pointer(trayNID)))
trayMu.Unlock()
}
func runTray(appName string, h Hooks) {
className, _ := windows.UTF16PtrFromString("NavisTrayClass")
title, _ := windows.UTF16PtrFromString(appName)
@@ -155,17 +193,27 @@ func runTray(appName string, h Hooks) {
return
}
icon, _, _ := procLoadIcon.Call(0, uintptr(idiApplication))
icon := dockicon.StatusIcon(false)
if icon == 0 {
h, _, _ := procLoadIcon.Call(0, uintptr(idiApplication))
icon = windows.Handle(h)
}
var nid notifyIconData
nid.CbSize = uint32(unsafe.Sizeof(nid))
nid.Hwnd = windows.Handle(hwnd)
nid.UID = 1
nid.UFlags = nifMessage | nifIcon | nifTip
nid.UCallbackMessage = wmTray
nid.HIcon = windows.Handle(icon)
nid.HIcon = icon
tip, _ := windows.UTF16FromString(appName)
copy(nid.SzTip[:], tip)
procShellNotify.Call(nimAdd, uintptr(unsafe.Pointer(&nid)))
trayMu.Lock()
trayNID = &nid
trayMu.Unlock()
if h.IsUp != nil {
SetConnectedIcon(h.IsUp())
}
var m msg
for {
@@ -176,6 +224,9 @@ func runTray(appName string, h Hooks) {
procTranslate.Call(uintptr(unsafe.Pointer(&m)))
procDispatch.Call(uintptr(unsafe.Pointer(&m)))
}
trayMu.Lock()
trayNID = nil
trayMu.Unlock()
procShellNotify.Call(nimDelete, uintptr(unsafe.Pointer(&nid)))
}