How do I get default title bar height of a NSWindow?
Asked Answered
A

3

16

I created an OS/X app that when it runs, I position the window in the center of the screen. In order to do this, it's essential that I include the title bar height in my calculation of the y value.

Is there a way to determine the default title bar? I'd expect (based on my experience with other windowing systems) that I have to query the window manager somehow...

Abandoned answered 10/3, 2015 at 3:5 Comment(4)
I think you will probably have to do a little mojo to figure out the content view, and figure out where it lives in the window... see developer.apple.com/library/mac/documentation/Cocoa/Reference/…Leibniz
You can configure the window to do that in IB.Sneeze
I'm not using IB. It makes me feel dirty.Abandoned
By the way, you can also just call NSWindow.center() to accomplish this without complex calculations of frame size and titlebar heightStodder
S
18

I've come up with this solution. Note that when the window's styleMask includes fullSizeContentView, this returns 0.0, because in that case the titlebar effectively has no height.

As a Swift extension:

extension NSWindow {
    var titlebarHeight: CGFloat {
        frame.height - contentRect(forFrameRect: frame).height
    }
}

Usage:

let titlebarHeight = someWindow.titlebarHeight

As an Objective-C Category-Extension:

@implementation NSWindow (TitleBarHeight)

- (CGFloat) titlebarHeight
{
    return self.frame.size.height - [self contentRectForFrameRect: self.frame].size.height;
}

@end

Usage:

CGFloat titlebarHeight = someWindow.titlebarHeight;
Stodder answered 28/4, 2017 at 15:39 Comment(1)
In the case where you want to treat a fullSizeContentView window as if it has a title bar, you can infer that height from the size and positions of the window buttonsStodder
P
9

Answer for computing the height of the toolbar/titlebar area when using .fullSizeContentView on NSWindow

if let windowFrameHeight = self.view.window?.contentView?.frame.height,
    let contentLayoutRectHeight = self.view.window?.contentLayoutRect.height {
    let fullSizeContentViewNoContentAreaHeight = windowFrameHeight - contentLayoutRectHeight
}

fullSizeContentViewNoContentAreaHeight is the height you want. This is important to compute this value dynamically, because if you have an app using NSDocument and if the user creates a new document, the system might open this new document in a new tab. You might do this in updateViewConstraints() to detect this kind of changes.

Source: https://developer.apple.com/videos/play/wwdc2016/239/

Privileged answered 13/12, 2019 at 13:52 Comment(1)
It's possible I'm missing something, but I changed the windowFrameHeight value to view.window?.frame.height and this is giving me the correct height regardless of whether the window has a full size content view. Super useful. Also works great as an extension on NSWindow: var titleBarHeight: CGFloat { return frame.height - contentLayoutRect.height }Cissie
G
6

It's not clear if you want to center the content rect and then build the frame rect to keep the content rect centered, or if you want to center the frame rect and are interested in the corresponding content rect.

In either case, NSWindow has methods that will help. Before you have an instance, you can use the class methods +frameRectForContentRect:styleMask: and +contentRectForFrameRect:styleMask:. Those take into account the window style as expressed by the style mask, but do not take any toolbar the eventual window may have into account.

If you're working with an existing instance, you can use the methods -frameRectForContentRect: and -contentRectForFrameRect:. Those use the current style of the window and take its toolbar into account, too. (The toolbar is within the frame rect but not the content rect.)

You seem determined to use the actual center of the screen for the window. However, you should consider using the -center method of NSWindow. It positions the window horizontally centered but actually higher than the true vertical center of the screen. It does that deliberately since that's deemed more prominent and immediate for the user.

Grundy answered 10/3, 2015 at 6:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.