How can I dismiss NSPopover when not active? - xcode

I have a menu bar app that displays an NSPopover when the status icon is pressed. The problem is that it will only close if you click again on the status icon.
I want the view to close when I click anywhere outside the popover itself.
I tried changing the popovers attributes Behaviour to Transient but the issue persists.
What is the best way I can achieve this?

Use UIPopoverController instead of NSPopover and Present it in the required ViewController using the below method
- (void)presentPopoverFromRect:(CGRect)rect inView:(UIView *)view permittedArrowDirections:(UIPopoverArrowDirection)arrowDirections animated:(BOOL)animated
So if any other view is clicked apart from the popover, it will dismiss automatically.

Related

Performing an action when _statusItem is clicked, with a NSMenu and the window not in focus seems impossible

There are similar questions on SO but this have a twist.
I need to trigger an action when the user clicks on my app icon sitting on the menu bar. The action is to bring its window to the front, or in other words,
[[[NSApplication sharedApplication] keyWindow] makeKeyAndOrderFront:self];
Normally I would do this:
[_statusItem setTarget:self];
[_statusItem setAction:#selector(bringToFront:)];
but this _statusItem has a NSMenu.
If I disable the menu, bringToFront: is triggered.
So I thought, I will implement NSMenuDelegate method menuWillOpen.
- (void)menuWillOpen:(NSMenu *)menu {
[[[NSApplication sharedApplication] keyWindow] makeKeyAndOrderFront:self];
}
But there is a problem. This will work if the app window is the one selected, but suppose the app is running and I select safari. Then, my app's window is not in focus anymore, is behind 2000 Safari windows. Now I click on my app's icon on the menu bar and menuWillOpen will not be triggered.
If I want to bring the window to focus by clicking on the app's icon on the menu bar, having to bring the window to focus to make it work does not make sense.
NSApplication notifications are posted in response to your app gaining/resigning active status. Handle these notifications and enable/disable your status item's menu so that your action gets invoked when your app is in the background.

NSStatusItem app focus

How can my menubar application achieve the same behaviours as 1Password or Dropbox:
clicking their menu bar icons or popovers does not steal focus, e.g. while I am in for example TextEdit and open 1Password/Dropbox, the blinking cursor disappears but the window itself does not go into the background, yet I can type into 1Password's text field.
even though they didn't take focus in the first place, they disappear when I click back into another application
I figured out how mouse over works in the Dropbox popover table view by using an NSTrackingArea with the options MouseEnteredAndExited, AssumeInside, and ActiveAlways.
I am trying to get the same behaviour to work in an NSPopover that opens from an NSStatusItem.
I found a workaround for now. I am able to get the same behaviour by using non-activating NSPanel with a window level kCGPopUpMenuWindowLevelKey and I had to override canBecomeKeyWindow to return true.
Unfortunately I haven't found a way yet to get a NSPopover to behave this way since it's not a subclass of NSWindow.
To set the kind of behavior you are describing you use:
yourPopover.behavior = .transient

How to make action to close NSPopover?

Hi I implemented an NSPopover in one of my apps, but the popover will not close. I'm guessing that it should close once I click something else, but its not. I know that there's a close popover action but that only works for a different button. How can I make it look to see that the popover is open and when it is open to close the popover when I press the same button?
I solved the problem!
First go ahead and click your .xib file.
Where you see the first responder box and files owner - click on the popover.
On the sidebar go to the attributes center
Change the behavior from Application-Defined to Transient and it should work!
That should make the popover disappear once someone has clicked outside the popover.
Another way to close the popover is to have a separate button.
Just add another NSButton and then link it to the popover on the sidebar and set it to Received actions -> perform close:

How do I get a textbox in an NSMenu?

I'm pretty sure i've seen this somewhere (not counting the help menu), and I feel like you could just drag one in under ib in leopard. Not that it matters, but it will either go into a dock menu or a service. Thanks
Try setting an NSTextField as the view of an NSMenuItem.
You can do this in IB by dragging the text field into the nib as a top-level object and setting the menu item's view outlet to point to the field.
Tricky thing you may need to solve in your app: In the IB simulator, at least, pressing return/enter did not dismiss the menu.

Programmatically Removing a Button from a Window in Cocoa OSX

I need to programmatically remove a button from a window in Cocoa but the only method close to this was dealloc in NSObject, but this is not what I want to do. Is there a way to actually delete the button from the window not just deallocate its memory?
Send the removeFromSuperview message to the button instance.
Though perhaps you just want to hide it instead (using setHidden:)?
An NSButton is a subclass of NSControl, which itself is a subclass of NSView.
You should be able to remove the button from it's superview by calling -removeFromSuperView on the button instance.

Resources