diff --git a/v2/internal/ffenestri/ffenestri.h b/v2/internal/ffenestri/ffenestri.h index 3e457315..532f2bd9 100644 --- a/v2/internal/ffenestri/ffenestri.h +++ b/v2/internal/ffenestri/ffenestri.h @@ -36,7 +36,7 @@ extern void MessageDialog(struct Application*, char *callbackID, char *type, cha extern void DarkModeEnabled(struct Application*, char *callbackID); extern void SetApplicationMenu(struct Application*, const char *); extern void AddTrayMenu(struct Application*, const char *menuTrayJSON); -extern void UpdateTrayMenu(struct Application*, const char *menuTrayJSON); +extern void SetTrayMenu(struct Application*, const char *menuTrayJSON); extern void AddContextMenu(struct Application*, char *contextMenuJSON); extern void UpdateContextMenu(struct Application*, char *contextMenuJSON); diff --git a/v2/internal/ffenestri/ffenestri_client.go b/v2/internal/ffenestri/ffenestri_client.go index 2978fde5..23285d74 100644 --- a/v2/internal/ffenestri/ffenestri_client.go +++ b/v2/internal/ffenestri/ffenestri_client.go @@ -188,8 +188,8 @@ func (c *Client) SetApplicationMenu(applicationMenuJSON string) { C.SetApplicationMenu(c.app.app, c.app.string2CString(applicationMenuJSON)) } -func (c *Client) UpdateTrayMenu(trayMenuJSON string) { - C.UpdateTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON)) +func (c *Client) SetTrayMenu(trayMenuJSON string) { + C.SetTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON)) } func (c *Client) UpdateContextMenu(contextMenuJSON string) { diff --git a/v2/internal/ffenestri/ffenestri_darwin.c b/v2/internal/ffenestri/ffenestri_darwin.c index dc2e9e3c..a784f5b1 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.c +++ b/v2/internal/ffenestri/ffenestri_darwin.c @@ -926,8 +926,10 @@ void AddTrayMenu(struct Application *app, const char *trayMenuJSON) { AddTrayMenuToStore(app->trayMenuStore, trayMenuJSON); } -void UpdateTrayMenu(struct Application *app, const char* trayMenuJSON) { - UpdateTrayMenuInStore(app->trayMenuStore, trayMenuJSON); +void SetTrayMenu(struct Application *app, const char* trayMenuJSON) { + ON_MAIN_THREAD( + UpdateTrayMenuInStore(app->trayMenuStore, trayMenuJSON); + ); } void SetBindings(struct Application *app, const char *bindings) { diff --git a/v2/internal/ffenestri/traymenustore_darwin.c b/v2/internal/ffenestri/traymenustore_darwin.c index ae916a30..4fd89f07 100644 --- a/v2/internal/ffenestri/traymenustore_darwin.c +++ b/v2/internal/ffenestri/traymenustore_darwin.c @@ -77,8 +77,16 @@ void UpdateTrayMenuInStore(TrayMenuStore* store, const char* menuJSON) { // Get the current menu TrayMenu *currentMenu = GetTrayMenuFromStore(store, newMenu->ID); + + // If we don't have a menu, we create one if ( currentMenu == NULL ) { - ABORT("Attempted to update unknown tray menu with ID '%s'.", newMenu->ID); + + // Store the new menu + hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu); + + // Show it + ShowTrayMenu(newMenu); + return; } // Save the status bar reference diff --git a/v2/internal/menumanager/menuitemmap.go b/v2/internal/menumanager/menuitemmap.go index 57902ea1..790d5d06 100644 --- a/v2/internal/menumanager/menuitemmap.go +++ b/v2/internal/menumanager/menuitemmap.go @@ -26,6 +26,9 @@ func NewMenuItemMap() *MenuItemMap { } func (m *MenuItemMap) AddMenu(menu *menu.Menu) { + if menu == nil { + return + } for _, item := range menu.Items { m.processMenuItem(item) } diff --git a/v2/internal/menumanager/processedMenu.go b/v2/internal/menumanager/processedMenu.go index 4f98c347..13dfd7f5 100644 --- a/v2/internal/menumanager/processedMenu.go +++ b/v2/internal/menumanager/processedMenu.go @@ -63,9 +63,11 @@ type ProcessedMenu struct { func NewProcessedMenu(menuItemMap *MenuItemMap, menu *menu.Menu) *ProcessedMenu { result := &ProcessedMenu{} - for _, item := range menu.Items { - processedMenuItem := NewProcessedMenuItem(menuItemMap, item) - result.Items = append(result.Items, processedMenuItem) + if menu != nil { + for _, item := range menu.Items { + processedMenuItem := NewProcessedMenuItem(menuItemMap, item) + result.Items = append(result.Items, processedMenuItem) + } } return result diff --git a/v2/internal/menumanager/traymenu.go b/v2/internal/menumanager/traymenu.go index ff2c42b4..2771a299 100644 --- a/v2/internal/menumanager/traymenu.go +++ b/v2/internal/menumanager/traymenu.go @@ -50,7 +50,7 @@ func NewTrayMenu(trayMenu *menu.TrayMenu) *TrayMenu { return result } -func (m *Manager) AddTrayMenu(trayMenu *menu.TrayMenu) { +func (m *Manager) AddTrayMenu(trayMenu *menu.TrayMenu) (string, error) { newTrayMenu := NewTrayMenu(trayMenu) // Hook up a new ID @@ -60,12 +60,15 @@ func (m *Manager) AddTrayMenu(trayMenu *menu.TrayMenu) { // Save the references m.trayMenus[trayID] = newTrayMenu m.trayMenuPointers[trayMenu] = trayID + + return newTrayMenu.AsJSON() } -func (m *Manager) UpdateTrayMenu(trayMenu *menu.TrayMenu) (string, error) { +// SetTrayMenu updates or creates a menu +func (m *Manager) SetTrayMenu(trayMenu *menu.TrayMenu) (string, error) { trayID, trayMenuKnown := m.trayMenuPointers[trayMenu] if !trayMenuKnown { - return "", fmt.Errorf("unknown Tray Menu '%s'. Please add the tray menu using AddTrayMenu()", trayMenu.Label) + return m.AddTrayMenu(trayMenu) } // Create the updated tray menu diff --git a/v2/internal/messagedispatcher/dispatchclient.go b/v2/internal/messagedispatcher/dispatchclient.go index ec753af9..5037b971 100644 --- a/v2/internal/messagedispatcher/dispatchclient.go +++ b/v2/internal/messagedispatcher/dispatchclient.go @@ -31,7 +31,7 @@ type Client interface { WindowSetColour(colour int) DarkModeEnabled(callbackID string) SetApplicationMenu(menuJSON string) - UpdateTrayMenu(trayMenuJSON string) + SetTrayMenu(trayMenuJSON string) UpdateContextMenu(contextMenuJSON string) } diff --git a/v2/internal/messagedispatcher/message/system.go b/v2/internal/messagedispatcher/message/system.go index 0e2ae97a..1e69ec62 100644 --- a/v2/internal/messagedispatcher/message/system.go +++ b/v2/internal/messagedispatcher/message/system.go @@ -8,8 +8,8 @@ import ( // systemMessageParser does what it says on the tin! func systemMessageParser(message string) (*parsedMessage, error) { - // Sanity check: system messages must be at least 4 bytes - if len(message) < 4 { + // Sanity check: system messages must be at least 2 bytes + if len(message) < 2 { return nil, fmt.Errorf("system message was an invalid length") } @@ -23,6 +23,9 @@ func systemMessageParser(message string) (*parsedMessage, error) { // Format of system response messages: S| // DarkModeEnabled case 'D': + if len(message) < 4 { + return nil, fmt.Errorf("system message was an invalid length") + } message = message[1:] idx := strings.IndexByte(message, '|') if idx < 0 { @@ -34,6 +37,10 @@ func systemMessageParser(message string) (*parsedMessage, error) { topic := "systemresponse:" + callbackID responseMessage = &parsedMessage{Topic: topic, Data: payloadData == "T"} + // This is our startup hook - the frontend is now ready + case 'S': + topic := "hooks:startup" + responseMessage = &parsedMessage{Topic: topic, Data: nil} default: return nil, fmt.Errorf("Invalid message to systemMessageParser()") } diff --git a/v2/internal/messagedispatcher/messagedispatcher.go b/v2/internal/messagedispatcher/messagedispatcher.go index 589a2325..4d41bcb7 100644 --- a/v2/internal/messagedispatcher/messagedispatcher.go +++ b/v2/internal/messagedispatcher/messagedispatcher.go @@ -445,10 +445,10 @@ func (d *Dispatcher) processMenuMessage(result *servicebus.Message) { client.frontend.SetApplicationMenu(updatedMenu) } - case "updatetraymenu": - updatedTrayMenu, ok := result.Data().(string) + case "settraymenu": + trayMenuJSON, ok := result.Data().(string) if !ok { - d.logger.Error("Invalid data for 'menufrontend:updatetraymenu' : %#v", + d.logger.Error("Invalid data for 'menufrontend:settraymenu' : %#v", result.Data()) return } @@ -456,8 +456,9 @@ func (d *Dispatcher) processMenuMessage(result *servicebus.Message) { // 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.UpdateTrayMenu(updatedTrayMenu) + client.frontend.SetTrayMenu(trayMenuJSON) } + case "updatecontextmenu": updatedContextMenu, ok := result.Data().(string) if !ok { diff --git a/v2/internal/runtime/menu.go b/v2/internal/runtime/menu.go index 34fe75f6..710f2eaa 100644 --- a/v2/internal/runtime/menu.go +++ b/v2/internal/runtime/menu.go @@ -9,7 +9,7 @@ import ( type Menu interface { UpdateApplicationMenu() UpdateContextMenu(contextMenu *menu.ContextMenu) - UpdateTrayMenu(trayMenu *menu.TrayMenu) + SetTrayMenu(trayMenu *menu.TrayMenu) } type menuRuntime struct { @@ -31,6 +31,6 @@ func (m *menuRuntime) UpdateContextMenu(contextMenu *menu.ContextMenu) { m.bus.Publish("menu:updatecontextmenu", contextMenu) } -func (m *menuRuntime) UpdateTrayMenu(trayMenu *menu.TrayMenu) { - m.bus.Publish("menu:updatetraymenu", trayMenu) +func (m *menuRuntime) SetTrayMenu(trayMenu *menu.TrayMenu) { + m.bus.Publish("menu:settraymenu", trayMenu) } diff --git a/v2/internal/subsystem/menu.go b/v2/internal/subsystem/menu.go index 989f309c..91e63f92 100644 --- a/v2/internal/subsystem/menu.go +++ b/v2/internal/subsystem/menu.go @@ -120,16 +120,16 @@ func (m *Menu) Start() error { // Notify frontend of menu change m.bus.Publish("menufrontend:updatecontextmenu", updatedMenu) - case "updatetraymenu": + case "settraymenu": trayMenu := menuMessage.Data().(*menu.TrayMenu) - updatedMenu, err := m.menuManager.UpdateTrayMenu(trayMenu) + updatedMenu, err := m.menuManager.SetTrayMenu(trayMenu) if err != nil { m.logger.Trace("%s", err.Error()) return } // Notify frontend of menu change - m.bus.Publish("menufrontend:updatetraymenu", updatedMenu) + m.bus.Publish("menufrontend:settraymenu", updatedMenu) default: m.logger.Error("unknown menu message: %+v", menuMessage) diff --git a/v2/test/kitchensink/main.go b/v2/test/kitchensink/main.go index 55393738..d0a2b6e5 100644 --- a/v2/test/kitchensink/main.go +++ b/v2/test/kitchensink/main.go @@ -34,6 +34,8 @@ func main() { TrayMenus: Tray.createTrayMenus(), }, LogLevel: logger.TRACE, + Startup: Tray.start, + Shutdown: Tray.shutdown, }) if err != nil { diff --git a/v2/test/kitchensink/tray.go b/v2/test/kitchensink/tray.go index a2ca047e..8aa31112 100644 --- a/v2/test/kitchensink/tray.go +++ b/v2/test/kitchensink/tray.go @@ -21,8 +21,8 @@ type Tray struct { done bool } -// WailsInit is called at application startup -func (t *Tray) WailsInit(runtime *wails.Runtime) error { +// This is called at application startup +func (t *Tray) start(runtime *wails.Runtime) { // Perform your setup here t.runtime = runtime @@ -36,7 +36,6 @@ func (t *Tray) WailsInit(runtime *wails.Runtime) error { // t.runtime.Tray.SetIcon("dark") //}) - return nil } func (t *Tray) showWindow(_ *menu.CallbackData) { @@ -55,7 +54,7 @@ func (t *Tray) minimiseWindow(_ *menu.CallbackData) { t.runtime.Window.Minimise() } -func (t *Tray) WailsShutdown() { +func (t *Tray) shutdown() { t.done = true } @@ -71,19 +70,19 @@ func (t *Tray) decrementcounter() int { func (t *Tray) SvelteIcon(_ *menu.CallbackData) { t.secondTrayMenu.Icon = "svelte" - t.runtime.Menu.UpdateTrayMenu(t.secondTrayMenu) + t.runtime.Menu.SetTrayMenu(t.secondTrayMenu) } func (t *Tray) NoIcon(_ *menu.CallbackData) { t.secondTrayMenu.Icon = "" - t.runtime.Menu.UpdateTrayMenu(t.secondTrayMenu) + t.runtime.Menu.SetTrayMenu(t.secondTrayMenu) } func (t *Tray) LightIcon(_ *menu.CallbackData) { t.secondTrayMenu.Icon = "light" - t.runtime.Menu.UpdateTrayMenu(t.secondTrayMenu) + t.runtime.Menu.SetTrayMenu(t.secondTrayMenu) } func (t *Tray) DarkIcon(_ *menu.CallbackData) { t.secondTrayMenu.Icon = "dark" - t.runtime.Menu.UpdateTrayMenu(t.secondTrayMenu) + t.runtime.Menu.SetTrayMenu(t.secondTrayMenu) } //func (t *Tray) removeMenu(_ *menu.MenuItem) { @@ -146,7 +145,7 @@ func (t *Tray) createTrayMenus() []*menu.TrayMenu { counter := t.incrementcounter() trayLabel := "Updated Label " + strconv.Itoa(counter) secondTrayMenu.Label = trayLabel - t.runtime.Menu.UpdateTrayMenu(t.secondTrayMenu) + t.runtime.Menu.SetTrayMenu(t.secondTrayMenu) }), menu.SubMenu("Select Icon", menu.NewMenuFromItems( menu.Text("Svelte", nil, t.SvelteIcon),