5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-04 02:39:30 +08:00

Support changing tray icon at runtime

Support both icon & text in tray
This commit is contained in:
Lea Anthony 2020-12-24 10:05:55 +11:00
parent 8625e99625
commit f0c932713b
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
12 changed files with 67 additions and 40 deletions

View File

@ -36,5 +36,6 @@ 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);
extern void UpdateTrayIcon(void *app, const char *label);
#endif

View File

@ -188,10 +188,15 @@ 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) UpdateTrayIcon(name string) {
C.UpdateTrayIcon(c.app.app, c.app.string2CString(name))
}
func (c *Client) UpdateContextMenus(contextMenus *menu.ContextMenus) {
// Guard against nil contextMenus

View File

@ -78,6 +78,14 @@
#define NSEventTypeRightMouseDown 3
#define NSEventTypeRightMouseUp 4
#define NSNoImage 0
#define NSImageOnly 1
#define NSImageLeft 2
#define NSImageRight 3
#define NSImageBelow 4
#define NSImageAbove 5
#define NSImageOverlaps 6
// References to assets
extern const unsigned char *assets[];
@ -219,9 +227,9 @@ struct Application {
// Tray
const char *trayMenuAsJSON;
const char *trayType;
const char *trayLabel;
const char *trayIconName;
int trayIconPosition;
JsonNode *processedTrayMenu;
id statusItem;
@ -823,9 +831,9 @@ void* NewApplication(const char *title, int width, int height, int resizable, in
// Tray
result->trayMenuAsJSON = NULL;
result->trayType = NULL;
result->trayLabel = NULL;
result->trayIconName = NULL;
result->trayIconPosition = NSImageLeft; // Left of the text by default
result->processedTrayMenu = NULL;
result->statusItem = NULL;
@ -1344,9 +1352,8 @@ 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, const char *trayType, const char *trayLabel, const char *trayIconName) {
void SetTray(struct Application *app, const char *trayMenuAsJSON, const char *trayLabel, const char *trayIconName) {
app->trayMenuAsJSON = trayMenuAsJSON;
app->trayType = trayType;
app->trayLabel = trayLabel;
app->trayIconName = trayIconName;
}
@ -2267,6 +2274,13 @@ void UpdateTrayLabel(struct Application *app, const char *label) {
msg(statusBarButton, s("setTitle:"), str(label));
}
void UpdateTrayIcon(struct Application *app, const char *name) {
id trayImage = hashmap_get(&trayIconCache, name, strlen(name));
id statusBarButton = msg(app->statusItem, s("button"));
msg(statusBarButton, s("setImagePosition:"), 2);
msg(statusBarButton, s("setImage:"), trayImage);
}
void processTrayIconData(struct Application *app) {
unsigned int count = 0;
@ -2312,18 +2326,16 @@ void parseTrayData(struct Application *app) {
statusItem = msg(statusBar, s("statusItemWithLength:"), NSVariableStatusItemLength);
app->statusItem = statusItem;
msg(statusItem, s("retain"));
id statusBarButton = msg(statusItem, s("button"));
id statusBarButton = msg(app->statusItem, s("button"));
msg(statusBarButton, s("setImagePosition:"), app->trayIconPosition);
if( STREQ(app->trayType, "icon") ) {
// Get the icon
if ( app->trayIconName != NULL ) {
id trayImage = hashmap_get(&trayIconCache, app->trayIconName, strlen(app->trayIconName));
msg(statusBarButton, s("setImage:"), trayImage);
}
// Get the icon
if ( app->trayIconName != NULL ) {
UpdateTrayIcon(app, app->trayIconName);
}
if( STREQ(app->trayType, "label") ) {
// If we have a tray icon
msg(statusBarButton, s("setTitle:"), str(app->trayLabel));
if( app->trayLabel != NULL ) {
UpdateTrayLabel(app, app->trayLabel);
}
}
@ -2365,12 +2377,6 @@ void parseTrayData(struct Application *app) {
processRadioGroup(radioGroup, &menuItemMapForTrayMenu, &radioGroupMapForTrayMenu);
}
// msg(statusBarButton, s("setImage:"),
// msg(c("NSImage"), s("imageNamed:"),
// msg(c("NSString"), s("stringWithUTF8String:"), tray->icon)));
msg(statusItem, s("setMenu:"), traymenu);
}

View File

@ -99,7 +99,7 @@ func (a *Application) processPlatformSettings() error {
if err != nil {
return err
}
C.SetTray(a.app, a.string2CString(string(trayMenuJSON)), a.string2CString(string(tray.Type)), a.string2CString(tray.Label), a.string2CString(tray.Icon))
C.SetTray(a.app, a.string2CString(string(trayMenuJSON)), a.string2CString(tray.Label), a.string2CString(tray.Icon))
}
// Process context menus

View File

@ -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 *, const char *, const char *, const char *);
extern void SetTray(void *, const char *, const char *, const char *);
extern void SetContextMenus(void *, const char *);
#endif

View File

@ -34,6 +34,7 @@ type Client interface {
UpdateMenu(menu *menu.Menu)
UpdateTray(menu *menu.Menu)
UpdateTrayLabel(label string)
UpdateTrayIcon(name string)
UpdateContextMenus(contextMenus *menu.ContextMenus)
}

View File

@ -523,6 +523,21 @@ func (d *Dispatcher) processTrayMessage(result *servicebus.Message) {
client.frontend.UpdateTrayLabel(updatedLabel)
}
case "seticon":
iconname, ok := result.Data().(string)
if !ok {
d.logger.Error("Invalid data for 'trayfrontend:seticon' : %#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.UpdateTrayIcon(iconname)
}
default:
d.logger.Error("Unknown menufrontend command: %s", command)
}

View File

@ -13,6 +13,7 @@ type Tray interface {
GetByID(menuID string) *menu.MenuItem
RemoveByID(id string) bool
SetLabel(label string)
SetIcon(name string)
}
type trayRuntime struct {
@ -43,6 +44,9 @@ func (t *trayRuntime) Update() {
func (t *trayRuntime) SetLabel(label string) {
t.bus.Publish("tray:setlabel", label)
}
func (t *trayRuntime) SetIcon(name string) {
t.bus.Publish("tray:seticon", name)
}
func (t *trayRuntime) GetByID(menuID string) *menu.MenuItem {
return t.trayMenu.Menu.GetByID(menuID)

View File

@ -126,6 +126,14 @@ func (t *Tray) Start() error {
// Notify frontend of menu change
t.bus.Publish("trayfrontend:setlabel", updatedLabel)
// Make sure we catch any icon updates
case "seticon":
iconname := menuMessage.Data().(string)
t.trayMenu.Label = iconname
// Notify frontend of menu change
t.bus.Publish("trayfrontend:seticon", iconname)
default:
t.logger.Error("unknown tray message: %+v", menuMessage)
}

View File

@ -1,18 +1,8 @@
package menu
type TrayType string
const (
TrayIcon TrayType = "icon"
TrayLabel TrayType = "label"
)
// TrayOptions are the options
type TrayOptions struct {
// Type is the type of tray item we want
Type TrayType
// Label is what is displayed initially when the type is TrayLabel
// Label is the text we wish to display in the tray
Label string
// Icon is the name of the tray icon we wish to display.

View File

@ -29,8 +29,6 @@ func main() {
TitleBar: mac.TitleBarHiddenInset(),
Menu: createApplicationMenu(),
Tray: &menu.TrayOptions{
//Type: menu.TrayLabel,
Type: menu.TrayIcon,
Label: "Hi Go BitBar!",
Icon: "light",
Menu: createApplicationTray(),

View File

@ -44,19 +44,18 @@ func (t *Tray) WailsInit(runtime *wails.Runtime) error {
t.runtime.Window.Unminimise()
})
// Auto switch between light / dark tray icons
t.runtime.Events.OnThemeChange(func(darkMode bool) {
if darkMode {
//t.runtime.Tray.SetIcon("light")
println("\n\n\n\n\n\nSET ICON TO LIGHT\n\n\n\n")
t.runtime.Tray.SetIcon("light")
return
}
//t.runtime.SetIcon("dark")
println("\n\n\n\n\n\nSET ICON TO DARK\n\n\n\n\n")
t.runtime.Tray.SetIcon("dark")
})
// Start ticker
//go t.startTicker()
go t.startTicker()
return nil
}