jhclare
jhclare

Reputation: 23

Autohide Toolbar only in full screen mode in Cocoa

My goal is simple and yet I cannot find a solution in spite of lots of searching.

Basically, when my app is in full-screen (kiosk) mode, I want the toolbar only to auto-hide, but I want the menu bar hidden.

Apparently this combination is not valid. I've tried:

- (NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions: (NSApplicationPresentationOptions)proposedOptions
{
    return (NSApplicationPresentationFullScreen |
        NSApplicationPresentationHideDock |
        NSApplicationPresentationHideMenuBar |
        NSApplicationPresentationAutoHideToolbar);
}

I get the following exception:

"... fullscreen presentation options must include NSApplicationPresentationAutoHideMenuBar if NSApplicationPresentationAutoHideToolbar is included"

Thing is, I don't want the menu bar displayed at all!

So, I'm presuming this is not possible using the standard presentation options. Any ideas how I might approach implementing this behaviour manually?

I'm thinking along the lines of: detect the mouse position and only show/hide the toolbar when the mouse is at/near the top of the screen.

I'm very new to Cocoa so not sure where I would start to achieve this. Any help much appreciated!

Many thanks,

John

Upvotes: 0

Views: 823

Answers (1)

Guilherme Rambo
Guilherme Rambo

Reputation: 2046

I've got It to work, but only by using private APIs.

First I had to find out how to prevent the menubar from appearing. I discovered the functions _HIMenuBarPositionLock and _HIMenuBarPositionUnlock, from Carbon (link the app with Carbon.framework).

Then I had to create a custom subclass of NSToolbar, at awakeFromNib I register notification observers to lock and unlock the menubar when the window enters and exits fullscreen, respectively:

- (void)awakeFromNib
{
    [super awakeFromNib];

    [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillEnterFullScreenNotification object:[self _window] queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        // lock menubar position when entering fullscreen so It doesn't appear when the mouse is at the top of the screen
        _HIMenuBarPositionLock();
    }];
    [[NSNotificationCenter defaultCenter] addObserverForName:NSWindowWillExitFullScreenNotification object:[self _window] queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
        // unlock menubar position when exiting fullscreen
        _HIMenuBarPositionUnlock();
    }];

    [self _setupToolbarHotspotTrackingView];
}

_setupToolbarHotspotTrackingView is a method on SOToolbar which adds a view to the window, this view will be used to track the mouse location and show/hide the toolbar accordingly.

- (void)_setupToolbarHotspotTrackingView
{
    NSView *contentView = [self _window].contentView;

    self.toolbarHotspotTrackingView = [[SOToolbarTrackingView alloc] initWithFrame:contentView.bounds];
    [contentView addSubview:self.toolbarHotspotTrackingView];
    self.toolbarHotspotTrackingView.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable;
    self.toolbarHotspotTrackingView.toolbar = self;
}

I also had to override _attachesToMenuBar on SOToolbar so the animation works properly.

- (BOOL)_attachesToMenuBar
{
    return NO;
}

SOToolbarTrackingView sets up a tracking area for mouse moved events and checks to see if the mouse is at the top of the window. It then calls some methods on the private class NSToolbarFullScreenWindowManager to show and hide the toolbar.

There's too much stuff to explain It all in detail here, I've uploaded my experimental project so you can take a look. Download the sample project here.

Upvotes: 2

Related Questions