How do I prevent the menu bar from moving down when my popover is open?
Asked Answered
E

4

12

I have an app with a popover that appears on a status bar item. The thing is, when you click on the icon while you're in a full screen app, then move the mouse away from the menu bar to click on something in the popup, the menu bar moves up, and so does the popup. It's annoying.

Anyone know of any way to solve this? I've tried attaching an invisible menu to the popup, but I can't get the menu to be invisible.

Screenshot for clarity, the annoying part is where I wave my mouse around:

enter image description here

Ectoparasite answered 21/1, 2016 at 0:40 Comment(3)
BTW - you'll not only have this issue when going full screen. On 10.11 it's possible to always automatically hide the menu bar: tekrevue.com/tip/hide-menu-bar-os-x-el-capitanNynorsk
You might want to check out this topic, sounds like a clean solution to your problem: #35009001Busey
Unfortunately none of the answers in that question helped much in my case. The best I managed to get was detecting when the menubar becomes hidden or visible again.Humanoid
E
5

The popover window is moving because its parent window is the status item window, and when the parent window moves, the child moves with it. (Before I investigated this, I didn't even know Cocoa had parent and child windows.) I solved the problem with this code immediately after showing the popover:

NSWindow *popoverWindow = self.popup.contentViewController.view.window;
[popoverWindow.parentWindow removeChildWindow:popoverWindow];

Now, the menu bar still moves up, but at least the popup stays in the same place.

Ectoparasite answered 27/1, 2016 at 20:46 Comment(3)
Messing with windows you don't own.. wouldn't go down that route if I were you. From experience that's asking for trouble and prone to break with upcoming OS releases (or even older versions than the OS you've tested it on)Nynorsk
@Nynorsk Any better ideas?Ectoparasite
The only other solution I found was to detach the popover when the menu-bar hides (See github.com/lukaskubanek/DetachablePopoverExample for detaching a popover)Humanoid
B
1

Either use Carbon events or watch for things happening to the menu bar (window of type NSStatusBarWindow):

Notifications of type

  • NSWindowDidChangeOcclusionStateNotification
  • NSWindowDidMoveNotification
  • NSWindowWillCloseNotification
  • NSWindowDidCloseNotification

with an object of class NSStatusBarWindow should give you enough information about the menu bar showing or hiding to add proper handling.

Busey answered 28/1, 2016 at 16:26 Comment(1)
And what is the proper handling? The hard part is not finding out when the status item moves, it's preventing the popup from moving.Ectoparasite
N
0

Super-hacky approach:

Custom window with some super-high window level to make it appear over the menu bar, then add a transparent custom view to the new window that catches and handles/blocks mouse clicks according to your needs.

Or:

Get the window instance the popover is using to display and track/handle NSWindowWillMoveNotification / NSWindowDidMoveNotification.

Nynorsk answered 21/1, 2016 at 7:3 Comment(6)
Not quite what my problem is, added a screenshot to clarify.Ectoparasite
Ah, right! Any notifications that are sent when the menu bar hides? Just try listen to anything and watch out in particular for the ones mentioned in developer.apple.com/library/mac/documentation/General/…Nynorsk
If there's any local notifications sent, they would be to the program that is in full screen. There might be a distributed notification, but what could I do about it? Hide the popup? That would make it impossible to use the popup in full screen mode.Ectoparasite
..AppKit sends heaps of notifications all the time, worth checking. No delegate method being called for your window? For the app's menu bar?Nynorsk
@Ectoparasite Or just watch out for the popover's window moving (see altered answer above)Nynorsk
I figured it out myself. Check my answer if you want to see how.Ectoparasite
R
0

I converted @tbodt's answer to Swift 4 and confirmed that is resolves this issue:

let popoverWindow = popup.contentViewController.view.window as? NSWindow
popoverWindow?.parent?.removeChildWindow(popoverWindow!)
Ratliff answered 17/4, 2018 at 21:1 Comment(3)
As cacau has mentioned its not a good idea to mess around with internal windows. Why not to place a small hidden window near the status bar item when the popover should be presented and to relate it to a view in the hidden window. I used this technique years ago to prevent flickering during open animation. There are different popover behaviour you can use and for me, to remove it from the parent window could have an side effect.Habilitate
@MarcT. Would you be so kind and provide a code snippet? I'm dealing with a similar problem, and didn't quite catch what you mean.Daren
I'd be very interested in seeing an example of this as well. I would like the popover to follow the menubar upwards, but stop when it reaches the top of the screen, so that none of the popover is cut off.Humanoid

© 2022 - 2024 — McMap. All rights reserved.