How to: Unified OS X Title Bars?



  • So i was checking out the QtMac and QtMacExtras documentation pages and kept wondering how Spotify archived this kind of unified title bar on osx: Screenshot

    The classic QMainWindow::setUnifiedTitleAndToolBarOnMac() method does not seem to do the trick.
    So is there any way, to put widgets in the titlebar like the example screenshot shows;
    aligned to the middle of the titlebar, along with the window controls?
    (for another example, open chrome on os x - same fancy alignment)


  • Lifetime Qt Champion

    Hi,

    AFAIK, it's not the same concept. This post might give you some clues on how to proceed.

    Hope it helps



  • Hey, thank you very much for that hint!

    I've ever touched Cocoa and never went beyond Qt's capabilities on OSX before, so this was a total challenge for me.

    Yet, this is how far i came:

    void Test::createFancyMacWindow() {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSWindow *window = [
                [NSWindow alloc]
                initWithContentRect: NSMakeRect(200, 200, 600, 400)
                styleMask: NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask |NSTexturedBackgroundWindowMask
                backing: NSBackingStoreBuffered
                defer: NO
          ];
        // store pointer
        nsWindow = &window;
    
        // move toolbar where the titlebar used to be
        [window setTitleVisibility: NSWindowTitleHidden];
    
        // Adjust Cocoa layouts
        NSView *contentView = [window contentView];
        [contentView setAutoresizesSubviews:YES];
    
        QMacNativeWidget *nativeWidget = new QMacNativeWidget(contentView);
        //nativeWidget->move(0, 0);
        nativeWidget->setPalette(QPalette(Qt::red));
        nativeWidget->setAutoFillBackground(true);
    
        NSView *nativeWidgetView = nativeWidget->nativeView();
        [contentView addSubview:nativeWidgetView positioned:NSWindowAbove relativeTo:nil];
        [nativeWidgetView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
        [nativeWidgetView setAutoresizesSubviews:YES];
    
        nativeWidget->show();
    
    
        // Show the window.
        [window makeKeyAndOrderFront:window];
        [pool release];
    
        QMacToolBar *toolBar = new QMacToolBar();
        toolBar->addItem(QIcon(), QStringLiteral("Helloooo"));
    
        [window setToolbar: toolBar->nativeToolbar()];
    }
    

    There are only 2 issues remaining:

    1. The documentation of QMacToolBar states that

    "The toolbar must be attached to a QWindow using the attachToWindow() method in order to be visible. The toolbar is attached to the native NSWindow and is displayed above the QWindow. QMacToolBar visibility follows window visibility."

    Yet i've found no clue on how to cast NSWindow to QWindow. Using QWindow's static fromWinId Method produces a runtime crash as QWindow asks the Objective-C for types that do not exist.

    So, as stated in the code, i've tried to add the toolbar via Objective-C++, but this renders the added ToolbarItem nearly invisible (no Text) and when clicking where the item should be located the area around it gets filled with random noise and this message gets printed:

    filter:2:47: error: excess elements in vector initializer
      return img.a * mix(c0, c1, dot(img.rgb, vec3(0,000000e+00, 0,000000e+00, 0,000000e+00)));
                                                  ^                ~~~~~~~~~~
    filter:1:6: error: non-void function should return a value
    vec4 _falseColor(vec4 img, vec4 c0, vec4 c1) {
         ^
    
    1. The documentation of QMacNativeWidget is very misleading, as the Objective-C++ code snippet produces a very "unwanted" situation of 2 windows where one is "empty" (i fixed that in the code above).

    @concept
    It basically replaces the titlebar with the toolbar, as far as i understood.



  • Update: I managed to get a QWindow involved into the code, yet the toolbar is messed up.
    Screenshot

    New code:

    void Test::createFancyMacWindow() {
        QWindow* w = new QWindow();
        NSView* mainWindowNSView = (NSView*) w->winId();
        NSWindow* window = [mainWindowNSView window];
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        // move toolbar where the titlebar used to be
        [window setTitleVisibility: NSWindowTitleHidden];
    
        // Adjust Cocoa layouts
        NSView *contentView = [window contentView];
        [contentView setAutoresizesSubviews:YES];
    
        QMacNativeWidget *nativeWidget = new QMacNativeWidget(contentView);
        //nativeWidget->move(0, 0);
        nativeWidget->setPalette(QPalette(Qt::red));
        nativeWidget->setAutoFillBackground(true);
    
        NSView *nativeWidgetView = nativeWidget->nativeView();
        [contentView addSubview:nativeWidgetView positioned:NSWindowAbove relativeTo:nil];
        [nativeWidgetView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
        [nativeWidgetView setAutoresizesSubviews:YES];
    
        nativeWidget->show();
    
    
        // Show the window.
        [window makeKeyAndOrderFront:window];
        [pool release];
    
        QMacToolBar *toolBar = new QMacToolBar();
        toolBar->addItem(QIcon(), QStringLiteral("Helloooo"));
        toolBar->attachToWindow(w);
    
        [window setToolbar: toolBar->nativeToolbar()];
    
        w->show();
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.