diff --git a/v2/internal/app/desktop.go b/v2/internal/app/desktop.go index 3548fb3d..3f89c36d 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 66c5e2d4..7aa1b76c 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 41089e56..d1be1115 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 38fd3fd6..3dbe7c42 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 3d9043d7..8d4a7d6e 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 bf29efbd..3ca84604 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 f5602b67..cf822fce 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 cad34d55..fb19a7c8 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 30a4d7dd..4452a761 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 1695bb1a..e8420ed7 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 c24603fa..257db391 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 cdccbadb..45c9b968 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 00000000..a0c7372e --- /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 f6c7ea17..da0be63b 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 f2a1d6dd..7d24e72e 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 8140e9b6..1340bf57 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 @@