2

i have a simple cocoa coredata statusbar application with Xcode 4.6.2. This is the situation:

Renamed MainMenu.xib to PreferencesWindow.xib, deleted the mainmenu, created a simple and working coredata function with arraycontrollers and bindings in the window. I have created a new file->User Interface->Main Menu and named it StatusBarMenu.xib. Added a simple menu to it and removed the main menu. Created new file->objective-c class->subclass of NSObject and named it StatusBarController. Here's the code for the interface:

@property IBOutlet NSMenu *statusMenu;
@property NSStatusItem *statusItem;
@property [some items for statusbar image]

implementation:

@synthesize [everything]
-(void)awakeFromNib{
    statusItem = [[NSStatusBar systemStatusBar]statusItemWithLength:NSVariableStatusItemLength];
    [some string, path and stuff for the images]
    statusItem.menu = statusMenu;
    statusItem.toolTip = @"";
    statusItem.highlightMode = YES;
}

Then I've created another new file->objective-c class->subclass of NSWindowController, named it PreferencesWindowController and leave it as it is. Then a new file->objective-c class->subclass of NSObjects named PreferencesAppController. Here's the code for .h:

@property (assign) IBOutlet NSWindow *mainWindow;
@property (retain) PreferencesWindowController *prefController;
-(IBAction)showPreferences:(id)sender;

.m code:

@synthesize [everything];
-(IBAction)showPreferences:(id)sender{
    if(!self.prefController)
        self.prefController = [[PreferencesWindowController alloc] initWithWindowNibName:@"PreferencesWindow"];

    [self.prefController showWindow:sender];
}

In the AppDelegate files there's only code for coredata, nothing added. Then in the PreferencesWindow.xib I've added NSObject (the blue cube) for PreferencesAppController with some bindings: Outlets-> mainWindow binded to the window with the simple coredata function. AppDelegate has the window outlet binded to the same window, then Referencing Outlets->File's Owner delegate, some saveaction and managedobjectcontext. In the StatusBarMenu.xib i've created a StatusBarController object and binded it to the menu (outlets->statusMenu), created another blue object called PreferencesAppController with Received Actions->showPreferences binded to a menu item.

Then i run the program and everything goes fine: an icon appears in the status bar, the dropdown menu works, if i click on "preferences..." the preferences window appears but... it isn't focused! It's on top of the other windows but i have to click to make it focused. The coredata saving functions works fine except that i have to manually save with a button, quitting the application from the statusbar menu does not save, but this is a marginal issue.

Why isn't the window focused?

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Val K.
  • 113
  • 1
  • 10
  • This probably isn't it, but make sure you're using LSUIElement rather than LSBackgroundOnly in the Info.plist. Background-only apps aren't supposed to show UI. – Peter Hosey Jun 13 '13 at 05:10
  • By the way, please don't delete the main menu. The text-editing (e.g., Cut, Copy, and Paste), window-closing, application-quitting, etc. menu items are in there. Standard shortcuts like ⌘Z, ⌘C, ⌘W, and ⌘Q won't work if you delete it. – Peter Hosey Jun 13 '13 at 05:11
  • Yes, in info.plist i've added the "Application is agent (UIElement)" to act as a statusbar app. It was intentional to prevent the use of the shortcuts. There's only a quit menu item in the statusbar. However if the app runs in the background, will the shortcuts work only if the preference panel is selected? – Val K. Jun 13 '13 at 08:24
  • Yes, if your panel is key or any other window/panel you show from your app is key, your menus (in your main menu) are then used for key-combo resolution even if you do not own the menu bar. This includes dialog boxes, so if your app needs to, say, ask for a password for some service, the user probably would like to be able to paste their password in. – Peter Hosey Jun 13 '13 at 08:26
  • very useful information, thank you – Val K. Jun 13 '13 at 08:33

1 Answers1

2

I'm assuming from your description of your app as a “statusbar application” that it is meant to run in the background and not show up in the Dock.

This means that your application is not the active application. The user clicking on your status item and choosing an item from its menu does not change that.

When an application that is not the active application opens a window, that window does not take focus (since this ordinarily would amount to stealing focus from whatever the user has been doing in the application that is active).

So, you need to activate your application.

Community
  • 1
  • 1
Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
  • [NSApp activateIgnoringOtherApps:YES] doesn't work. However, the OrderFrontStandardAboutPanel is working good: on top of everything as the preference window, but finally focused. – Val K. Jun 13 '13 at 08:29
  • a little note: the about panel worked good before i tried with activateIgnoringOtherApps: it simply doesn't affect any change to the behaviour of the app. – Val K. Jun 13 '13 at 09:25
  • PROBLEM SOLVED! I put the [NSApp activateIgnoringOtherApps:YES] in the wrong controller (the statusbarcontroller instead of preferencesappcontroller). Now it just works fine! Thanks a lot. Now i only have to understand how to automatically save in coredata the content of the preferences windows instead of manually press the button. – Val K. Jun 13 '13 at 12:09
  • Is there any way to force the `NSWindow` to show its menu when it appears? Right now I have to switch apps back and forth to make the menu show. – Oscar Swanros Nov 04 '16 at 23:18