28

I want to create a custom Window Toolbar but without using an actual NSToolbar (because it doesn't behaves right in some cases for my needs and I can't style it the way I want), therefore I need to add a subview to the Window titlebar. It should look like the following: Screenshot of custom Toolbar

A posible way would be:

[[[_window contentView] superview] addSubview:_titlebarView];

but this has the problem, that it causes a warning on Yosemite (NSWindow warning: adding an unknown subview: <NSView: 0x608000122b20>) so this doesn't seem to be the right way to do it.

Currently I am adding the toolbar view to the titlebar view:

[[[_window standardWindowButton:NSWindowCloseButton]
    superview] addSubview:_titlebarView];

but this feels wrong too.

Since my App only targets OS X 10.10 (Yosemite) it would be fine for me to use Yosemite-only API's, so I had a look to NSTitlebarAccessoryViewController and I managed to successfully subclass it and using it with NSWindow's addTitlebarAccessoryViewController: method. With this approach there remains one problem, the possible values for layoutAttribute are:

  • NSLayoutAttributeBottom
    Adds the view to the bottom of the window's titlebar, while preserving the view's height.
  • NSLayoutAttributeRight
    Adds the view to the right of the window's titlebar, clipping the view to the height of the titlebar.

The NSLayoutAttributeBottom is not suitable for me, since I need to position things right at the top of the window titlebar (see screenshot above) and center the traffic lights. NSLayoutAttributeRight would be exactly what I need, but I can't find a way to increase the titlebar height, so the view is clipped to the titlebar height, making it useless for me. (Note: Using a textured Window and changing the content border doesn't work, since it will not change the actual titlebar height)

What is the recommended way to do this? I would prefer to go with the official API's and use the AccessoryViewController approach, if it would be possible to have a view larger than the default titlebar.

Community
  • 1
  • 1
ePirat
  • 1,068
  • 11
  • 20
  • 1
    Arrgh! This is bugging me as well... – SevenBits Jan 02 '15 at 03:26
  • FYI, you can still use the approach that you are currently using... but it will just generate a warning. – SevenBits Jan 02 '15 at 03:36
  • 3
    @SevenBits I know that I can use it, but there was a clear note in the release notes: “Applications doing this will need to fix this problem, as it prevents new features on 10.10 from working properly.” on [Mac OS X Developer Release Note](https://developer.apple.com/library/mac/releasenotes/AppKit/RN-AppKit/) – ePirat Jan 02 '15 at 13:51
  • There's another problem I see when using the new titlebar accessory view: core graphics behavior changes somehow, which creates trouble for 3rd party code I use (warnings for EDSidebar, https://www.cocoacontrols.com/controls/edsidebar, and rendering calls with a null context, CorePlot, https://github.com/core-plot/core-plot). I can reliably reproduce that. Happens when I add the accessory view and disappears when I remove it. – Mike Lischke Jan 03 '15 at 11:22
  • @MikeLischke What warnings for example? And how are you adding it? (Which layoutAttribute?) – ePirat Jan 04 '15 at 02:31
  • @ePirat When you add your toolbarView to the titlebarView does it dynamically adjust the height of the titlebar OR is the titlebar height fixed irrespective of the content height of the view you are adding? – Sam Jan 21 '15 at 12:20
  • @Sam When using the official way (NSTitlebarAccessoryViewController) and NSLayoutAttributeRight it is clipped to the height of the titlebar. – ePirat Jan 21 '15 at 12:31
  • @Sam if you mean the titlebarView of WAYAppStoreWindow, that would be the same as using [[[_window standardWindowButton:NSWindowCloseButton] superview] addSubview:_titlebarView]; (which is what it actually does). It does work, but is nearly as bad as the old way is and breaks i.e. in fullscreen mode. – ePirat Jan 21 '15 at 12:32
  • @ePirat When I use NSTitlebarAccessoryViewController and NSLayoutAttribute.Right it fills the entire titlebar! How do you get it to not do that? But yes, I confirm that it also clips height to that of existing titlebar. What were Apple thinking with this API? – Sam Jan 21 '15 at 12:58
  • @ePirat I have gone through the WAYWindow source to see what they are doing to resize the height (as I can tell you have) and it is the only way I can see to do it right now...there is no warning (yet) and hopefully Apple fixes the official way at next release!? – Sam Jan 21 '15 at 13:00
  • @Sam just checked, it fills the entire titlebar for me too (which for my usecase is quite useful but) given the LayoutAttribute name is NSLayoutAttribute.Right this behavior is confusing. – ePirat Jan 23 '15 at 12:28

4 Answers4

6

it just a NSToolBar. in Yosemite, when window.title.titleVisibility = .Hidden, the NSToolBar will become the titlebar

  • 1
    As already mentioned in my question for reasons of styling I do not want to use a NSToolBar, except there would be a way to use it like a view and be able to completely design it in interface builder (and use autolayout). I don't think this is possible. – ePirat Jan 28 '15 at 06:46
4

WAYAppStoreWindow might accomplish what you're looking for. It was build explicitly to avoid the subview warning in Yosemite, specify a custom window titlebar height and add subviews to the titlebar.

Fabian
  • 6,973
  • 2
  • 26
  • 27
  • Thanks, I already had a look at it, but can't figure out how to add subviews. – ePirat Jan 06 '15 at 18:01
  • 4
    Adding subviews to their titlebarView, would be the same as doing `[[[_window standardWindowButton:NSWindowCloseButton] superview] addSubview:_customTitlebarView];` – ePirat Jan 23 '15 at 12:31
  • With El-Capitan the traffic lights reset their position if a sheet is shown. There are even more problems when in full-screen mode. Aaarggh this has become so difficult to achieve now. – strangetimes Oct 06 '15 at 12:17
  • 1
    Why doesn't Apple provide clear APIS, the problem with WAYAppStoreWindow or INAppStoreWindow is that it does all that code that should be apple's. My 'INAppStoreWindow' has a nice side effect in that my window size keeps increasing after each run ... – Klajd Deda Mar 15 '16 at 04:25
1

Thanks @ePirat

Adding subviews to their titlebarView, would be the same as doing

[[[_window standardWindowButton:NSWindowCloseButton] superview] addSubview:_customTitlebarView];
Huynh Inc
  • 2,010
  • 1
  • 25
  • 42
  • 1
    That actually is not a very constructive answer as it doesn't help at all answering my question. It does work, but feels hacky and like Apple would probably not like it in App Store Apps. (with this way there are additionally some problems in Fullscreen mode) – ePirat Jun 05 '15 at 16:57
0

Assign your Window to self view. and then add the subview with frame later provide required functionality

Abhi
  • 115
  • 11