Im pretty sure the answer must be quite easy, but for some reason I can't get it to work!
I have a window, and this code:
[someWindow setHidesOnDeactivate:YES];
I have a status item, and the following code
- (void)openWindow{
if ([someWindow isVisible]) {
NSLog(#"CLOSING");
[lyricWindow close];
}else {
[someWindow makeKeyAndOrderFront:nil];
NSLog(#"SHOWING");
}
}
This worked when I closed the window and wanted to open it again. Now that I've implemented the hides of deactivate I am lost as to what I need to do! I've tried all sorts of things... I want the window to show again and the window to become active when I click the status item! I think thats my problem.
How can I make the window active when I click on a status item?
I get the following in the log:
CLOSING SHOWING CLOSING SHOWING
Closing is first regardless if the window is hidden or not, which is rather intriguing, because id guess isVisible would return false if the window has been hidden. Anyhow, I get no window. How can I unhide the window?
Thanks!
I had this same problem where I couldn't get a window to re-show after it was hidden from deactivation. In my case, I was showing a NSPanel (subclass of NSWindow) when a NSStatusItem was pressed.
The following code finally got my NSPanel to re-show up:
[NSApp arrangeInFront:sender];
[myWindow makeKeyAndOrderFront:sender];
[NSApp activateIgnoringOtherApps:YES];
I'm pretty sure 'activateIgnoringOtherApps' is the key here. For me, it's not ideal because it takes focus away from the user's current application.
Related
I'm building a Mac app that only sits in the menu bar with no dock item and no key window and no main menu (it's LSUIElement in the info.plist is set to YES). When I first launch the app, applicationDidBecomeActive: is called, as I expect. However, once another app gains focus, applicationDidBecomeActive: is never called again.
This prevents a text field I have within my app from becoming the first responder. When I first open the app, the text field is editable:
But after another app comes to the foreground, the text field is not editable:
What I've tried:
When the menu is opened, menuWillOpen: is called on the NSMenu's delegate. I've tried placing the following with no success:
[NSApp unhide];
[NSApp arrangeInFront:self];
[NSApp activateIgnoringOtherApps:YES];
[NSApp requestUserAttention:NSCriticalRequest];
[[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
[[NSRunningApplication currentApplication] unhide];
I think the issue is probably related to not having any windows to bring to the front. I feel like I'm grasping at straws here. Any help would be greatly appreciated.
I think the issue is with that how the runloop operates when a NSMenu is open, so you should try activating the app before you display the menu. If you're having the NSStatusItem display it, I'd suggest doing it yourself like this:
- (void)toggleMenu:(id)sender
{
// App might already be active
if ([NSApp isActive]) {
[self.statusItem popUpStatusItemMenu:self.menu];
} else {
[NSApp activateIgnoringOtherApps:YES];
}
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
[self.statusItem popUpStatusItemMenu:self.menu];
}
That should work, but I think though in general you'll have better luck with an actual window instead of a menu.
You probably need to allow your input to -becomeFirstResponder, maybe by overriding -canBecomeFirstResponder or by calling the become method yourself.
You'd likely have to implement/call these methods for whatever view is housing your text input, or maybe tell your input view to become the first responder.
Either way, it smells like a responder chain issue.
Try calling -makeFirstResponder: on your window. NSWindow is usually the start of the NSResponder chain.
- (void)menuWillOpen:(NSMenu *)menu {
[[NSApp mainWindow] makeFirstResponder:yourTextInputField];
}
I'm assuming your text field already accepts first responder since you said your app launches initially with it as the first responder. If not, make sure your text field overrides -acceptsFirstResponder: to return YES
- (BOOL)acceptsFirstResponder {
return YES;
}
Edit: Ah, see that you don't have a key window. It looks like NSMenu actually has a window associated with it though, and it's safe to call -makeFirstResponder:. Some discussion here suggests overriding -viewDidMoveToWindow: on your view containing your text field in the NSMenu like so:
- (void)viewDidMoveToWindow {
[super viewDidMoveToWindow];
[[self window] makeFirstResponder:yourTextInputField];
}
I'm trying to display a modal dialog on top of my app but it's blocking my main app window when it closes. Here's my code:
TutorialWindowController* pTutorialController = [[TutorialWindowController alloc] initWithWindowNibName:#"TutorialWindow"];
NSWindow* pTutorialWindow = [pTutorialController window];
DDLogInfo(#"Tutorial window opening...");
[NSApp runModalForWindow: pTutorialWindow];
DDLogInfo(#"Tutorial window closed!"); // CODE NEVER GETS HERE
[NSApp endSheet: pTutorialWindow];
[pTutorialWindow orderOut: self];
In the modal dialog, my Close button runs this:
- (IBAction)closeButtonPressed:(id)sender {
[NSApp stopModal];
}
The modal dialog displays fine. However, when I click the Close button, the dialog disappears and my app's main window isn't responsive. I hear the bonk every time I try clicking. I'm pretty sure this is because the code never continues after runModalForWindow. Same thing happens if I close the modal dialo using the red X.
What am I doing wrong?
After ordering out the tutorial window, try doing a
[window makeKeyAndOrderFront:self];
on your main window.
You should call [pTutorialWindow orderOut:nil] first.
Not sure about the closeButtonPressed handler. But try adding to the delegate:
- (void) windowWillClose:(NSNotification *)notification
{
// ...
// In there, you should verify that you are calling:
[NSApp stopModal]
}
Adding the stopModal call solved the issue for me.
Verify that the Window delegate in the Interface Editor's Connection Inspector is connected to the File's Owner.
I had several modal dialogues working correctly except for one, and the missing connection was the only difference. Making the connection fixed the problem.
I'm running a modal window in my application, which works fine. The problem however seems to be dismissing the window.
While the window closes, it takes at least 20 seconds for the application to continue (I show the modal window at startup), but it will continue instantly if I click on its dock icon.
Here's how I close the modal window:
[NSApp stopModal];
[updaterWindow orderOut:self];
[updaterWindow close];
I've tried various things to get the Application to continue faster, such as manually switching to the main run loop and speaking to the main window directly (asking it to become the key window), which all did not work. Same as before, 20 seconds wait or instant load when clicking on the dock icon.
What can cause something like this? I'm really baffled.
Edit:
My modal window is actually created in a really simple way. I run my window as modal:
[NSApp runModalForWindow:updaterWindow];
When I am done with things, I close it:
[NSApp stopModal];
[updaterWindow orderOut:self];
[updaterWindow close];
The window goes away, but it needs a click to the dock icon or anywhere on the screen for the app to continue.
I'm doing something similar in my app at the moment: I have an IBAction method that calls the modal window:
-(IBAction)showMyModalWindow:(id)sender {
[theModalWindow makeKeyWindow];
NSInteger retVal = [NSApp runModalForWindow:theModalWindow];
[theModalWindow close];
//continue and do somethin according the value in retVal
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
In this case theModalWindow is in it's own nib file has an NSObject in it that deals with the ok and cancel button to dismiss theWindow, by way of example here's the cancel button callback:
-(IBAction)cancelButton:(id)sender
{
[NSApp stopModalWithCode:errAuthorizationCanceled];
}
The last line in showMyModalWindow: method seems to be what's needed in my case by sending the app forward... Hope that's of some use!
Todd.
I'm pretty new to cocoa, so please excuse me for any stupid mistakes I make.
I have a NSStatusItem, which I want to use to open up a menu. However as far as I know and have heard across different forms, without a custom view you are restricted to just a pop down menu. Is this true? And if so how do you make a custom view to do something (e.g. open a window in my case)? Thanks for any help.
No, it is not true. You need to set up the target and action for the status item to call a method which does what you want (opens the window).
// This goes where you set up the status item
NSStatusItem *statusItem; // You need to get this from the status bar
[statusItem setTarget:self];
[statusItem setAction:#selector(openWindow:)];
// This method is called when the status item is clicked
- (void)openWindow:(id)sender {
NSWindow *window = [self window]; // Get the window to open
[window makeKeyAndOrderFront:nil];
}
You may also want to call [NSApp activateIgnoringOtherApps:nil]; to your openWindow: method to ensure that the window you open is not behind some other application's window.
Hey, SO, minor issue: I have an NSWindow I am using to report exceptions that works pretty well. I give the user the option to quit the application or continue running in an uncertain state with a "Continue" button. The "Continue" button is supposed to simply close the window, however it does not work. Here is the code:
- (IBAction) continueOperation:(id)sender
{
[[self window] performClose:self];
}
If the user presses the close X in the upper left corner, the window closes correctly, but the code does not do the trick. Any ideas what I might be doing wrong? Thanks!
Are you sure that [self window] is returning the window that you think it is?