diff --git a/pkg/systray/wails.go b/pkg/systray/wails.go index 6cbb5bf..2ebc5e3 100644 --- a/pkg/systray/wails.go +++ b/pkg/systray/wails.go @@ -15,7 +15,7 @@ func NewWailsPlatform(app *application.App) *WailsPlatform { } func (wp *WailsPlatform) NewTray() PlatformTray { - return &wailsTray{tray: wp.app.SystemTray.New(), app: wp.app} + return &wailsTray{tray: wp.app.SystemTray.New()} } func (wp *WailsPlatform) NewMenu() PlatformMenu { @@ -24,7 +24,6 @@ func (wp *WailsPlatform) NewMenu() PlatformMenu { type wailsTray struct { tray *application.SystemTray - app *application.App } func (wt *wailsTray) SetIcon(data []byte) { wt.tray.SetIcon(data) } @@ -39,8 +38,19 @@ func (wt *wailsTray) SetMenu(menu PlatformMenu) { } func (wt *wailsTray) AttachWindow(w WindowHandle) { - // Wails systray AttachWindow expects an application.Window interface. - // The caller must pass an appropriate wrapper. + if wt.tray == nil { + return + } + window, ok := w.(interface { + Show() + Hide() + Focus() + IsVisible() bool + }) + if !ok { + return + } + wt.tray.AttachWindow(window) } // wailsTrayMenu wraps *application.Menu for the PlatformMenu interface. diff --git a/pkg/systray/wails_test.go b/pkg/systray/wails_test.go new file mode 100644 index 0000000..d7934fc --- /dev/null +++ b/pkg/systray/wails_test.go @@ -0,0 +1,34 @@ +package systray + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/wailsapp/wails/v3/pkg/application" +) + +func TestWailsTray_AttachWindow_Good(t *testing.T) { + app := application.NewApp() + platform := NewWailsPlatform(app) + + tray, ok := platform.NewTray().(*wailsTray) + require.True(t, ok) + + window := app.Window.NewWithOptions(application.WebviewWindowOptions{ + Name: "panel", + Title: "Panel", + Hidden: true, + }) + + tray.AttachWindow(window) + + assert.False(t, window.IsVisible()) + + tray.tray.Click() + assert.True(t, window.IsVisible()) + assert.True(t, window.IsFocused()) + + tray.tray.Click() + assert.False(t, window.IsVisible()) +} diff --git a/stubs/wails/v3/pkg/application/application.go b/stubs/wails/v3/pkg/application/application.go index 54c7c14..a58c74a 100644 --- a/stubs/wails/v3/pkg/application/application.go +++ b/stubs/wails/v3/pkg/application/application.go @@ -258,11 +258,18 @@ func (mi *MenuItem) OnClick(fn func(ctx *Context)) *MenuItem { // SystemTray models a tray icon. type SystemTray struct { - icon []byte - templateIcon []byte - tooltip string - label string - menu *Menu + icon []byte + templateIcon []byte + tooltip string + label string + menu *Menu + attachedWindow interface { + Show() + Hide() + Focus() + IsVisible() bool + } + onClick func() } func (st *SystemTray) SetIcon(icon []byte) *SystemTray { @@ -288,9 +295,39 @@ func (st *SystemTray) SetMenu(menu *Menu) *SystemTray { return st } -func (st *SystemTray) Show() {} -func (st *SystemTray) Hide() {} -func (st *SystemTray) OnClick(callback func()) *SystemTray { return st } +func (st *SystemTray) Show() {} +func (st *SystemTray) Hide() {} +func (st *SystemTray) OnClick(callback func()) *SystemTray { + st.onClick = callback + return st +} + +func (st *SystemTray) AttachWindow(window interface { + Show() + Hide() + Focus() + IsVisible() bool +}) *SystemTray { + st.attachedWindow = window + st.OnClick(func() { + if st.attachedWindow == nil { + return + } + if st.attachedWindow.IsVisible() { + st.attachedWindow.Hide() + return + } + st.attachedWindow.Show() + st.attachedWindow.Focus() + }) + return st +} + +func (st *SystemTray) Click() { + if st.onClick != nil { + st.onClick() + } +} // SystemTrayManager creates trays. type SystemTrayManager struct {