4
votes

I have no idea where to even start trying to fix this but maybe someone can point me in the right direction. I have a status item application that shows a popover when clicked, some user interactions produce an NSUserNotification to warn/inform about changes or errors. But when the notification appears it is shown behind the popover, so if they overlay the user can't read what it says.

Is there a way to force the notification to appear in front of the popover? Like order the notification to the front.

Edit: here's a picture showing part of the notification hidden behind the popover after a user gave bad input. I don't really want to hide the popover to show the error notification.

I've tried stuff lake makeKeyAndOrderFront, activateIgnoringOtherApps, the type of stuff you'd use on a window, but none of it applies to an NSUserNotification so it doesn't work.

Edit 2: I should note that to get the popover to appear in front of everything when called I use activateIgnoringOtherApps and becomeFirstResponder on the popover, but even getting rid of that still shows the notification behind the popover.

Edit 3: The popover is shown relative to a status item in the status bar using [[self popover] showRelativeToRect:statusItem.view.bounds ofView:statusItem.view preferredEdge:NSMaxYEdge]; When clicked, the status item calls a method that does this:

- (void)openPopover:(id)sender {
if (![_popover isShown] | (_popoverIsClosing)) {
    [_preferencesWindow close];
    [NSApp activateIgnoringOtherApps:YES];
    [_popover becomeFirstResponder];
    [statusItemView setHighlighted:YES];
    [[self popover] showRelativeToRect:statusItem.view.bounds ofView:statusItem.view preferredEdge:NSMaxYEdge];
    [self performSelector:@selector(defaultTextField)];
    NSLog(@"popover opened");

} else {
    [_preferencesWindow close];
    [NSApp activateIgnoringOtherApps:NO];
    NSLog(@"popover closed");
    [_popover close];
    [_popover resignFirstResponder];
    [[NSApplication sharedApplication] hide: self];
    [statusItemView setHighlighted:NO];
}

}

Thanks for the help.

1
I'm guessing this is probably related to the window level in the popover's window, can you share some more about how you're displaying that popover?pfandrade
Edit 3 has more informationElbimio
you are positioning an NSPopover on an item in the menu bar, which has a higher level than notifications.Brad Allred
How about [[[_popover.contentViewController view] window] setLevel:level]? I've not tested though.rintaro
@rintaro That worked! Write it up in an answer and I'll select it as the answer. Thanks!Elbimio

1 Answers

1
votes

You want to adjust the window.level.

A notification is using level 18, so as long as your level is lower, you will not have this issue.

You can use these default NSWindow.Level

  • .normal = 0
  • .floating = 3
  • .submenu = 3
  • .tornOffMenu = 3

Or a custom level NSWindow.Level(rawValue: 17).

An important thing to note is you should set the windows level during or after the popover did show. Otherwise your setting will be reset.

You can do this from the popover.delegate using the function,

func popoverDidShow(_ notification: Notification)

Or listen to the notification directly with NSPopoverDidShowNotification.

This has been tested on macOS 10.15