diff --git a/v3/examples/systray/main.go b/v3/examples/systray/main.go index 9e0a31b18..b35a0b6c4 100644 --- a/v3/examples/systray/main.go +++ b/v3/examples/systray/main.go @@ -67,9 +67,7 @@ func main() { app.Quit() }) - if runtime.GOOS != "darwin" { - systemTray.SetMenu(myMenu) - } + systemTray.SetMenu(myMenu) systemTray.AttachWindow(window).WindowOffset(5) diff --git a/v3/pkg/application/systemtray_darwin.go b/v3/pkg/application/systemtray_darwin.go index a8a5cda66..2d3efecb1 100644 --- a/v3/pkg/application/systemtray_darwin.go +++ b/v3/pkg/application/systemtray_darwin.go @@ -32,8 +32,8 @@ type macosSystemTray struct { type button int const ( - left button = iota - right + leftButtonDown button = 1 + rightButtonDown button = 2 ) // system tray map @@ -44,6 +44,7 @@ func systrayClickCallback(id C.long, buttonID C.int) { // Get the system tray systemTray := systemTrayMap[uint(id)] if systemTray == nil { + println("system tray not found") return } systemTray.processClick(button(buttonID)) @@ -132,7 +133,12 @@ func (s *macosSystemTray) run() { s.menu.Update() // Convert impl to macosMenu object s.nsMenu = (s.menu.impl).(*macosMenu).nsMenu - C.systemTraySetMenu(s.nsStatusItem, s.nsMenu) + // We only set the tray menu if we don't have an attached + // window. If we do, then we manually operate the menu using + // the right mouse button + if s.parent.attachedWindow.Window == nil { + C.systemTraySetMenu(s.nsStatusItem, s.nsMenu) + } } }) @@ -185,13 +191,13 @@ func (s *macosSystemTray) destroy() { func (s *macosSystemTray) processClick(b button) { switch b { - case left: + case leftButtonDown: // Check if we have a callback if s.parent.clickHandler != nil { s.parent.clickHandler() return } - case right: + case rightButtonDown: // Check if we have a callback if s.parent.rightClickHandler != nil { s.parent.rightClickHandler() @@ -200,6 +206,10 @@ func (s *macosSystemTray) processClick(b button) { } // Open the default menu if we have one if s.menu != nil { - C.showMenu(s.nsStatusItem) + if s.parent.attachedWindow.Window != nil { + // If we have an attached window, then we need to hide it + s.parent.attachedWindow.Window.Hide() + } + C.showMenu(s.nsStatusItem, s.nsMenu) } } diff --git a/v3/pkg/application/systemtray_darwin.h b/v3/pkg/application/systemtray_darwin.h index 03c7a2297..66ffb7528 100644 --- a/v3/pkg/application/systemtray_darwin.h +++ b/v3/pkg/application/systemtray_darwin.h @@ -11,6 +11,6 @@ NSImage* imageFromBytes(const unsigned char *bytes, int length); void systemTraySetIcon(void* nsStatusItem, void* nsImage, int position, bool isTemplate); void systemTraySetMenu(void* nsStatusItem, void* nsMenu); void systemTrayDestroy(void* nsStatusItem); -void showMenu(void* nsStatusItem); +void showMenu(void* nsStatusItem, void *nsMenu); void systemTrayGetBounds(void* nsStatusItem, NSRect *rect); int statusBarHeight(); \ No newline at end of file diff --git a/v3/pkg/application/systemtray_darwin.m b/v3/pkg/application/systemtray_darwin.m index 95df42524..df0a32b01 100644 --- a/v3/pkg/application/systemtray_darwin.m +++ b/v3/pkg/application/systemtray_darwin.m @@ -10,15 +10,8 @@ extern void systrayClickCallback(long, int); @implementation StatusItemController - (void)statusItemClicked:(id)sender { - // Get the left or right button NSEvent *event = [NSApp currentEvent]; - if (event.type == NSEventTypeRightMouseUp) { - // Right click - systrayClickCallback(self.id, 1); - } else { - // Left click - systrayClickCallback(self.id, 0); - } + systrayClickCallback(self.id, event.type); } @end @@ -30,6 +23,8 @@ void* systemTrayNew(long id) { NSStatusItem *statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain]; [statusItem setTarget:controller]; [statusItem setAction:@selector(statusItemClicked:)]; + NSButton *button = statusItem.button; + [button sendActionOn:(NSEventMaskLeftMouseDown|NSEventMaskRightMouseDown)]; return (void*)statusItem; } @@ -90,14 +85,23 @@ void systemTrayDestroy(void* nsStatusItem) { }); } -void showMenu(void* nsStatusItem) { +void showMenu(void* nsStatusItem, void *nsMenu) { // Show the menu on the main thread dispatch_async(dispatch_get_main_queue(), ^{ NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - // Check it's not nil - if( statusItem.menu != nil ) { - [statusItem popUpStatusItemMenu:statusItem.menu]; - } + [statusItem popUpStatusItemMenu:(NSMenu *)nsMenu]; + // Post a mouse up event so the statusitem defocuses + NSEvent *event = [NSEvent mouseEventWithType:NSEventTypeLeftMouseUp + location:[NSEvent mouseLocation] + modifierFlags:0 + timestamp:[[NSProcessInfo processInfo] systemUptime] + windowNumber:0 + context:nil + eventNumber:0 + clickCount:1 + pressure:1]; + [NSApp postEvent:event atStart:NO]; + [statusItem.button highlight:NO]; }); }