I'm developing a small menubar application and I want to display the settings window when the corresponding NSMenuItem is pressed.
I currently have the following IBAction assigned to the menu item:
#IBAction func settingsButtonPressed(sender: NSMenuItem) {
settingsView.makeKeyAndOrderFront(sender)
}
This displays the window, but doesn't push it into focus, so it's displayed behind the currently active window, which is not the behaviour I'm looking for.
I had a suspicion that this might have been due to the fact that the Application is agent target property is set to YES, but this actually has no effect on the outcome.
Could there be anything to be done with the window in the XIB file?
Probably your app is not the active app. It should work to call [NSApp activateIgnoringOtherApps:YES] in addition to making the window key and ordering it front.
Related
This is the set up of my ViewControllers
If i run the app and i move from one view controller to the other, the "Quit appName" menu item does not work, views are presented as sheets..
Why is the Quit function the only one not being triggered when moved away from the initial VC, but other menu items(e.g Minimize) work fine?
Any how can i fix the issue?
Ok i found the solution. In every class of ViewVontroller that is presented i had to insert:
override func viewDidAppear() {
self.view.window!.preventsApplicationTerminationWhenModal = false
}
Apple Doc: "Usually, application termination is prevented when a modal window or sheet is open, without consulting the application delegate. Some windows may wish not to prevent termination, however. Setting this property to NO overrides the default behavior and allows termination to proceed even if the window is open, either through the sudden termination path if enabled, or after consulting the application delegate."
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
I have a custom NSBorderlessWindowMask window in my application that I show when user taps a certain hot key.
This window has a `NSTextField, that has to become first responder when the window shows up.
This window is not a main window, but it can take focus from the main window.
This what I do to show it and make it key:
[self.myCustomWindow makeKeyAndOrderFront:sender];
and then to set the first responder
[self.myTextField becomeFirstResponder];
Everything works as expected when the application is a frontmost application,
but if it's not, the window appears, but doesn't become key and i have to click it to become active.
I override in my CustomWindow class:
- (BOOL)canBecomeKeyWindow {
return YES;
}
What might be the problem?
Thanks!
According to the Cocoa Event Handling Guide, only the frontmost application can have main and key window status:
When an application is displaying both a main window and a key window,
the responder chains of both windows can be involved in an action
message. As explained in “Window Layering and Types of Windows”, the
main window is the frontmost document or application window. Often
main windows also have key status, meaning they are the current focus
of user input. But a main window can have a secondary window or panel
associated with it, such as the Find panel or a Info window showing
details of a selection in the document window. When this secondary
window is the focus of user input, then it is the key window.
I don't see any way around this.
EDIT: Also from the Window Programming Guide:
Since the key window belongs to the active application, its
highlighted title bar has the secondary effect of helping to show
which application is currently active. The key window is the most
prominently marked window in the active application, making it “key”
in a second sense: it’s the main focus of the user’s attention on the
screen.
I have an LSUIElement application that needs to keep it's status as an LSUIElement (it cannot have a dock icon) this application is launched and handled by a plugin.
When I change the app so it is a "Regular" app (without LSUIElement), [NSApp activateIgnoringOtherApps:YES] works perfectly. However when I make it an LSUIElement it shows the window, but the window is stuck behind safari (where the plugin is running) but on top of everything else. I am calling -[NSWindow makeKeyAndOrderFront:self]; but that doesn't make any difference.
To be clear the "plugin" side is irrelevant as the plugin and application are two separate processes. The plugin sends an event (over a mach port) to the application which calls some code to open the window and bring it to focus. The problem is the code to bring it to focus only works when it's not an LSUIElement application.
I've exhaustively searched for an existing call to make this work, I'm open to suggestions on how to fake a mouse click, or even run some applescript to make this work, maybe there's an undocumented method of doing this.
The Apple docs for LSUIElement state "The application does not appear in the Dock and does not have a menu bar, but it may be activated programmatically" but I cannot find the magic that enables this.
You need to activate your app first:
[NSApp activateIgnoringOtherApps:YES];
and then make your window become key window:
[NSWindow makeKeyAndOrderFront:nil];
This works in my project.
The following approach works for me in an app with "LSUIElement" set to "1", even if the entire application is using Cocoa:
ProcessSerialNumber psn;
if (noErr == GetCurrentProcess(&psn))
{
(OSStatus)SetFrontProcess(&psn);
}
(This is part of the Carbon API.)
I have an NSWindow that I defined in interface builder. I want to make it so that when the user clicks a button, it opens a new instance that NSWindow. Do I have to subclass NSWindow or something?
If you created the window in IB and it's in your main nib file, you cannot create a "new instance" each time you press a button. When you create an object in the nib file, an instance is actually created by IB and then archived into the nib file, so you get that instance. Assuming your window is wired to a variable named auxWindow on the same object that responds to your button click, and the action message is named buttonClick, you could do something like this to show it:
-(IBAction)buttonClick:(id)sender {
if(! [auxWindow isVisible] )
[auxWindow makeKeyAndOrderFront:sender];
}
This will cause the aux window that you defined in IB to appear on the screen and become the key window (and foremost window in the application). Please note, however, that if you intend to reuse this window, you must uncheck the box in the IB Inspector that says Release on Close, otherwise you will get an access violation the next time you click the button.
This is a simple answer to your basic question, but window programming can be quite complicated and is usually very specific (for instance, do you really want a panel for what you're doing?)... so I strongly suggest that you read the Window Programming Guide for more information on this topic, and then ask very specific questions here when you get stuck.
Put the window in its own nib file, then load the nib file each time. You should use NSWindowController for loading the nib, like NSDocument does.