detecting menubar mode

Hello,
in System Preferences > General there is the option to “Automatically hide and show the Menu Bar”.
Suppose I hide the MenuBar and push a window up to the screen-top.
When I make the MenuBar again visible, the MenuBar overlaps the top of the window.
macOSlib has got a function that tells whether the MenuBar is visible or not, but how can I make my app aware that the MenuBar mode has changed and consequently push the window below? I would avoid a timer solution polling MenubarVisible.

Suggestions welcome. Thanks.

OS X sends a distributed notification when the menu bar is hidden or shown.
To get this notification you have to use something like MBS plugins and listen for a notification named

AppleInterfaceMenuBarHidingChangedNotification

this is done using NSDistributedNotificationCenter in Cocoa.
Maybe macosLib has something for this too.

I looked into macosLib, but as usual I find myself lost.
In the open event of a window I tried a variety of
cocoa.NSDistributedNotificationCenter.NSNotificationDeliverImmediately
but debugging (obviously) show an error at this line.
Could you put together a snippet? Thanks.

I can’t find reference to this notification. Google, Bing and DuckDuckGo all return 0 results (not even finding your post!).

I suspect it’s not a documented notification that can be relied on.

There is a MenuBarVisible Boolean property described at https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSMenu_Class/#//apple_ref/occ/clm/NSMenu/menuBarVisible

@Michel: yes, with macoslib installed, the following snippet in the activate and deactivate event handlers does the job:
if Cocoa.NSMenu.MenuBarVisible then
if top < 45 then top = 45
end if

But I was after a “notification” solution that is beyond my expertise.

Indeed this is not documented, I discovered it simply subscribing for all notifications and going to system preferences and turning on and off the setting for the menu bar.

For this I normally use the MBS plugin, therefore I don’t know how to proceed with macosLib.
Sorry but I have not time to try it. You can know more about it here:
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDistributedNotificationCenter_Class/

Anyway, you should basically access the shared notification center (it’s a singleton) and subscribe to the wanted notification.

@Massimo: [quote]Sorry but I have not time to try it.[/quote]
OK Massimo. Your suggestion is valuable. Thanks.

[quote=262705:@Carlo Rubini]@Michel: yes, with macoslib installed, the following snippet in the activate and deactivate event handlers does the job:
if Cocoa.NSMenu.MenuBarVisible then
if top < 45 then top = 45
end if

But I was after a “notification” solution that is beyond my expertise.[/quote]

A simple multiple timer monitoring the property every half a second or so are to do it. I would rather go that route than relying on undocumented features that may break each time a new version of OS X appears.

Well, it’s true this notification is not (yet) documented from Apple. I have to say I used this mechanism very often in past and never had problems with undocumented notifications. The worst thing can happen is the notification name change and the application doesn’t detect anymore the change. The timer solution should be the last resource IMHO.

Whatever. I know some people are prejudiced against timers. I rather use them than something that can break on a moment’s notice. Live and let live.

I modified my module for getting window fullscreen notifications to listen for all from the distributed center and get a different notification name, here’s the ones collected so far

com.apple.HIToolbox.hideMenuBarShown <<<<<<< hiding menubar com.apple.HIToolbox.frontMenuBarShown com.apple.HIToolbox.beginMenuTrackingNotification com.apple.HIToolbox.endMenuTrackingNotification com.apple.systemBeep _NSDoNotDisturbEnabledNotification _NSDoNotDisturbDisabledNotification AppleInterfaceThemeChangedNotification AppleNoRedisplayAppearancePreferenceChanged AppleShowScrollBarsSettingChanged AppleAquaAntiAliasingChanged com.apple.dock.prefchanged com.apple.carbon.core.DirectoryNotification com.apple.backup.exclusionschanged IMKUserDictionaryDidChangeNotification com.apple.Foundation.NSHTTPCookieManagerAcceptPolicyChanged

Don’t know why my names are different. Also I couldn’t find in the system preferences and option to hide the menubar. Toggling things in preferences yields notifications like AppleInterfaceThemeChangedNotification but using Xojo to hide the menubar yields com.apple.HIToolbox.hideMenuBarShown.

Anyways here’s my code.
http://trochoid.weebly.com/uploads/6/2/6/4/62644133/distnot.zip
It’s fairly simple, for declares, but I don’t know how much help it will be.
It only handles one listener. Call distNot.setup(receiver) to start. receiver must implement the iNotify interface whose single method is called each time a notification comes in. Call distNot.destroy before receiver is done with.

[quote=262760:@Will Shank]
Don’t know why my names are different. Also I couldn’t find in the system preferences and option to hide the menubar. [/quote]

This is what I get with your code (snippet):

com.apple.HIToolbox.beginMenuTrackingNotification com.apple.HIToolbox.endMenuTrackingNotification com.apple.backup.RegisterHooksNotification AppleInterfaceMenuBarHidingChangedNotification AppleTextInputMenuExtraDidLoadNotification AppleInterfaceMenuBarHidingChangedNotification AppleTextInputMenuExtraDidLoadNotification

You see the notification is there.
I’m talking about the System Preferences setting in the General panel for Yosemite+

Btw, I got the same with the MBS methods.

@Carlo Rubini you can use the code from Will then, and get notified for both the System Preferences setting and the menu on/off switch from Xojo or other applications.

I think that’s new in El Capitan. I have Yosemite and don’t have that.

Ahh sorry, I mistakenly thought it was introduced in Yosemite.

OK, thanks Massimo, I see it now. The notification for this new El Capitan feature is AppleInterfaceMenuBarHidingChangedNotification. The other notification I pointed out is just an app hiding it’s own menubar.

Nice work Will. Thank you.

Just for the record: this snippet either in a timer or in activation/deactivation events won’t do:
if Cocoa.NSMenu.MenuBarVisible then
if top < 45 then top = 45
end if

In fact, if in System Preferences > General the option is set to hide the menubar and a window is positioned at top < 45, then moving the mouse over the hidden menubar, the menubar shows up and the window.top shifts to top = 45.
Experimenting with Safari etc., it seems this is NOT the expected behavior; i.e. the window should remain at top < 45. Only at resetting the Preferences option to “Show” the window should move to top = 45.

Therefore, it seems that “notification” (like Will’s, MBS or other) is indeed needed.
Again, thanks to all who contributed to this topic.

Just tested this :

static previousmenubarvisible as boolean dim ismenuvisible as boolean = Cocoa.NSMenu.MenuBarVisible if ismenuVisible <> previousmenubarvisible then // Do what is needed on MenuBarChanged system.DebugLog str(ismenuVisible) end if previousmenubarvisible = ismenuVisible

It triggers the debuglog like clockworks when the bar is hidden/reinstated.

The issue must be with the window top values. Simply hiding the window bar with the menu takes a value of 22, not 45. You can also go by Self.Bounds.Top = 0 which indicates the top of the window bar is at position 0.

It does not mean you should not use the events.