From 16b872352d23a66b612f27cf753a102d24819d6f Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 22 Dec 2020 18:08:38 +1100 Subject: [PATCH] Support Text label tray --- v2/internal/app/desktop.go | 2 +- v2/internal/ffenestri/ffenestri.h | 1 + v2/internal/ffenestri/ffenestri_client.go | 3 ++ v2/internal/ffenestri/ffenestri_darwin.c | 32 ++++++++--- v2/internal/ffenestri/ffenestri_darwin.go | 6 +-- v2/internal/ffenestri/ffenestri_darwin.h | 2 +- .../messagedispatcher/dispatchclient.go | 1 + .../messagedispatcher/messagedispatcher.go | 15 ++++++ v2/internal/runtime/runtime.go | 2 +- v2/internal/runtime/tray.go | 13 +++-- v2/internal/subsystem/runtime.go | 2 +- v2/internal/subsystem/tray.go | 16 ++++-- v2/pkg/menu/trayoptions.go | 14 +++++ v2/pkg/options/mac/mac.go | 2 +- v2/pkg/options/options.go | 6 +-- .../src/pages/Window/Window/Window.svelte | 6 +-- v2/test/kitchensink/main.go | 8 ++- v2/test/kitchensink/tray.go | 53 +++++++++++++------ 18 files changed, 135 insertions(+), 49 deletions(-) create mode 100644 v2/pkg/menu/trayoptions.go diff --git a/v2/internal/app/desktop.go b/v2/internal/app/desktop.go index 3548fb3d4..3f89c36da 100644 --- a/v2/internal/app/desktop.go +++ b/v2/internal/app/desktop.go @@ -94,7 +94,7 @@ func (a *App) Run() error { // Start the runtime applicationMenu := options.GetApplicationMenu(a.options) - trayMenu := options.GetTrayMenu(a.options) + trayMenu := options.GetTray(a.options) contextMenus := options.GetContextMenus(a.options) runtimesubsystem, err := subsystem.NewRuntime(a.servicebus, a.logger, applicationMenu, trayMenu, contextMenus) diff --git a/v2/internal/ffenestri/ffenestri.h b/v2/internal/ffenestri/ffenestri.h index 66c5e2d40..7aa1b76cb 100644 --- a/v2/internal/ffenestri/ffenestri.h +++ b/v2/internal/ffenestri/ffenestri.h @@ -35,5 +35,6 @@ extern void DarkModeEnabled(void *appPointer, char *callbackID); extern void UpdateMenu(void *app, char *menuAsJSON); extern void UpdateTray(void *app, char *menuAsJSON); extern void UpdateContextMenus(void *app, char *contextMenusAsJSON); +extern void UpdateTrayLabel(void *app, const char *label); #endif diff --git a/v2/internal/ffenestri/ffenestri_client.go b/v2/internal/ffenestri/ffenestri_client.go index 41089e561..d1be11151 100644 --- a/v2/internal/ffenestri/ffenestri_client.go +++ b/v2/internal/ffenestri/ffenestri_client.go @@ -188,6 +188,9 @@ func (c *Client) UpdateTray(menu *menu.Menu) { } C.UpdateTray(c.app.app, c.app.string2CString(string(trayMenuJSON))) } +func (c *Client) UpdateTrayLabel(label string) { + C.UpdateTrayLabel(c.app.app, c.app.string2CString(label)) +} func (c *Client) UpdateContextMenus(contextMenus *menu.ContextMenus) { diff --git a/v2/internal/ffenestri/ffenestri_darwin.c b/v2/internal/ffenestri/ffenestri_darwin.c index 38fd3fd6a..3dbe7c425 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.c +++ b/v2/internal/ffenestri/ffenestri_darwin.c @@ -213,6 +213,8 @@ struct Application { // Tray const char *trayMenuAsJSON; + const char *trayType; + const char *trayLabel; JsonNode *processedTrayMenu; id statusItem; @@ -794,6 +796,8 @@ void* NewApplication(const char *title, int width, int height, int resizable, in // Tray result->trayMenuAsJSON = NULL; + result->trayType = NULL; + result->trayLabel = NULL; result->processedTrayMenu = NULL; result->statusItem = NULL; @@ -1302,8 +1306,10 @@ void SetMenu(struct Application *app, const char *menuAsJSON) { } // SetTray sets the initial tray menu for the application -void SetTray(struct Application *app, const char *trayMenuAsJSON) { +void SetTray(struct Application *app, const char *trayMenuAsJSON, const char *trayType, const char *trayLabel) { app->trayMenuAsJSON = trayMenuAsJSON; + app->trayType = trayType; + app->trayLabel = trayLabel; } // SetContextMenus sets the context menu map for this application @@ -2217,6 +2223,11 @@ void parseContextMenus(struct Application *app) { // dumpContextMenus(app); } +void UpdateTrayLabel(struct Application *app, const char *label) { + id statusBarButton = msg(app->statusItem, s("button")); + msg(statusBarButton, s("setTitle:"), str(label)); +} + void parseTrayData(struct Application *app) { // Allocate the hashmaps we need @@ -2235,13 +2246,20 @@ void parseTrayData(struct Application *app) { msg(statusItem, s("retain")); id statusBarButton = msg(statusItem, s("button")); - // If we have a tray icon - if ( trayIconLength > 0 ) { - id imageData = msg(c("NSData"), s("dataWithBytes:length:"), trayIcon, trayIconLength); - id trayImage = ALLOC("NSImage"); - msg(trayImage, s("initWithData:"), imageData); - msg(statusBarButton, s("setImage:"), trayImage); + if( STREQ(app->trayType, "icon") ) { + // If we have a tray icon + if ( trayIconLength > 0 ) { + id imageData = msg(c("NSData"), s("dataWithBytes:length:"), trayIcon, trayIconLength); + id trayImage = ALLOC("NSImage"); + msg(trayImage, s("initWithData:"), imageData); + msg(statusBarButton, s("setImage:"), trayImage); + } } + if( STREQ(app->trayType, "label") ) { + // If we have a tray icon + msg(statusBarButton, s("setTitle:"), str(app->trayLabel)); + } + } // Parse the processed menu json diff --git a/v2/internal/ffenestri/ffenestri_darwin.go b/v2/internal/ffenestri/ffenestri_darwin.go index 3d9043d73..8d4a7d6e0 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.go +++ b/v2/internal/ffenestri/ffenestri_darwin.go @@ -83,7 +83,7 @@ func (a *Application) processPlatformSettings() error { } // Process tray - tray := options.GetTrayMenu(a.config) + tray := options.GetTray(a.config) if tray != nil { /* @@ -94,12 +94,12 @@ func (a *Application) processPlatformSettings() error { a list of all members of the group and the number of members in the group (this last one is for optimisation at the C layer). */ - processedMenu := NewProcessedMenu(tray) + processedMenu := NewProcessedMenu(tray.Menu) trayMenuJSON, err := json.Marshal(processedMenu) if err != nil { return err } - C.SetTray(a.app, a.string2CString(string(trayMenuJSON))) + C.SetTray(a.app, a.string2CString(string(trayMenuJSON)), a.string2CString(string(tray.Type)), a.string2CString(tray.Label)) } // Process context menus diff --git a/v2/internal/ffenestri/ffenestri_darwin.h b/v2/internal/ffenestri/ffenestri_darwin.h index bf29efbde..3ca846044 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.h +++ b/v2/internal/ffenestri/ffenestri_darwin.h @@ -13,7 +13,7 @@ extern void SetAppearance(void *, const char *); extern void WebviewIsTransparent(void *); extern void WindowBackgroundIsTranslucent(void *); extern void SetMenu(void *, const char *); -extern void SetTray(void *, const char *); +extern void SetTray(void *, const char *, const char *, const char *); extern void SetContextMenus(void *, const char *); #endif \ No newline at end of file diff --git a/v2/internal/messagedispatcher/dispatchclient.go b/v2/internal/messagedispatcher/dispatchclient.go index f5602b674..cf822fce3 100644 --- a/v2/internal/messagedispatcher/dispatchclient.go +++ b/v2/internal/messagedispatcher/dispatchclient.go @@ -33,6 +33,7 @@ type Client interface { DarkModeEnabled(callbackID string) UpdateMenu(menu *menu.Menu) UpdateTray(menu *menu.Menu) + UpdateTrayLabel(label string) UpdateContextMenus(contextMenus *menu.ContextMenus) } diff --git a/v2/internal/messagedispatcher/messagedispatcher.go b/v2/internal/messagedispatcher/messagedispatcher.go index cad34d55e..fb19a7c80 100644 --- a/v2/internal/messagedispatcher/messagedispatcher.go +++ b/v2/internal/messagedispatcher/messagedispatcher.go @@ -508,6 +508,21 @@ func (d *Dispatcher) processTrayMessage(result *servicebus.Message) { client.frontend.UpdateTray(updatedMenu) } + case "setlabel": + + updatedLabel, ok := result.Data().(string) + if !ok { + d.logger.Error("Invalid data for 'trayfrontend:setlabel' : %#v", + result.Data()) + return + } + + // TODO: Work out what we mean in a multi window environment... + // For now we will just pick the first one + for _, client := range d.clients { + client.frontend.UpdateTrayLabel(updatedLabel) + } + default: d.logger.Error("Unknown menufrontend command: %s", command) } diff --git a/v2/internal/runtime/runtime.go b/v2/internal/runtime/runtime.go index 30a4d7dde..4452a761c 100644 --- a/v2/internal/runtime/runtime.go +++ b/v2/internal/runtime/runtime.go @@ -21,7 +21,7 @@ type Runtime struct { } // New creates a new runtime -func New(serviceBus *servicebus.ServiceBus, menu *menu.Menu, trayMenu *menu.Menu, contextMenus *menu.ContextMenus) *Runtime { +func New(serviceBus *servicebus.ServiceBus, menu *menu.Menu, trayMenu *menu.TrayOptions, contextMenus *menu.ContextMenus) *Runtime { result := &Runtime{ Browser: newBrowser(), Events: newEvents(serviceBus), diff --git a/v2/internal/runtime/tray.go b/v2/internal/runtime/tray.go index 1695bb1a0..e8420ed79 100644 --- a/v2/internal/runtime/tray.go +++ b/v2/internal/runtime/tray.go @@ -12,15 +12,16 @@ type Tray interface { Update() GetByID(menuID string) *menu.MenuItem RemoveByID(id string) bool + SetLabel(label string) } type trayRuntime struct { bus *servicebus.ServiceBus - trayMenu *menu.Menu + trayMenu *menu.TrayOptions } // newTray creates a new Menu struct -func newTray(bus *servicebus.ServiceBus, menu *menu.Menu) Tray { +func newTray(bus *servicebus.ServiceBus, menu *menu.TrayOptions) Tray { return &trayRuntime{ bus: bus, trayMenu: menu, @@ -39,10 +40,14 @@ func (t *trayRuntime) Update() { t.bus.Publish("tray:update", t.trayMenu) } +func (t *trayRuntime) SetLabel(label string) { + t.bus.Publish("tray:setlabel", label) +} + func (t *trayRuntime) GetByID(menuID string) *menu.MenuItem { - return t.trayMenu.GetByID(menuID) + return t.trayMenu.Menu.GetByID(menuID) } func (t *trayRuntime) RemoveByID(id string) bool { - return t.trayMenu.RemoveByID(id) + return t.trayMenu.Menu.RemoveByID(id) } diff --git a/v2/internal/subsystem/runtime.go b/v2/internal/subsystem/runtime.go index c24603faa..257db3919 100644 --- a/v2/internal/subsystem/runtime.go +++ b/v2/internal/subsystem/runtime.go @@ -24,7 +24,7 @@ type Runtime struct { } // NewRuntime creates a new runtime subsystem -func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, menu *menu.Menu, trayMenu *menu.Menu, contextMenus *menu.ContextMenus) (*Runtime, error) { +func NewRuntime(bus *servicebus.ServiceBus, logger *logger.Logger, menu *menu.Menu, trayMenu *menu.TrayOptions, contextMenus *menu.ContextMenus) (*Runtime, error) { // Register quit channel quitChannel, err := bus.Subscribe("quit") diff --git a/v2/internal/subsystem/tray.go b/v2/internal/subsystem/tray.go index cdccbadb4..45c9b9681 100644 --- a/v2/internal/subsystem/tray.go +++ b/v2/internal/subsystem/tray.go @@ -26,14 +26,14 @@ type Tray struct { logger logger.CustomLogger // The tray menu - trayMenu *menu.Menu + trayMenu *menu.TrayOptions // Service Bus bus *servicebus.ServiceBus } // NewTray creates a new menu subsystem -func NewTray(trayMenu *menu.Menu, bus *servicebus.ServiceBus, +func NewTray(trayMenu *menu.TrayOptions, bus *servicebus.ServiceBus, logger *logger.Logger) (*Tray, error) { // Register quit channel @@ -59,7 +59,7 @@ func NewTray(trayMenu *menu.Menu, bus *servicebus.ServiceBus, } // Build up list of item/id pairs - result.processMenu(trayMenu) + result.processMenu(trayMenu.Menu) return result, nil } @@ -118,6 +118,14 @@ func (t *Tray) Start() error { // Notify frontend of menu change t.bus.Publish("trayfrontend:update", updatedMenu) + // Make sure we catch any menu updates + case "setlabel": + updatedLabel := menuMessage.Data().(string) + t.trayMenu.Label = updatedLabel + + // Notify frontend of menu change + t.bus.Publish("trayfrontend:setlabel", updatedLabel) + default: t.logger.Error("unknown tray message: %+v", menuMessage) } @@ -134,7 +142,7 @@ func (t *Tray) Start() error { func (t *Tray) processMenu(trayMenu *menu.Menu) { // Initialise the variables t.menuItems = make(map[string]*menu.MenuItem) - t.trayMenu = trayMenu + t.trayMenu.Menu = trayMenu for _, item := range trayMenu.Items { t.processMenuItem(item) diff --git a/v2/pkg/menu/trayoptions.go b/v2/pkg/menu/trayoptions.go new file mode 100644 index 000000000..a0c7372ec --- /dev/null +++ b/v2/pkg/menu/trayoptions.go @@ -0,0 +1,14 @@ +package menu + +type TrayType string + +const ( + TrayIcon TrayType = "icon" + TrayLabel TrayType = "label" +) + +type TrayOptions struct { + Type TrayType + Label string + Menu *Menu +} diff --git a/v2/pkg/options/mac/mac.go b/v2/pkg/options/mac/mac.go index f6c7ea17d..da0be63b9 100644 --- a/v2/pkg/options/mac/mac.go +++ b/v2/pkg/options/mac/mac.go @@ -9,6 +9,6 @@ type Options struct { WebviewIsTransparent bool WindowBackgroundIsTranslucent bool Menu *menu.Menu - Tray *menu.Menu + Tray *menu.TrayOptions ContextMenus *menu.ContextMenus } diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go index f2a1d6ddf..7d24e72e3 100644 --- a/v2/pkg/options/options.go +++ b/v2/pkg/options/options.go @@ -25,7 +25,7 @@ type App struct { DevTools bool RGBA int ContextMenus *menu.ContextMenus - Tray *menu.Menu + Tray *menu.TrayOptions Menu *menu.Menu Mac *mac.Options Logger logger.Logger `json:"-"` @@ -49,8 +49,8 @@ func MergeDefaults(appoptions *App) { } -func GetTrayMenu(appoptions *App) *menu.Menu { - var result *menu.Menu +func GetTray(appoptions *App) *menu.TrayOptions { + var result *menu.TrayOptions switch runtime.GOOS { case "darwin": if appoptions.Mac != nil { diff --git a/v2/test/kitchensink/frontend/src/pages/Window/Window/Window.svelte b/v2/test/kitchensink/frontend/src/pages/Window/Window/Window.svelte index 8140e9b6a..1340bf57c 100644 --- a/v2/test/kitchensink/frontend/src/pages/Window/Window/Window.svelte +++ b/v2/test/kitchensink/frontend/src/pages/Window/Window/Window.svelte @@ -35,10 +35,8 @@ break; case 'Hide': windowRuntime.Hide(); - setTimeout( windowRuntime.Show, 3000 ); case 'Minimise': - windowRuntime.Hide(); - setTimeout( windowRuntime.Unminimise, 3000 ); + windowRuntime.Minimise(); default: windowRuntime[windowAction](); } @@ -92,8 +90,6 @@
diff --git a/v2/test/kitchensink/main.go b/v2/test/kitchensink/main.go index a7ce1fa0b..fa8689e59 100644 --- a/v2/test/kitchensink/main.go +++ b/v2/test/kitchensink/main.go @@ -3,6 +3,7 @@ package main import ( "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/logger" + "github.com/wailsapp/wails/v2/pkg/menu" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/mac" "log" @@ -27,7 +28,12 @@ func main() { // Comment out line below to see Window.SetTitle() work TitleBar: mac.TitleBarHiddenInset(), Menu: createApplicationMenu(), - Tray: createApplicationTray(), + Tray: &menu.TrayOptions{ + //Type: menu.TrayLabel, + Type: menu.TrayIcon, + Label: "Hi Go BitBar!", + Menu: createApplicationTray(), + }, }, LogLevel: logger.TRACE, }) diff --git a/v2/test/kitchensink/tray.go b/v2/test/kitchensink/tray.go index 68da2488c..e75d66c7f 100644 --- a/v2/test/kitchensink/tray.go +++ b/v2/test/kitchensink/tray.go @@ -1,8 +1,11 @@ package main import ( + "fmt" + "math/rand" "strconv" "sync" + "time" "github.com/wailsapp/wails/v2" "github.com/wailsapp/wails/v2/pkg/menu" @@ -16,6 +19,8 @@ type Tray struct { lock sync.Mutex dynamicMenuItems map[string]*menu.MenuItem anotherDynamicMenuCounter int + + done bool } // WailsInit is called at application startup @@ -26,25 +31,42 @@ func (t *Tray) WailsInit(runtime *wails.Runtime) error { // Setup Menu Listeners t.runtime.Tray.On("Show Window", func(mi *menu.MenuItem) { t.runtime.Window.Show() - showWindow := t.runtime.Tray.GetByID("Show Window") - hideWindow := t.runtime.Tray.GetByID("Hide Window") - showWindow.Hidden = true - hideWindow.Hidden = false - t.runtime.Tray.Update() }) t.runtime.Tray.On("Hide Window", func(mi *menu.MenuItem) { t.runtime.Window.Hide() - showWindow := t.runtime.Tray.GetByID("Show Window") - hideWindow := t.runtime.Tray.GetByID("Hide Window") - showWindow.Hidden = false - hideWindow.Hidden = true - t.runtime.Tray.Update() - }) + t.runtime.Tray.On("Minimise Window", func(mi *menu.MenuItem) { + t.runtime.Window.Minimise() + }) + + t.runtime.Tray.On("Unminimise Window", func(mi *menu.MenuItem) { + t.runtime.Window.Unminimise() + }) + + // Start ticker + //go t.startTicker() + return nil } +func (t *Tray) WailsShutdown() { + t.done = true +} + +func (t *Tray) startTicker() { + time.Sleep(1 * time.Second) + ticker := time.NewTicker(1 * time.Second) + for t.done == false { + select { + case <-ticker.C: + r := rand.Intn(100) + t.runtime.Tray.SetLabel(fmt.Sprintf("CPU: %d", r)) + } + } + ticker.Stop() +} + func (t *Tray) incrementcounter() int { t.dynamicMenuCounter++ return t.dynamicMenuCounter @@ -119,12 +141,9 @@ func (t *Tray) removeMenu(_ *menu.MenuItem) { func createApplicationTray() *menu.Menu { trayMenu := &menu.Menu{} - trayMenu.Append(&menu.MenuItem{ - ID: "Show Window", - Label: "Show Window", - Type: menu.TextType, - Hidden: true, - }) + trayMenu.Append(menu.Text("Show Window", "Show Window")) trayMenu.Append(menu.Text("Hide Window", "Hide Window")) + trayMenu.Append(menu.Text("Minimise Window", "Minimise Window")) + trayMenu.Append(menu.Text("Unminimise Window", "Unminimise Window")) return trayMenu }