fix: restore tray icon after Explorer restart
This commit is contained in:
@@ -70,9 +70,11 @@ var (
|
|||||||
procGetCursorPos = user32Tray.NewProc("GetCursorPos")
|
procGetCursorPos = user32Tray.NewProc("GetCursorPos")
|
||||||
procSetForeground = user32Tray.NewProc("SetForegroundWindow")
|
procSetForeground = user32Tray.NewProc("SetForegroundWindow")
|
||||||
procGetModuleHandle = user32Tray.NewProc("GetModuleHandleW")
|
procGetModuleHandle = user32Tray.NewProc("GetModuleHandleW")
|
||||||
|
procRegisterMessage = user32Tray.NewProc("RegisterWindowMessageW")
|
||||||
procShellNotify = shell32Tray.NewProc("Shell_NotifyIconW")
|
procShellNotify = shell32Tray.NewProc("Shell_NotifyIconW")
|
||||||
trayCallback = syscall.NewCallback(trayWindowProc)
|
trayCallback = syscall.NewCallback(trayWindowProc)
|
||||||
trayWindows sync.Map // hwnd -> *trayWindow
|
trayWindows sync.Map // hwnd -> *trayWindow
|
||||||
|
taskbarCreatedMessage uint32
|
||||||
)
|
)
|
||||||
|
|
||||||
type trayPoint struct{ X, Y int32 }
|
type trayPoint struct{ X, Y int32 }
|
||||||
@@ -212,7 +214,10 @@ func runTrayMessageLoop(output io.Writer, tooltip string, ready chan<- *trayWind
|
|||||||
window.icon = trayIconData{CbSize: uint32(unsafe.Sizeof(trayIconData{})), HWnd: hwnd, UID: trayIconID, UFlags: trayNIFMessage | trayNIFIcon | trayNIFTip, UCallbackMessage: trayMessage, HIcon: icon}
|
window.icon = trayIconData{CbSize: uint32(unsafe.Sizeof(trayIconData{})), HWnd: hwnd, UID: trayIconID, UFlags: trayNIFMessage | trayNIFIcon | trayNIFTip, UCallbackMessage: trayMessage, HIcon: icon}
|
||||||
copy(window.icon.Tip[:], winapi.StringToUTF16(tooltip))
|
copy(window.icon.Tip[:], winapi.StringToUTF16(tooltip))
|
||||||
trayWindows.Store(hwnd, window)
|
trayWindows.Store(hwnd, window)
|
||||||
if result, _, err := procShellNotify.Call(uintptr(trayNIMAdd), uintptr(unsafe.Pointer(&window.icon))); result == 0 {
|
messageName, _ := winapi.UTF16PtrFromString("TaskbarCreated")
|
||||||
|
registeredMessage, _, _ := procRegisterMessage.Call(uintptr(unsafe.Pointer(messageName)))
|
||||||
|
taskbarCreatedMessage = uint32(registeredMessage)
|
||||||
|
if err := window.addIcon(); err != nil {
|
||||||
trayWindows.Delete(hwnd)
|
trayWindows.Delete(hwnd)
|
||||||
_, _, _ = procDestroyWindow.Call(hwnd)
|
_, _, _ = procDestroyWindow.Call(hwnd)
|
||||||
done <- err
|
done <- err
|
||||||
@@ -263,10 +268,28 @@ func trayWindowProc(hwnd uintptr, message uint32, wParam, lParam uintptr) uintpt
|
|||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
if window != nil && taskbarCreatedMessage != 0 && message == taskbarCreatedMessage {
|
||||||
|
// Explorer may restart without destroying the tray window. Re-add the
|
||||||
|
// icon with the current bounded tooltip so the frontend recovers without
|
||||||
|
// restarting the service or tray process.
|
||||||
|
_ = window.addIcon()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
result, _, _ := procDefWindowProc.Call(hwnd, uintptr(message), wParam, lParam)
|
result, _, _ := procDefWindowProc.Call(hwnd, uintptr(message), wParam, lParam)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (window *trayWindow) addIcon() error {
|
||||||
|
window.icon.UFlags = trayNIFMessage | trayNIFIcon | trayNIFTip
|
||||||
|
if result, _, err := procShellNotify.Call(uintptr(trayNIMAdd), uintptr(unsafe.Pointer(&window.icon))); result == 0 {
|
||||||
|
if err == syscall.Errno(0) {
|
||||||
|
err = syscall.GetLastError()
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (window *trayWindow) removeIcon() {
|
func (window *trayWindow) removeIcon() {
|
||||||
window.closeOnce.Do(func() {
|
window.closeOnce.Do(func() {
|
||||||
window.icon.UFlags = 0
|
window.icon.UFlags = 0
|
||||||
@@ -400,10 +423,10 @@ func (window *trayWindow) setTooltip(value string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func openExactPath(path string) error {
|
func openExactPath(path string) error {
|
||||||
if path == "" || strings.TrimSpace(path) != path || !utf8.ValidString(path) {
|
if path == "" || strings.TrimSpace(path) != path || !utf8.ValidString(path) || !filepath.IsAbs(path) {
|
||||||
return errors.New("invalid path returned by service")
|
return errors.New("invalid path returned by service")
|
||||||
}
|
}
|
||||||
info, err := os.Stat(path)
|
info, err := os.Lstat(path)
|
||||||
if err != nil || !info.Mode().IsRegular() {
|
if err != nil || !info.Mode().IsRegular() {
|
||||||
return errors.New("service path is not a regular file")
|
return errors.New("service path is not a regular file")
|
||||||
}
|
}
|
||||||
@@ -412,7 +435,7 @@ func openExactPath(path string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
explorer := filepath.Join(windowsDir, "explorer.exe")
|
explorer := filepath.Join(windowsDir, "explorer.exe")
|
||||||
if info, err := os.Stat(explorer); err != nil || !info.Mode().IsRegular() {
|
if info, err := os.Lstat(explorer); err != nil || !info.Mode().IsRegular() {
|
||||||
return errors.New("Windows Explorer is unavailable")
|
return errors.New("Windows Explorer is unavailable")
|
||||||
}
|
}
|
||||||
return exec.Command(explorer, path).Start()
|
return exec.Command(explorer, path).Start()
|
||||||
|
|||||||
Reference in New Issue
Block a user