Saving NSStatusBarButton highlighted while displaying popover

Almost all NSStatusItem are deprecated for 10.10, and the behavior of the underlying NSStatusBarButton seems confusing.

I am currently working on a menu application. When the user clicks on the menu bar icon for the application, the method in my application’s application is called through the target action, which displays NSPopover (or closes it, if it is already visible) with some information.

Usually, if you associate, say, NSMenu with NSStatusItem when the user clicks on the menu bar icon, that icon remains blue until the menu is closed. Similarly, clicking on the system volume icon pushes the slider and highlights the blue icon until the view containing the slider disappears.

However, since I open NSPopover, the system instead highlights the icon in blue on the mouse down, and then returns it to the normal position on the mouse up after calling the method. This means that I cannot do anything in this loop to save the selection. I want the icon to continue to stand out with the mouse and return only to its normal state when I say (for example, when I close my popover.)

I do not know how to do that. I tried using

 [self.statusItem.button setHighlighted: YES]; //or [self.statusItem.button highlight: YES]; 

when I get a mouse up event in my application’s dellet and open a popover. The problem is that the system still has this, it seems, selected this frame / loop from an earlier mouse and right after I set it to be selected, it sets it to unlit because of the mouse. I can get around this by encapsulating it in a method and starting the method with a timer or a delayed selector in a second. This allows me to save the icon, but introduces a flicker; the icon is automatically highlighted as the mouse goes down, as the mouse rises, it highlights it for the frame, then my method emphasizes it again.

I also suggested that I could use the deprecated setHighlightMode: and set it to NO to prevent the icon from automatically highlighting when clicked, and then use setHighlighted: / highlighted: set it manually, but that won't work either. In the same way, I thought it might work:

  NSButtonCell* cell = (NSButtonCell*)self.statusItem.button.cell; cell.highlightsBy = NSNoCellMask; 

But regardless of the click, it automatically selects the icon and deactivates it when you click the mouse immediately after calling my method.

Basically:

  • The unwanted behavior of the NSStatusBarButton automatic backlight prevents manual adjustment of the backlight state unless I manually delay it to introduce a short flicker.
  • The only thing that seems to successfully disable this automatic behavior is the deprecated setHighlightMode: but this seems to prevent all selection, manual or not.
  • The only job seems to be to add a subview to NSButtonCell, add an event listener for the mouse, and then set the add-on's highlight state to match here: NSStatusBarButton would be highlighted but I would have thought that there would be an easy way to just turn off automatic selection at all.

tl; dr: Is there a way for me to easily get full control over when and when the menu icon will not be highlighted so that I can naturally highlight it while my NSPopover is displayed?

+5
source share
1 answer

I decided to solve this without setting the NSStatusItem action selector property. Instead, I used NSEvent addLocalMonitorForEventsMatchingMask:handler: In the handler block, I check to see if event.locationInWindow in my .bounds status element. If so, I am sending a message that .action will have manually and then will return nil to prevent the event from being sent. If it is not within the borders of the status icon, I return event to make it pass normally. In my click processing method, I use [self.statusItem.button highlight: YES/NO] when my popover is displayed / closed.

TL DR:

In applicationDidFinishLaunching:

 __block AppDelegate* appDelegate = self; [NSEvent addLocalMonitorForEventsMatchingMask: NSEventMaskFromType(NSLeftMouseDown) handler:^NSEvent* (NSEvent* event){ if (NSPointInRect(event.locationInWindow, appDelegate.statusItem.button.bounds)){ [appDelegate clickedMenuBarIcon: event]; return nil; } return event; }]; 

In clickedMenuBarIcon: I can set the selection state. Since I returned nil to the handler block, this prevented the event from being transmitted, so automatic highlighting never occurs, and I can do it manually.


If there are any errors related to this, I will be grateful for any advice.

+7
source

All Articles