window buttons are greyed when unhide and active the app from status bar

Viewed 207

enter image description here My app has NSStatusBarButton on status bar (where the time, wifi etc) The user can tap to show/hide the app.

to hide :

[[NSApplication sharedApplication] hide:self];
[[NSApplication sharedApplication] deactivate];

to show :

[self.windowController.window makeKeyAndOrderFront:self];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];

The problem is when I show the app, the window buttons (close, maximise ) are flickering their colour, then turn gray. I can see in logs of events the application is active and it responds to mouse scroll.

Only if I activate OTHER app with the mouse and return back to my app, the buttons will be active with there colour (red and green)

More info :
1. the app is created in code (not storyboard) besided the mainMenu.xib.
2. when I tap the image menu status bar to UNHIDE the app, in debug mode=on, the code is break with this error :

"error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=1, address=0x4e47432b2b00). The process has been returned to the state before expression evaluation."

Any ideas where to continue from here ?

2 Answers

Thanks to the help of Asperi, the create sample code to narrow the diffrences, the problem was enabling this override :

-(BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
    return YES;
}
  1. disable it and I could unhide/hide the app with the 3 buttons being activated with their color.

  2. also this [window orderOut] was important call.

Here is AppDelegate from project created from scratch. XIB file was not modified. All manipulations with StatusBar is here.

Note: no crash/exception is observed with provided code snapshot

During demo just clicked several times on added X status bar button:

Activate/Deactivate on NSStatusBarButton click

Update: added variant with controller & window created programmatically, nothing except main menu left in XIB... Tested as worked. Xcode 11.2 / macOS 10.15 Catalina

#import "AppDelegate.h"

@interface AppDelegate ()

@property (strong) NSWindowController *controller;
@property (strong) NSStatusItem *statusItem;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    NSWindow *window = [[NSWindow alloc] initWithContentRect:
         NSMakeRect(0, 0, 480, 300) 
         styleMask:(NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable) 
         backing:NSBackingStoreBuffered defer:NO];
    [window setFrameAutosaveName:@"MyWindow"];
    [window setTitle:@"Testing hide-unhide"];

    self.controller = [[NSWindowController alloc] initWithWindow:window];
    [self.controller showWindow:nil];
    [self.controller.window center]; // << for simplicity


    // Insert code here to initialize your application
    NSStatusBar *statusBar = [NSStatusBar systemStatusBar];
    self.statusItem = [statusBar statusItemWithLength:16];

    NSStatusBarButton *button = self.statusItem.button;
    [button setTitle:@"X"];
    [button setTarget:self];
    [button setAction:@selector(hideUnhide:)];
}

- (void)hideUnhide:(id)sender
{
  if([[NSApplication sharedApplication] isHidden])
  {
      [NSApp activateIgnoringOtherApps:true];
      [self.controller.window makeKeyAndOrderFront:nil];
  } else {
      [self.controller.window orderOut:nil];
      if (NSApp.isActive) {
          [NSApp deactivate];
      }
      [NSApp hide:nil];
  }
}

@end

Variant with window created in XIB by project template

#import "AppDelegate.h"

@interface AppDelegate ()

@property (weak) IBOutlet NSWindow *window;
@property (strong) NSStatusItem *statusItem;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Insert code here to initialize your application
    NSStatusBar *statusBar = [NSStatusBar systemStatusBar];
    self.statusItem = [statusBar statusItemWithLength:16];

    NSStatusBarButton *button = self.statusItem.button;
    [button setTitle:@"X"];
    [button setTarget:self];
    [button setAction:@selector(hideUnhide:)];

}

- (void)hideUnhide:(id)sender
{
    [self.window orderOut:nil]; // drops current window state
    // [self.window resignKeyWindow]; // << also works
    if (NSApp.isActive) {
        [NSApp deactivate];
        [NSApp hide:nil];
    } else {

        [NSApp activateIgnoringOtherApps:true];
        [self.window makeKeyAndOrderFront:nil];
    }
}

@end
Related