diff --git a/v2/internal/app/desktop.go b/v2/internal/app/desktop.go index 64bb10c26..96e88360d 100644 --- a/v2/internal/app/desktop.go +++ b/v2/internal/app/desktop.go @@ -63,10 +63,8 @@ func CreateApp(appoptions *options.App) (*App, error) { // Process context menus contextMenus := options.GetContextMenus(appoptions) - if contextMenus != nil { - for contextMenuID, contextMenu := range contextMenus.Items { - menuManager.AddContextMenu(contextMenuID, contextMenu) - } + for _, contextMenu := range contextMenus { + menuManager.AddContextMenu(contextMenu) } // Process tray menus diff --git a/v2/internal/ffenestri/contextmenus_darwin.c b/v2/internal/ffenestri/contextmenus_darwin.c index bf1effcf5..deaaf397b 100644 --- a/v2/internal/ffenestri/contextmenus_darwin.c +++ b/v2/internal/ffenestri/contextmenus_darwin.c @@ -8,9 +8,20 @@ #include "contextmenus_darwin.h" #include "menu_darwin.h" -ContextMenu* NewContextMenu(JsonNode* menuData, ContextMenuStore *store) { +ContextMenu* NewContextMenu(const char* contextMenuJSON) { ContextMenu* result = malloc(sizeof(ContextMenu)); - result->menu = NewMenu(menuData); + + JsonNode* processedJSON = json_decode(contextMenuJSON); + if( processedJSON == NULL ) { + ABORT("[NewTrayMenu] Unable to parse TrayMenu JSON: %s", contextMenuJSON); + } + // Save reference to this json + result->processedJSON = processedJSON; + + result->ID = mustJSONString(processedJSON, "ID"); + JsonNode* processedMenu = mustJSONObject(processedJSON, "ProcessedMenu"); + + result->menu = NewMenu(processedMenu); result->nsmenu = NULL; result->menu->menuType = ContextMenuType; result->menu->parentData = result; @@ -18,9 +29,8 @@ ContextMenu* NewContextMenu(JsonNode* menuData, ContextMenuStore *store) { return result; } - ContextMenu* GetContextMenuByID(ContextMenuStore* store, const char *contextMenuID) { - return (ContextMenu*)hashmap_get(&store->contextMenuStore, (char*)contextMenuID, strlen(contextMenuID)); + return (ContextMenu*)hashmap_get(&store->contextMenuMap, (char*)contextMenuID, strlen(contextMenuID)); } void DeleteContextMenu(ContextMenu* contextMenu) { @@ -32,6 +42,12 @@ void DeleteContextMenu(ContextMenu* contextMenu) { MEMFREE(contextMenu->contextMenuData); } + // Free JSON + if (contextMenu->processedJSON != NULL ) { + json_delete(contextMenu->processedJSON); + contextMenu->processedJSON = NULL; + } + // Free context menu free(contextMenu); } @@ -41,43 +57,6 @@ int freeContextMenu(void *const context, struct hashmap_element_s *const e) { return -1; } -void ProcessContextMenus(ContextMenuStore* store) { - - // Decode the context menus JSON - store->processedContextMenus = json_decode(store->contextMenusAsJSON); - if( store->processedContextMenus == NULL ) { - ABORT("[ProcessContextMenus] Unable to parse Context Menus JSON: %s", store->contextMenusAsJSON); - } - -// // Get the context menu items -// JsonNode *contextMenuItems = json_find_member(store->processedContextMenus, "Items"); -// if( contextMenuItems == NULL ) { -// ABORT("[ProcessContextMenus] Unable to find Items in processedContextMenus!"); -// } - - // Iterate context menus - JsonNode *contextMenu; - json_foreach(contextMenu, store->processedContextMenus) { - - const char* ID = getJSONString(contextMenu, "ID"); - if ( ID == NULL ) { - ABORT("Unable to read ID of contextMenu\n"); - } - - JsonNode* processedMenu = json_find_member(contextMenu, "ProcessedMenu"); - if ( processedMenu == NULL ) { - ABORT("Unable to read ProcessedMenu of contextMenu\n"); - } - // Create a new context menu instance - ContextMenu *thisContextMenu = NewContextMenu(processedMenu, store); - thisContextMenu->ID = ID; - - // Store the item in the context menu map - hashmap_put(&store->contextMenuStore, (char*)ID, strlen(ID), thisContextMenu); - } - -} - void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData) { // If no context menu ID was given, abort diff --git a/v2/internal/ffenestri/contextmenus_darwin.h b/v2/internal/ffenestri/contextmenus_darwin.h index 3091a1312..a1e7b976a 100644 --- a/v2/internal/ffenestri/contextmenus_darwin.h +++ b/v2/internal/ffenestri/contextmenus_darwin.h @@ -14,17 +14,19 @@ typedef struct { id nsmenu; Menu* menu; - // The optional data that may be passed with a context menu selection + JsonNode* processedJSON; + + // Context menu data is given by the frontend when clicking a context menu. + // We send this to the backend when an item is selected const char* contextMenuData; } ContextMenu; -ContextMenu* NewContextMenu(JsonNode* menuData, ContextMenuStore* store); +ContextMenu* NewContextMenu(const char* contextMenuJSON); ContextMenu* GetContextMenuByID( ContextMenuStore* store, const char *contextMenuID); void DeleteContextMenu(ContextMenu* contextMenu); int freeContextMenu(void *const context, struct hashmap_element_s *const e); -void ProcessContextMenus( ContextMenuStore* store); void ShowContextMenu(ContextMenuStore* store, id mainWindow, const char *contextMenuID, const char *contextMenuData); diff --git a/v2/internal/ffenestri/contextmenustore_darwin.c b/v2/internal/ffenestri/contextmenustore_darwin.c index b2a9be579..c777f014e 100644 --- a/v2/internal/ffenestri/contextmenustore_darwin.c +++ b/v2/internal/ffenestri/contextmenustore_darwin.c @@ -2,22 +2,48 @@ #include "contextmenus_darwin.h" #include "contextmenustore_darwin.h" -ContextMenuStore* NewContextMenuStore(const char* contextMenusAsJSON) { +ContextMenuStore* NewContextMenuStore() { ContextMenuStore* result = malloc(sizeof(ContextMenuStore)); - // Init members - result->contextMenusAsJSON = contextMenusAsJSON; - result->processedContextMenus = NULL; - // Allocate Context Menu Store - if( 0 != hashmap_create((const unsigned)4, &result->contextMenuStore)) { + if( 0 != hashmap_create((const unsigned)4, &result->contextMenuMap)) { ABORT("[NewContextMenus] Not enough memory to allocate contextMenuStore!"); } return result; } +void AddContextMenuToStore(ContextMenuStore* store, const char* contextMenuJSON) { + ContextMenu* newMenu = NewContextMenu(contextMenuJSON); + + //TODO: check if there is already an entry for this menu + hashmap_put(&store->contextMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu); +} + +ContextMenu* GetContextMenuFromStore(ContextMenuStore* store, const char* menuID) { + // Get the current menu + return hashmap_get(&store->contextMenuMap, menuID, strlen(menuID)); +} + +void UpdateContextMenuInStore(ContextMenuStore* store, const char* menuJSON) { + ContextMenu* newContextMenu = NewContextMenu(menuJSON); + + // Get the current menu + ContextMenu *currentMenu = GetContextMenuFromStore(store, newContextMenu->ID); + if ( currentMenu == NULL ) { + ABORT("Attempted to update unknown context menu with ID '%s'.", newContextMenu->ID); + } + + hashmap_remove(&store->contextMenuMap, newContextMenu->ID, strlen(newContextMenu->ID)); + + // Save the status bar reference + DeleteContextMenu(currentMenu); + + hashmap_put(&store->contextMenuMap, newContextMenu->ID, strlen(newContextMenu->ID), newContextMenu); + +} + void DeleteContextMenuStore(ContextMenuStore* store) { @@ -27,19 +53,13 @@ void DeleteContextMenuStore(ContextMenuStore* store) { } // Delete context menus - if( hashmap_num_entries(&store->contextMenuStore) > 0 ) { - if (0 != hashmap_iterate_pairs(&store->contextMenuStore, freeContextMenu, NULL)) { + if( hashmap_num_entries(&store->contextMenuMap) > 0 ) { + if (0 != hashmap_iterate_pairs(&store->contextMenuMap, freeContextMenu, NULL)) { ABORT("[DeleteContextMenuStore] Failed to release contextMenuStore entries!"); } } // Free context menu hashmap - hashmap_destroy(&store->contextMenuStore); - - // Destroy processed Context Menus - if( store->processedContextMenus != NULL) { - json_delete(store->processedContextMenus); - store->processedContextMenus = NULL; - } + hashmap_destroy(&store->contextMenuMap); } diff --git a/v2/internal/ffenestri/contextmenustore_darwin.h b/v2/internal/ffenestri/contextmenustore_darwin.h index f7e42a11d..793eef691 100644 --- a/v2/internal/ffenestri/contextmenustore_darwin.h +++ b/v2/internal/ffenestri/contextmenustore_darwin.h @@ -8,19 +8,20 @@ #include "common.h" typedef struct { + + int dummy; + // This is our context menu store which keeps track // of all instances of ContextMenus - struct hashmap_s contextMenuStore; - - // The raw JSON defining the context menus - const char* contextMenusAsJSON; - - // The processed context menus - JsonNode* processedContextMenus; + struct hashmap_s contextMenuMap; } ContextMenuStore; -ContextMenuStore* NewContextMenuStore(const char* contextMenusAsJSON); +ContextMenuStore* NewContextMenuStore(); + void DeleteContextMenuStore(ContextMenuStore* store); +void UpdateContextMenuInStore(ContextMenuStore* store, const char* menuJSON); + +void AddContextMenuToStore(ContextMenuStore* store, const char* contextMenuJSON); #endif //CONTEXTMENUSTORE_DARWIN_H diff --git a/v2/internal/ffenestri/ffenestri.h b/v2/internal/ffenestri/ffenestri.h index 847ad64ff..3e4573158 100644 --- a/v2/internal/ffenestri/ffenestri.h +++ b/v2/internal/ffenestri/ffenestri.h @@ -35,11 +35,9 @@ extern void SaveDialog(struct Application*, char *callbackID, char *title, char extern void MessageDialog(struct Application*, char *callbackID, char *type, char *title, char *message, char *icon, char *button1, char *button2, char *button3, char *button4, char *defaultButton, char *cancelButton); extern void DarkModeEnabled(struct Application*, char *callbackID); extern void SetApplicationMenu(struct Application*, const char *); -extern void UpdateTray(struct Application*, char *menuAsJSON); -extern void UpdateContextMenus(struct Application*, char *contextMenusAsJSON); -extern void UpdateTrayLabel(struct Application*, const char *label); -extern void UpdateTrayIcon(struct Application*, const char *label); -extern void AddTrayMenu(struct Application*, const char *trayAsJSON); -extern void UpdateTrayMenu(struct Application*, const char *trayAsJSON); +extern void AddTrayMenu(struct Application*, const char *menuTrayJSON); +extern void UpdateTrayMenu(struct Application*, const char *menuTrayJSON); +extern void AddContextMenu(struct Application*, char *contextMenuJSON); +extern void UpdateContextMenu(struct Application*, char *contextMenuJSON); #endif diff --git a/v2/internal/ffenestri/ffenestri_client.go b/v2/internal/ffenestri/ffenestri_client.go index 96c8c7198..8bbe0578f 100644 --- a/v2/internal/ffenestri/ffenestri_client.go +++ b/v2/internal/ffenestri/ffenestri_client.go @@ -12,7 +12,6 @@ package ffenestri import "C" import ( - "github.com/wailsapp/wails/v2/pkg/menu" "strconv" "github.com/wailsapp/wails/v2/internal/logger" @@ -193,17 +192,6 @@ func (c *Client) UpdateTrayMenu(trayMenuJSON string) { C.UpdateTrayMenu(c.app.app, c.app.string2CString(trayMenuJSON)) } -func (c *Client) UpdateContextMenus(contextMenus *menu.ContextMenus) { - // - // // Guard against nil contextMenus - // if contextMenus == nil { - // return - // } - // // Process the menu - // contextMenusJSON, err := processContextMenus(contextMenus) - // if err != nil { - // c.app.logger.Error("Error processing updated Context Menu: %s", err.Error()) - // return - // } - // C.UpdateContextMenus(c.app.app, c.app.string2CString(contextMenusJSON)) +func (c *Client) UpdateContextMenu(contextMenuJSON string) { + C.UpdateContextMenu(c.app.app, c.app.string2CString(contextMenuJSON)) } diff --git a/v2/internal/ffenestri/ffenestri_darwin.c b/v2/internal/ffenestri/ffenestri_darwin.c index 4aea453d2..5367032ec 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.c +++ b/v2/internal/ffenestri/ffenestri_darwin.c @@ -117,8 +117,6 @@ struct Application { // Context Menus ContextMenuStore *contextMenuStore; - const char *contextMenusAsJSON; - JsonNode *processedContextMenus; // Callback ffenestriCallback sendMessageToBackend; @@ -427,9 +425,12 @@ void DestroyApplication(struct Application *app) { DeleteMenu(app->applicationMenu); } - // Delete the tray menu store + // Delete the tray menu store DeleteTrayMenuStore(app->trayMenuStore); + // Delete the context menu store + DeleteContextMenuStore(app->contextMenuStore); + // Destroy the context menus destroyContextMenus(app); @@ -439,11 +440,6 @@ void DestroyApplication(struct Application *app) { // Unload the tray Icons UnloadTrayIcons(); - // Clear context menu data if we have it - if( contextMenuData != NULL ) { - MEMFREE(contextMenuData); - } - // Remove script handlers msg(app->manager, s("removeScriptMessageHandlerForName:"), str("contextMenu")); msg(app->manager, s("removeScriptMessageHandlerForName:"), str("windowDrag")); @@ -916,17 +912,20 @@ void SetDebug(void *applicationPointer, int flag) { // SetContextMenus sets the context menu map for this application -void SetContextMenus(struct Application *app, const char *contextMenusAsJSON) { - app->contextMenuStore = NewContextMenuStore(contextMenusAsJSON); +void AddContextMenu(struct Application *app, const char *contextMenuJSON) { + AddContextMenuToStore(app->contextMenuStore, contextMenuJSON); } - -void AddTrayMenu(struct Application *app, const char *trayJSON) { - AddTrayMenuToStore(app->trayMenuStore, trayJSON); +void UpdateContextMenu(struct Application *app, const char* contextMenuJSON) { + UpdateContextMenuInStore(app->contextMenuStore, contextMenuJSON); } -void UpdateTrayMenu(struct Application *app, const char* trayJSON) { - UpdateTrayMenuInStore(app->trayMenuStore, trayJSON); +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 SetBindings(struct Application *app, const char *bindings) { @@ -1428,84 +1427,6 @@ void SetApplicationMenu(struct Application *app, const char *menuAsJSON) { updateMenu(app, menuAsJSON); } -//void dumpContextMenus(struct Application *app) { -// dumpHashmap("menuItemMapForContextMenus", &menuItemMapForContextMenus); -// printf("&menuItemMapForContextMenus = %p\n", &menuItemMapForContextMenus); -// -// //Free radio groups hashmap -// dumpHashmap("radioGroupMapForContextMenus", &radioGroupMapForContextMenus); -// printf("&radioGroupMapForContextMenus = %p\n", &radioGroupMapForContextMenus); -// -// //Free context menu map -// dumpHashmap("contextMenuMap", &contextMenuMap); -// printf("&contextMenuMap = %p\n", &contextMenuMap); -//} - -//void parseContextMenus(struct Application *app) { -// -// // Parse the context menu json -// app->processedContextMenus = json_decode(app->contextMenusAsJSON); -// -// if( app->processedContextMenus == NULL ) { -// // Parse error! -// Fatal(app, "Unable to parse Context Menus JSON: %s", app->contextMenusAsJSON); -// return; -// } -// -// JsonNode *contextMenuItems = json_find_member(app->processedContextMenus, "Items"); -// if( contextMenuItems == NULL ) { -// // Parse error! -// Fatal(app, "Unable to find Items:", app->processedContextMenus); -// return; -// } -// // Iterate context menus -// JsonNode *contextMenu; -// json_foreach(contextMenu, contextMenuItems) { -// // Create a new menu -// id menu = createMenu(str("")); -// -// // parse the menu -// parseMenu(app, menu, contextMenu, &menuItemMapForContextMenus, -// "checkboxMenuCallbackForContextMenus:", "radioMenuCallbackForContextMenus:", "menuCallbackForContextMenus:"); -// -// // Store the item in the context menu map -// hashmap_put(&contextMenuMap, (char*)contextMenu->key, strlen(contextMenu->key), menu); -// } -// -//// dumpContextMenus(app); -//} - -void UpdateTrayLabel(struct Application *app, const char *label) { - // TBD -} - -void UpdateTrayIcon(struct Application *app, const char *name) { - // TBD -} - -// UpdateTray replaces the current tray menu with the given one -void UpdateTray(struct Application *app, const char *trayMenuAsJSON) { - ON_MAIN_THREAD ( - // TBD - ); -} - -void UpdateContextMenus(struct Application *app, const char *contextMenusAsJSON) { - - ON_MAIN_THREAD ( - - // Free up memory - DeleteContextMenuStore(app->contextMenuStore); - - // Recreate Context Menus - app->contextMenuStore = NewContextMenuStore(contextMenusAsJSON); - - // Process them - ProcessContextMenus(app->contextMenuStore); - ); - -} - void processDialogIcons(struct hashmap_s *hashmap, const unsigned char *dialogIcons[]) { unsigned int count = 0; @@ -1727,11 +1648,6 @@ void Run(struct Application *app, int argc, char **argv) { // Setup initial trays ShowTrayMenusInStore(app->trayMenuStore); - // If we have context menus, process them - if( app->contextMenuStore != NULL ) { - ProcessContextMenus(app->contextMenuStore); - } - // Process dialog icons processUserDialogIcons(app); @@ -1793,10 +1709,7 @@ void* NewApplication(const char *title, int width, int height, int resizable, in result->trayMenuStore = NewTrayMenuStore(); // Context Menus - result->contextMenuStore = NULL; - result->contextMenusAsJSON = NULL; - result->processedContextMenus = NULL; - contextMenuData = NULL; + result->contextMenuStore = NewContextMenuStore(); // Window Appearance result->titlebarAppearsTransparent = 0; diff --git a/v2/internal/ffenestri/ffenestri_darwin.go b/v2/internal/ffenestri/ffenestri_darwin.go index 0bb05912c..fafb391b8 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.go +++ b/v2/internal/ffenestri/ffenestri_darwin.go @@ -72,20 +72,20 @@ func (a *Application) processPlatformSettings() error { } if trays != nil { for _, tray := range trays { - println("Adding tray menu: " + tray) C.AddTrayMenu(a.app, a.string2CString(tray)) } } // Process context menus - //contextMenus := options.GetContextMenus(a.config) - //if contextMenus != nil { - // contextMenusJSON, err := processContextMenus(contextMenus) - // if err != nil { - // return err - // } - // C.SetContextMenus(a.app, a.string2CString(contextMenusJSON)) - //} + contextMenus, err := a.menuManager.GetContextMenus() + if err != nil { + return err + } + if contextMenus != nil { + for _, contextMenu := range contextMenus { + C.AddContextMenu(a.app, a.string2CString(contextMenu)) + } + } return nil } diff --git a/v2/internal/ffenestri/traymenustore_darwin.c b/v2/internal/ffenestri/traymenustore_darwin.c index 89035d591..ae916a303 100644 --- a/v2/internal/ffenestri/traymenustore_darwin.c +++ b/v2/internal/ffenestri/traymenustore_darwin.c @@ -30,6 +30,8 @@ void DumpTrayMenuStore(TrayMenuStore* store) { void AddTrayMenuToStore(TrayMenuStore* store, const char* menuJSON) { TrayMenu* newMenu = NewTrayMenu(menuJSON); + + //TODO: check if there is already an entry for this menu hashmap_put(&store->trayMenuMap, newMenu->ID, strlen(newMenu->ID), newMenu); } diff --git a/v2/internal/menumanager/contextmenu.go b/v2/internal/menumanager/contextmenu.go index 5067f767b..e07cc2222 100644 --- a/v2/internal/menumanager/contextmenu.go +++ b/v2/internal/menumanager/contextmenu.go @@ -1,47 +1,60 @@ package menumanager import ( + "encoding/json" "fmt" "github.com/wailsapp/wails/v2/pkg/menu" ) type ContextMenu struct { - ID string - JSON string - menuItemMap *MenuItemMap - menu *menu.Menu + ID string + ProcessedMenu *WailsMenu + menuItemMap *MenuItemMap + menu *menu.Menu } -func NewContextMenu(ID string, menu *menu.Menu) *ContextMenu { +func (t *ContextMenu) AsJSON() (string, error) { + data, err := json.Marshal(t) + if err != nil { + return "", err + } + return string(data), nil +} + +func NewContextMenu(contextMenu *menu.ContextMenu) *ContextMenu { result := &ContextMenu{ - ID: ID, - JSON: "", - menu: menu, + ID: contextMenu.ID, + menu: contextMenu.Menu, menuItemMap: NewMenuItemMap(), } - result.menuItemMap.AddMenu(menu) + result.menuItemMap.AddMenu(contextMenu.Menu) + result.ProcessedMenu = NewWailsMenu(result.menuItemMap, result.menu) return result } -func (m *Manager) AddContextMenu(menuID string, menu *menu.Menu) error { - contextMenu := NewContextMenu(menuID, menu) - m.contextMenus[menuID] = contextMenu - return contextMenu.process() +func (m *Manager) AddContextMenu(contextMenu *menu.ContextMenu) { + + newContextMenu := NewContextMenu(contextMenu) + + // Save the references + m.contextMenus[contextMenu.ID] = newContextMenu + m.contextMenuPointers[contextMenu] = contextMenu.ID } -func (c *ContextMenu) process() error { - - // Process the menu - processedApplicationMenu := NewWailsMenu(c.menuItemMap, c.menu) - JSON, err := processedApplicationMenu.AsJSON() - if err != nil { - return err +func (m *Manager) UpdateContextMenu(contextMenu *menu.ContextMenu) (string, error) { + contextMenuID, contextMenuKnown := m.contextMenuPointers[contextMenu] + if !contextMenuKnown { + return "", fmt.Errorf("unknown Context Menu '%s'. Please add the context menu using AddContextMenu()", contextMenu.ID) } - c.JSON = JSON - fmt.Printf("Processed context menu '%s':", c.ID) - println(JSON) - return nil + + // Create the updated context menu + updatedContextMenu := NewContextMenu(contextMenu) + + // Save the reference + m.contextMenus[contextMenuID] = updatedContextMenu + + return updatedContextMenu.AsJSON() } diff --git a/v2/internal/menumanager/menumanager.go b/v2/internal/menumanager/menumanager.go index 092ef5e9e..862143bb3 100644 --- a/v2/internal/menumanager/menumanager.go +++ b/v2/internal/menumanager/menumanager.go @@ -15,7 +15,8 @@ type Manager struct { applicationMenuItemMap *MenuItemMap // Context menus - contextMenus map[string]*ContextMenu + contextMenus map[string]*ContextMenu + contextMenuPointers map[*menu.ContextMenu]string // Tray menu stores trayMenus map[string]*TrayMenu @@ -26,6 +27,7 @@ func NewManager() *Manager { return &Manager{ applicationMenuItemMap: NewMenuItemMap(), contextMenus: make(map[string]*ContextMenu), + contextMenuPointers: make(map[*menu.ContextMenu]string), trayMenus: make(map[string]*TrayMenu), trayMenuPointers: make(map[*menu.TrayMenu]string), } diff --git a/v2/internal/menumanager/traymenu.go b/v2/internal/menumanager/traymenu.go index 1ad53ef79..ff2c42b41 100644 --- a/v2/internal/menumanager/traymenu.go +++ b/v2/internal/menumanager/traymenu.go @@ -90,3 +90,16 @@ func (m *Manager) GetTrayMenus() ([]string, error) { return result, nil } + +func (m *Manager) GetContextMenus() ([]string, error) { + result := []string{} + for _, contextMenu := range m.contextMenus { + JSON, err := contextMenu.AsJSON() + if err != nil { + return nil, err + } + result = append(result, JSON) + } + + return result, nil +} diff --git a/v2/internal/messagedispatcher/dispatchclient.go b/v2/internal/messagedispatcher/dispatchclient.go index 09855047d..9da3731ed 100644 --- a/v2/internal/messagedispatcher/dispatchclient.go +++ b/v2/internal/messagedispatcher/dispatchclient.go @@ -2,8 +2,6 @@ package messagedispatcher import ( "fmt" - "github.com/wailsapp/wails/v2/pkg/menu" - "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/messagedispatcher/message" "github.com/wailsapp/wails/v2/internal/servicebus" @@ -33,8 +31,8 @@ type Client interface { WindowSetColour(colour int) DarkModeEnabled(callbackID string) SetApplicationMenu(menuJSON string) - UpdateTrayMenu(menuJSON string) - UpdateContextMenus(contextMenus *menu.ContextMenus) + UpdateTrayMenu(trayMenuJSON string) + UpdateContextMenu(contextMenuJSON string) } // DispatchClient is what the frontends use to interface with the diff --git a/v2/internal/messagedispatcher/messagedispatcher.go b/v2/internal/messagedispatcher/messagedispatcher.go index 6a7958cef..7df5c0616 100644 --- a/v2/internal/messagedispatcher/messagedispatcher.go +++ b/v2/internal/messagedispatcher/messagedispatcher.go @@ -2,7 +2,6 @@ package messagedispatcher import ( "encoding/json" - "github.com/wailsapp/wails/v2/pkg/menu" "strconv" "strings" "sync" @@ -17,15 +16,14 @@ import ( // Dispatcher translates messages received from the frontend // and publishes them onto the service bus type Dispatcher struct { - quitChannel <-chan *servicebus.Message - resultChannel <-chan *servicebus.Message - eventChannel <-chan *servicebus.Message - windowChannel <-chan *servicebus.Message - dialogChannel <-chan *servicebus.Message - systemChannel <-chan *servicebus.Message - menuChannel <-chan *servicebus.Message - contextMenuChannel <-chan *servicebus.Message - running bool + quitChannel <-chan *servicebus.Message + resultChannel <-chan *servicebus.Message + eventChannel <-chan *servicebus.Message + windowChannel <-chan *servicebus.Message + dialogChannel <-chan *servicebus.Message + systemChannel <-chan *servicebus.Message + menuChannel <-chan *servicebus.Message + running bool servicebus *servicebus.ServiceBus logger logger.CustomLogger @@ -77,23 +75,17 @@ func New(servicebus *servicebus.ServiceBus, logger *logger.Logger) (*Dispatcher, return nil, err } - contextMenuChannel, err := servicebus.Subscribe("contextmenufrontend:") - if err != nil { - return nil, err - } - result := &Dispatcher{ - servicebus: servicebus, - eventChannel: eventChannel, - logger: logger.CustomLogger("Message Dispatcher"), - clients: make(map[string]*DispatchClient), - resultChannel: resultChannel, - quitChannel: quitChannel, - windowChannel: windowChannel, - dialogChannel: dialogChannel, - systemChannel: systemChannel, - menuChannel: menuChannel, - contextMenuChannel: contextMenuChannel, + servicebus: servicebus, + eventChannel: eventChannel, + logger: logger.CustomLogger("Message Dispatcher"), + clients: make(map[string]*DispatchClient), + resultChannel: resultChannel, + quitChannel: quitChannel, + windowChannel: windowChannel, + dialogChannel: dialogChannel, + systemChannel: systemChannel, + menuChannel: menuChannel, } return result, nil @@ -125,8 +117,6 @@ func (d *Dispatcher) Start() error { d.processSystemMessage(systemMessage) case menuMessage := <-d.menuChannel: d.processMenuMessage(menuMessage) - case contextMenuMessage := <-d.contextMenuChannel: - d.processContextMenuMessage(contextMenuMessage) } } @@ -468,25 +458,10 @@ func (d *Dispatcher) processMenuMessage(result *servicebus.Message) { for _, client := range d.clients { client.frontend.UpdateTrayMenu(updatedTrayMenu) } - - default: - d.logger.Error("Unknown menufrontend command: %s", command) - } -} -func (d *Dispatcher) processContextMenuMessage(result *servicebus.Message) { - splitTopic := strings.Split(result.Topic(), ":") - if len(splitTopic) < 2 { - d.logger.Error("Invalid contextmenu message : %#v", result.Data()) - return - } - - command := splitTopic[1] - switch command { - case "update": - - updatedContextMenus, ok := result.Data().(*menu.ContextMenus) + case "updatecontextmenu": + updatedContextMenu, ok := result.Data().(string) if !ok { - d.logger.Error("Invalid data for 'contextmenufrontend:update' : %#v", + d.logger.Error("Invalid data for 'menufrontend:updatecontextmenu' : %#v", result.Data()) return } @@ -494,10 +469,10 @@ func (d *Dispatcher) processContextMenuMessage(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.UpdateContextMenus(updatedContextMenus) + client.frontend.UpdateContextMenu(updatedContextMenu) } default: - d.logger.Error("Unknown contextmenufrontend command: %s", command) + d.logger.Error("Unknown menufrontend command: %s", command) } } diff --git a/v2/internal/subsystem/menu.go b/v2/internal/subsystem/menu.go index 80bdf3732..989f309c5 100644 --- a/v2/internal/subsystem/menu.go +++ b/v2/internal/subsystem/menu.go @@ -110,16 +110,16 @@ func (m *Menu) Start() error { m.bus.Publish("menufrontend:updateappmenu", updatedMenu) case "updatecontextmenu": - m.logger.Info("Update Context Menu TBD") - //contextMenu := menuMessage.Data().(*menu.ContextMenu) - //updatedMenu, err := m.menuManager.UpdateContextMenu(contextMenu) - //if err != nil { - // m.logger.Trace("%s", err.Error()) - // return - //} - // - //// Notify frontend of menu change - //m.bus.Publish("menufrontend:updatecontextmenu", updatedMenu) + contextMenu := menuMessage.Data().(*menu.ContextMenu) + updatedMenu, err := m.menuManager.UpdateContextMenu(contextMenu) + if err != nil { + m.logger.Trace("%s", err.Error()) + return + } + + // Notify frontend of menu change + m.bus.Publish("menufrontend:updatecontextmenu", updatedMenu) + case "updatetraymenu": trayMenu := menuMessage.Data().(*menu.TrayMenu) updatedMenu, err := m.menuManager.UpdateTrayMenu(trayMenu) diff --git a/v2/pkg/menu/contextmenu.go b/v2/pkg/menu/contextmenu.go index 869991e44..e24b04067 100644 --- a/v2/pkg/menu/contextmenu.go +++ b/v2/pkg/menu/contextmenu.go @@ -1,19 +1,5 @@ package menu -type ContextMenus struct { - Items map[string]*Menu -} - -func NewContextMenus() *ContextMenus { - return &ContextMenus{ - Items: make(map[string]*Menu), - } -} - -func (c *ContextMenus) AddMenu(ID string, menu *Menu) { - c.Items[ID] = menu -} - type ContextMenu struct { ID string Menu *Menu diff --git a/v2/pkg/options/mac/mac.go b/v2/pkg/options/mac/mac.go index fcf9d1cc6..3e0a85073 100644 --- a/v2/pkg/options/mac/mac.go +++ b/v2/pkg/options/mac/mac.go @@ -10,5 +10,5 @@ type Options struct { WindowBackgroundIsTranslucent bool Menu *menu.Menu TrayMenus []*menu.TrayMenu - ContextMenus *menu.ContextMenus + ContextMenus []*menu.ContextMenu } diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go index 8df231cdf..0df0bf4b6 100644 --- a/v2/pkg/options/options.go +++ b/v2/pkg/options/options.go @@ -24,7 +24,7 @@ type App struct { StartHidden bool DevTools bool RGBA int - ContextMenus *menu.ContextMenus + ContextMenus []*menu.ContextMenu TrayMenus []*menu.TrayMenu Menu *menu.Menu Mac *mac.Options @@ -89,15 +89,13 @@ func GetApplicationMenu(appoptions *App) *menu.Menu { return result } -func GetContextMenus(appoptions *App) *menu.ContextMenus { - var result *menu.ContextMenus +func GetContextMenus(appoptions *App) []*menu.ContextMenu { + var result []*menu.ContextMenu - result = appoptions.ContextMenus - var contextMenuOverrides *menu.ContextMenus switch runtime.GOOS { case "darwin": if appoptions.Mac != nil { - contextMenuOverrides = appoptions.Mac.ContextMenus + result = appoptions.Mac.ContextMenus } //case "linux": // if appoptions.Linux != nil { @@ -109,11 +107,8 @@ func GetContextMenus(appoptions *App) *menu.ContextMenus { // } } - // Overwrite defaults with OS Specific context menus - if contextMenuOverrides != nil { - for id, contextMenu := range contextMenuOverrides.Items { - result.AddMenu(id, contextMenu) - } + if result == nil { + result = appoptions.ContextMenus } return result diff --git a/v2/test/kitchensink/contextmenus.go b/v2/test/kitchensink/contextmenus.go index 82662a156..68b25e74b 100644 --- a/v2/test/kitchensink/contextmenus.go +++ b/v2/test/kitchensink/contextmenus.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "sync" "github.com/wailsapp/wails/v2" @@ -9,9 +10,11 @@ import ( // ContextMenu struct type ContextMenu struct { - runtime *wails.Runtime - counter int - lock sync.Mutex + runtime *wails.Runtime + counter int + lock sync.Mutex + testContextMenu *menu.ContextMenu + clickedMenu *menu.MenuItem } // WailsInit is called at application startup @@ -22,10 +25,19 @@ func (c *ContextMenu) WailsInit(runtime *wails.Runtime) error { return nil } -func createContextMenus() *menu.ContextMenus { - result := menu.NewContextMenus() - result.AddMenu("test", menu.NewMenuFromItems( - menu.Text("Clicked 0 times", nil, nil), +// Setup Menu Listeners +func (c *ContextMenu) updateContextMenu(_ *menu.CallbackData) { + c.lock.Lock() + c.counter++ + c.clickedMenu.Label = fmt.Sprintf("Clicked %d times", c.counter) + c.lock.Unlock() + c.runtime.Menu.UpdateContextMenu(c.testContextMenu) +} + +func (c *ContextMenu) createContextMenus() []*menu.ContextMenu { + c.clickedMenu = menu.Text("Clicked 0 times", nil, c.updateContextMenu) + c.testContextMenu = menu.NewContextMenu("test", menu.NewMenuFromItems( + c.clickedMenu, menu.Separator(), menu.Checkbox("I am a checkbox", false, nil, nil), menu.Separator(), @@ -37,5 +49,7 @@ func createContextMenus() *menu.ContextMenus { menu.Text("Hello", nil, nil), )), )) - return result + return []*menu.ContextMenu{ + c.testContextMenu, + } } diff --git a/v2/test/kitchensink/main.go b/v2/test/kitchensink/main.go index adf6d6a66..553937383 100644 --- a/v2/test/kitchensink/main.go +++ b/v2/test/kitchensink/main.go @@ -12,6 +12,7 @@ func main() { Menu := &Menu{} Tray := &Tray{} + ContextMenu := &ContextMenu{} // Create application with options app, err := wails.CreateAppWithOptions(&options.App{ @@ -23,7 +24,7 @@ func main() { //Tray: menu.NewMenuFromItems(menu.AppMenu()), //Menu: menu.NewMenuFromItems(menu.AppMenu()), //StartHidden: true, - ContextMenus: createContextMenus(), + ContextMenus: ContextMenu.createContextMenus(), Mac: &mac.Options{ WebviewIsTransparent: true, WindowBackgroundIsTranslucent: true, @@ -47,7 +48,7 @@ func main() { app.Bind(&Window{}) app.Bind(Menu) app.Bind(Tray) - app.Bind(&ContextMenu{}) + app.Bind(ContextMenu) err = app.Run() if err != nil {