diff --git a/systray_windows.go b/systray_windows.go index e40874a..855b480 100644 --- a/systray_windows.go +++ b/systray_windows.go @@ -21,8 +21,8 @@ var ( webView *walk.WebView notifyIcon *walk.NotifyIcon - actions = make(map[int32]*walk.Action) - nextActionId int32 + actions = make(map[int32]*walk.Action) + menus = make(map[int32]*walk.Menu) okayToClose int32 ) @@ -149,11 +149,39 @@ func ShowAppWindow(url string) { mainWindow.SetVisible(true) } -func addOrUpdateMenuItem(item *MenuItem) { +func getOrCreateMenu(item *MenuItem) *walk.Menu { + if item == nil { + return notifyIcon.ContextMenu() + } + menu := menus[item.id] + if menu != nil { + return menu + } + menu, err := walk.NewMenu() + if err != nil { + fail("Unable to create new menu", err) + } + menus[item.id] = menu + action := actions[item.id] + // If we already have an action in array, it means an action is already created (as a simple action) + // Get parent menu to remove it and create a menu entry instead + if action != nil { + parent := getOrCreateMenu(item.parent) + parent.Actions().Remove(action) + actions[item.id] = nil + updateAction(item, getOrCreateAction(item, menu)) + } + return menu +} + +func getOrCreateAction(item *MenuItem, menu *walk.Menu) *walk.Action { action := actions[item.id] if action == nil { - item.id = nextActionId - action = walk.NewAction() + if menu != nil { + action = walk.NewMenuAction(menu) + } else { + action = walk.NewAction() + } action.Triggered().Attach(func() { select { case item.ClickedCh <- struct{}{}: @@ -162,12 +190,15 @@ func addOrUpdateMenuItem(item *MenuItem) { // no listener, ignore } }) - if err := notifyIcon.ContextMenu().Actions().Add(action); err != nil { + if err := getOrCreateMenu(item.parent).Actions().Add(action); err != nil { fail("Unable to add menu item to systray", err) } actions[item.id] = action - atomic.AddInt32(&nextActionId, 1) } + return action +} + +func updateAction(item *MenuItem, action *walk.Action) { err := action.SetText(item.title) if err != nil { fail("Unable to set menu item text", err) @@ -180,7 +211,10 @@ func addOrUpdateMenuItem(item *MenuItem) { if err != nil { fail("Unable to set menu item enabled", err) } - // TODO: add support for sub-menus +} + +func addOrUpdateMenuItem(item *MenuItem) { + updateAction(item, getOrCreateAction(item, nil)) } // SetIcon sets the icon of a menu item. Only works on macOS and Windows.