diff --git a/v2/internal/platform/systray.go b/v2/internal/platform/systray.go index 0a8f69ca2..9625f1a7e 100644 --- a/v2/internal/platform/systray.go +++ b/v2/internal/platform/systray.go @@ -17,7 +17,7 @@ type SysTray interface { Close() SetMenu(menu *menu.Menu) error SetIcons(lightModeIcon, darkModeIcon *options.SystemTrayIcon) error - Update() + Update() error } func NewSysTray() SysTray { diff --git a/v2/internal/platform/systray/windows.go b/v2/internal/platform/systray/windows.go index 20e386a72..0273a1097 100644 --- a/v2/internal/platform/systray/windows.go +++ b/v2/internal/platform/systray/windows.go @@ -49,14 +49,13 @@ func (p *Systray) Close() { } } -func (p *Systray) Update() { +func (p *Systray) Update() error { // Delete old menu if p.menu != nil { p.menu.Destroy() } - p.menu.Update() - + return p.menu.Update() } // SetTitle is unused on Windows @@ -123,15 +122,13 @@ func New() (*Systray, error) { } nid.CbSize = uint32(unsafe.Sizeof(nid)) - ret := win32.ShellNotifyIcon(win32.NIM_ADD, &nid) - if ret == 0 { + if !win32.ShellNotifyIcon(win32.NIM_ADD, &nid) { return nil, errors.New("shell notify create failed") } nid.UVersion = win32.NOTIFYICON_VERSION - ret = win32.ShellNotifyIcon(win32.NIM_SETVERSION, &nid) - if ret == 0 { + if !win32.ShellNotifyIcon(win32.NIM_SETVERSION, &nid) { return nil, errors.New("shell notify version failed") } @@ -153,8 +150,8 @@ func (p *Systray) SetMenu(popupMenu *menu.Menu) (err error) { func (p *Systray) Stop() error { nid := p.newNotifyIconData() - ret := win32.ShellNotifyIcon(win32.NIM_DELETE, &nid) - if ret == 0 { + win32.PostQuitMessage(0) + if !win32.ShellNotifyIcon(win32.NIM_DELETE, &nid) { return errors.New("shell notify delete failed") } return nil @@ -173,8 +170,7 @@ func (p *Systray) SetTooltip(tooltip string) error { nid.UFlags = win32.NIF_TIP copy(nid.SzTip[:], win32.MustUTF16FromString(tooltip)) - ret := win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) - if ret == 0 { + if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) { return errors.New("shell notify tooltip failed") } return nil @@ -192,8 +188,7 @@ func (p *Systray) ShowMessage(title, msg string, bigIcon bool) error { copy(nid.SzInfoTitle[:], win32.MustUTF16FromString(title)) copy(nid.SzInfo[:], win32.MustUTF16FromString(msg)) - ret := win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) - if ret == 0 { + if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) { return errors.New("shell notify tooltip failed") } return nil @@ -224,8 +219,7 @@ func (p *Systray) setVisible(visible bool) error { nid.DwState = win32.NIS_HIDDEN } - ret := win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) - if ret == 0 { + if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) { return errors.New("shell notify tooltip failed") } return nil @@ -261,8 +255,7 @@ func (p *Systray) setIcon(hicon win32.HICON) error { nid.HIcon = hicon } - ret := win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) - if ret == 0 { + if !win32.ShellNotifyIcon(win32.NIM_MODIFY, &nid) { return errors.New("shell notify icon failed") } return nil diff --git a/v2/internal/platform/win32/consts.go b/v2/internal/platform/win32/consts.go index 0490aee3d..b577bd011 100644 --- a/v2/internal/platform/win32/consts.go +++ b/v2/internal/platform/win32/consts.go @@ -26,6 +26,7 @@ var ( procIsDialogMessage = moduser32.NewProc("IsDialogMessageW") procTranslateMessage = moduser32.NewProc("TranslateMessage") procDispatchMessage = moduser32.NewProc("DispatchMessageW") + procPostQuitMessage = moduser32.NewProc("PostQuitMessage") modshell32 = syscall.NewLazyDLL("shell32.dll") procShellNotifyIcon = modshell32.NewProc("Shell_NotifyIconW") @@ -135,9 +136,9 @@ func PostMessage(hwnd HWND, msg uint32, wParam, lParam uintptr) uintptr { return ret } -func ShellNotifyIcon(cmd uintptr, nid *NOTIFYICONDATA) uintptr { +func ShellNotifyIcon(cmd uintptr, nid *NOTIFYICONDATA) bool { ret, _, _ := procShellNotifyIcon.Call(cmd, uintptr(unsafe.Pointer(nid))) - return ret + return ret == 1 } func IsDialogMessage(hwnd HWND, msg *MSG) uintptr { @@ -154,3 +155,7 @@ func DispatchMessage(msg *MSG) uintptr { ret, _, _ := procDispatchMessage.Call(uintptr(unsafe.Pointer(msg))) return ret } + +func PostQuitMessage(exitCode int32) { + procPostQuitMessage.Call(uintptr(exitCode)) +} diff --git a/v2/pkg/application/application.go b/v2/pkg/application/application.go index 512de94c5..03d98ebd7 100644 --- a/v2/pkg/application/application.go +++ b/v2/pkg/application/application.go @@ -6,6 +6,7 @@ import ( "github.com/wailsapp/wails/v2/internal/signal" "github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/options" + "sync" ) // Application is the main Wails application @@ -18,6 +19,8 @@ type Application struct { // running flag running bool + + shutdown sync.Once } // NewWithOptions creates a new Application with the given options @@ -81,10 +84,12 @@ func (a *Application) Run() error { // Quit will shut down the application func (a *Application) Quit() { - for _, systray := range a.systemTrays { - systray.Close() - } - a.application.Shutdown() + a.shutdown.Do(func() { + for _, systray := range a.systemTrays { + systray.Close() + } + a.application.Shutdown() + }) } // Bind the given struct to the application diff --git a/v2/pkg/application/systray.go b/v2/pkg/application/systray.go index 4e0154e39..ba52d097c 100644 --- a/v2/pkg/application/systray.go +++ b/v2/pkg/application/systray.go @@ -59,6 +59,7 @@ func (t *SystemTray) Run() error { func (t *SystemTray) Close() { if t.impl != nil { t.impl.Close() + t.impl = nil } } @@ -70,8 +71,9 @@ func (t *SystemTray) SetMenu(items *menu.Menu) { } } -func (t *SystemTray) Update() { +func (t *SystemTray) Update() error { if t.impl != nil { - t.impl.Update() + return t.impl.Update() } + return nil }