Pregunta

I need to show a window (without title bar) above third party applications without my window taking focus.

I have tried using an NSPanel and setting enabling non-activating, but that didn't help.

I tried orderFront:self, but that didn't help either.

I always needed to add [NSApp activateIgnoringOtherApps:YES]; because the window wouldn't show otherwise.

I have here a sample project for just this functionality:
http://users.telenet.be/prullen/TopW2.zip

UIElement is set to true in the application's plist file, so there is no dock. You can activate the window by pressing ALT + SPACE at the same time. You will see that the app below it looses focus. Any thoughts on how to fix this? I've seen other apps do it so I know it's possible.

Edit: here's the code so far. Remember the window is a non-activating NSPanel. I still need that last NSApp activateIgnoringOtherApps line or otherwise it doesn't display. But of course that makes the window the active one.

 _windowController = [[MyWindowController alloc] initWithWindowNibName:@"MyWindowController"];

    [[_windowController window] setLevel:NSNormalWindowLevel+1];
    [[_windowController window] orderFrontRegardless];

    [_windowController showWindow:self];

   [NSApp activateIgnoringOtherApps:YES];

I've also subclassed NSPanel and added two methods:

- (BOOL)canBecomeKeyWindow
{
    return YES;
}

- (BOOL)canBecomeMainWindow
{
    return YES;
}

Edit: OK, unchecking setHidesOnDeactivate fixes this, but now the window will never hide. I need it to hide when the user presses the app below it or switches to another app.

Edit 2: OK, this seems to fix the above issue:

- (void)awakeFromNib
{
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hideWindow) name:NSWindowDidResignKeyNotification object:nil];
}
- (void)hideWindow {
    [self setHidesOnDeactivate:YES];
}

Not sure if there's a better way.

And for those that want to know how to display the window:

    [[_windowController window] setLevel:NSPopUpMenuWindowLevel];
    [[_windowController window] orderFrontRegardless];
    [[_windowController window] makeKeyWindow];

    [_windowController showWindow:self];
¿Fue útil?

Solución

Either one of these should do the trick:

  • Use -[NSWindow orderFrontRegardless] to get a normal level window to the front without activating the corresponding app, or
  • Use -[NSWindow setLevel:] to increase the window level to something higher than NSNormalWindowLevel

Otros consejos

Not to take away from @puzzle's useful answer, but it sounds like your problem has something to do with using an NSPanel instead of an NSWindow.

The "How Panels Work" docs say:

  • Onscreen panels, except for alert dialogs, are removed from the screen when the application isn’t active and are restored when the application again becomes active. This reduces screen clutter.
  • Specifically, the NSWindow implementation of the hidesOnDeactivate method returns NO, but the NSPanel implementation of the same method returns YES.

So perhaps you could override hidesOnDeactivate to return NO, or change to NSWindow

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top