From 3192026e6dfd2f2c100368b06832263942924372 Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Tue, 6 Jul 2021 21:07:35 +1000 Subject: [PATCH] [windows] Support updating application menu --- .../ffenestri/ffenestri_client_windows.go | 4 +- v2/internal/ffenestri/ffenestri_windows.go | 38 ++++++++++++++++++- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/v2/internal/ffenestri/ffenestri_client_windows.go b/v2/internal/ffenestri/ffenestri_client_windows.go index 5316fe61c..ff668ad1a 100644 --- a/v2/internal/ffenestri/ffenestri_client_windows.go +++ b/v2/internal/ffenestri/ffenestri_client_windows.go @@ -284,8 +284,8 @@ func (c *Client) DarkModeEnabled(callbackID string) { } // SetApplicationMenu sets the application menu -func (c *Client) SetApplicationMenu(applicationMenuJSON string) { - C.SetApplicationMenu(c.app.app, c.app.string2CString(applicationMenuJSON)) +func (c *Client) SetApplicationMenu(_ string) { + c.updateApplicationMenu() } // SetTrayMenu sets the tray menu diff --git a/v2/internal/ffenestri/ffenestri_windows.go b/v2/internal/ffenestri/ffenestri_windows.go index c2701986d..df08f3b7b 100644 --- a/v2/internal/ffenestri/ffenestri_windows.go +++ b/v2/internal/ffenestri/ffenestri_windows.go @@ -27,6 +27,7 @@ var ( // DLL stuff user32 = windows.NewLazySystemDLL("User32.dll") win32CreateMenu = user32.NewProc("CreateMenu") + win32DestroyMenu = user32.NewProc("DestroyMenu") win32CreatePopupMenu = user32.NewProc("CreatePopupMenu") win32AppendMenuW = user32.NewProc("AppendMenuW") win32SetMenu = user32.NewProc("SetMenu") @@ -80,6 +81,7 @@ type menuCacheEntry struct { item *menumanager.ProcessedMenuItem } +var menubar uintptr var menuCache = map[uint32]menuCacheEntry{} var menuCacheLock sync.RWMutex @@ -150,6 +152,13 @@ func (a *Application) processPlatformSettings() error { return nil } +func (c *Client) updateApplicationMenu() { + applicationMenu = c.app.menuManager.GetProcessedApplicationMenu() + radioGroupCache = map[uint32]*radioGroupCacheEntry{} + menuCache = map[uint32]menuCacheEntry{} + createApplicationMenu(uintptr(C.GetWindowHandle(c.app.app))) +} + func createMenu() (uintptr, error) { res, _, err := win32CreateMenu.Call() if res == 0 { @@ -158,6 +167,14 @@ func createMenu() (uintptr, error) { return res, nil } +func destroyMenu(menu uintptr) error { + res, _, err := win32CreateMenu.Call(menu) + if res == 0 { + return err + } + return nil +} + func createPopupMenu() (uintptr, error) { res, _, err := win32CreatePopupMenu.Call() if res == 0 { @@ -220,6 +237,13 @@ func mustAtoi(input string) int { return result } +/* +Application Menu +---------------- +There's only 1 application menu and this is where we create it. This method +is called from C after the window is created and the WM_CREATE message has +been sent. +*/ //export createApplicationMenu func createApplicationMenu(hwnd uintptr) { if applicationMenu == nil { @@ -241,8 +265,17 @@ func createApplicationMenu(hwnd uintptr) { } } + // Delete current menu if it exists + var err error + if menubar != 0 { + err = destroyMenu(menubar) + if err != nil { + log.Fatal("destroyMenu:", err.Error()) + } + } + // Create top level menu bar - menubar, err := createMenu() + menubar, err = createMenu() if err != nil { log.Fatal("createMenu:", err.Error()) } @@ -269,6 +302,9 @@ func mustSelectRadioItem(id uint32, parent uintptr) { } } +/* +This method is called by C when a menu item is pressed +*/ //export menuClicked func menuClicked(id uint32) {