Cocoa: Window type and flags handling.
authorMorten Sorvig <morten.sorvig@nokia.com>
Fri, 1 Jul 2011 12:22:16 +0000 (14:22 +0200)
committerMorten Sorvig <morten.sorvig@nokia.com>
Fri, 1 Jul 2011 12:22:41 +0000 (14:22 +0200)
Bring over code from Qt4's qwidget_mac.mm.

src/plugins/platforms/cocoa/qcocoawindow.h
src/plugins/platforms/cocoa/qcocoawindow.mm

index 9ce449a..dc7907d 100644 (file)
@@ -73,11 +73,16 @@ public:
     void setCurrentContext(QCocoaGLContext *context);
     QCocoaGLContext *currentContext() const;
 
+protected:
+    void determineWindowClass();
+    NSWindow *createWindow();
 private:
     friend class QCocoaBackingStore;
     NSWindow *m_nsWindow;
     QNSView *m_contentView;
     NSView *m_windowSurfaceView;
+    quint32 m_windowAttributes;
+    quint32 m_windowClass;
     QCocoaGLContext *m_glContext;
 };
 
index 984e616..550c429 100644 (file)
 #include "qcocoaglcontext.h"
 #include "qnsview.h"
 #include <QtCore/private/qcore_mac_p.h>
-
+#include <qwindow.h>
 #include <QWindowSystemInterface>
 
+#include <Cocoa/Cocoa.h>
+#include <Carbon/Carbon.h>
+
 #include <QDebug>
 
 QCocoaWindow::QCocoaWindow(QWindow *tlw)
@@ -54,13 +57,9 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
     , m_glContext(0)
 {
     QCocoaAutoReleasePool pool;
-    const QRect geo = tlw->geometry();
-    NSRect frame = NSMakeRect(geo.x(), geo.y(), geo.width(), geo.height());
 
-    m_nsWindow  = [[NSWindow alloc] initWithContentRect:frame
-                                            styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask
-                                            backing:NSBackingStoreBuffered
-                                            defer:YES];
+    determineWindowClass();
+    m_nsWindow = createWindow();
 
     QNSWindowDelegate *delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this];
     [m_nsWindow setDelegate:delegate];
@@ -70,6 +69,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
     m_contentView = [[QNSView alloc] initWithQWindow:tlw];
 
     if (tlw->surfaceType() == QWindow::OpenGLSurface) {
+        const QRect geo = window()->geometry();
         NSRect glFrame = NSMakeRect(0, 0, geo.width(), geo.height());
         m_windowSurfaceView = [[NSOpenGLView alloc] initWithFrame : glFrame pixelFormat : QCocoaGLContext::createNSOpenGLPixelFormat() ];
         [m_contentView setAutoresizesSubviews : YES];
@@ -168,3 +168,166 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
     return m_glContext;
 }
 
+/*
+    Determine the window class based on the window type and
+    window flags, and widget attr Sets m_windowAttributes
+    and m_windowClass.
+*/
+void QCocoaWindow::determineWindowClass()
+{
+    Qt::WindowType type = window()->windowType();
+    Qt::WindowFlags flags = window()->windowFlags();
+
+    const bool popup = (type == Qt::Popup);
+
+    if (type == Qt::ToolTip || type == Qt::SplashScreen || popup)
+        flags |= Qt::FramelessWindowHint;
+
+    m_windowClass = kSheetWindowClass;
+
+    if (popup || type == Qt::SplashScreen)
+        m_windowClass = kModalWindowClass;
+    else if (type == Qt::ToolTip)
+        m_windowClass = kHelpWindowClass;
+    else if (type == Qt::Tool)
+        m_windowClass = kFloatingWindowClass;
+    else
+        m_windowClass = kDocumentWindowClass;
+
+    m_windowAttributes = (kWindowCompositingAttribute | kWindowStandardHandlerAttribute);
+
+//    if(qt_mac_is_macsheet(window())) {
+//        m_windowClass = kSheetWindowClass;
+//    } else
+
+    {
+        // Shift things around a bit to get the correct window class based on the presence
+        // (or lack) of the border.
+
+        bool customize = flags & Qt::CustomizeWindowHint;
+        bool framelessWindow = (flags & Qt::FramelessWindowHint || (customize && !(flags & Qt::WindowTitleHint)));
+        if (framelessWindow) {
+            if (m_windowClass == kDocumentWindowClass) {
+                m_windowAttributes |= kWindowNoTitleBarAttribute;
+            } else if (m_windowClass == kFloatingWindowClass) {
+                m_windowAttributes |= kWindowNoTitleBarAttribute;
+            } else if (m_windowClass  == kMovableModalWindowClass) {
+                m_windowClass = kModalWindowClass;
+            }
+        } else {
+            m_windowAttributes |= NSTitledWindowMask;
+            if (m_windowClass != kModalWindowClass)
+                m_windowAttributes |= NSResizableWindowMask;
+        }
+
+        // Only add extra decorations (well, buttons) for widgets that can have them
+        // and have an actual border we can put them on.
+
+        if(m_windowClass != kModalWindowClass && m_windowClass != kMovableModalWindowClass
+                && m_windowClass != kSheetWindowClass && m_windowClass != kPlainWindowClass
+                && !framelessWindow && m_windowClass != kDrawerWindowClass
+                && m_windowClass != kHelpWindowClass) {
+            if (flags & Qt::WindowMinimizeButtonHint)
+                m_windowAttributes |= NSMiniaturizableWindowMask;
+            if (flags & Qt::WindowSystemMenuHint || flags & Qt::WindowCloseButtonHint)
+                m_windowAttributes |= NSClosableWindowMask;
+        } else {
+            // Clear these hints so that we aren't call them on invalid windows
+            flags &= ~(Qt::WindowMaximizeButtonHint | Qt::WindowMinimizeButtonHint
+                       | Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint);
+        }
+
+    }
+
+    if((popup || type == Qt::Tool) && !window()->isModal())
+        m_windowAttributes |= kWindowHideOnSuspendAttribute;
+    m_windowAttributes |= kWindowLiveResizeAttribute;
+}
+
+/*
+
+*/
+NSWindow * QCocoaWindow::createWindow()
+{
+    // Determine if we need to add in our "custom window" attribute. Cocoa is rather clever
+    // in deciding if we need the maximize button or not (i.e., it's resizeable, so you
+    // must need a maximize button). So, the only buttons we have control over are the
+    // close and minimize buttons. If someone wants to customize and NOT have the maximize
+    // button, then we have to do our hack. We only do it for these cases because otherwise
+    // the window looks different when activated. This "QtMacCustomizeWindow" attribute is
+    // intruding on a public space and WILL BREAK in the future.
+    // One can hope that there is a more public API available by that time.
+/*
+    Qt::WindowFlags flags = widget ? widget->windowFlags() : Qt::WindowFlags(0);
+    if ((flags & Qt::CustomizeWindowHint)) {
+        if ((flags & (Qt::WindowCloseButtonHint | Qt::WindowSystemMenuHint
+                      | Qt::WindowMinimizeButtonHint | Qt::WindowTitleHint))
+            && !(flags & Qt::WindowMaximizeButtonHint))
+            wattr |= QtMacCustomizeWindow;
+    }
+*/
+    // If we haven't created the desktop widget, you have to pass the rectangle
+    // in "cocoa coordinates" (i.e., top points to the lower left coordinate).
+    // Otherwise, we do the conversion for you. Since we are the only ones that
+    // create the desktop widget, this is OK (but confusing).
+/*
+    NSRect geo = NSMakeRect(crect.left(),
+                            (qt_root_win != 0) ? flipYCoordinate(crect.bottom() + 1) : crect.top(),
+                            crect.width(), crect.height());
+*/
+    QRect geo = window()->geometry();
+    NSRect frame = NSMakeRect(geo.x(), geo.y(), geo.width(), geo.height());
+
+    QCocoaAutoReleasePool pool;
+    NSWindow *window;
+
+    switch (m_windowClass) {
+    case kMovableModalWindowClass:
+    case kModalWindowClass:
+    case kSheetWindowClass:
+    case kFloatingWindowClass:
+    case kOverlayWindowClass:
+    case kHelpWindowClass: {
+        NSPanel *panel;
+
+        BOOL needFloating = NO;
+        BOOL worksWhenModal = (this->window()->windowType() == Qt::Popup);
+
+        // Add in the extra flags if necessary.
+        switch (m_windowClass) {
+        case kSheetWindowClass:
+            m_windowAttributes |= NSDocModalWindowMask;
+            break;
+        case kFloatingWindowClass:
+        case kHelpWindowClass:
+            needFloating = YES;
+            m_windowAttributes |= NSUtilityWindowMask;
+            break;
+        default:
+            break;
+        }
+
+        panel = [[NSPanel alloc] initWithContentRect:frame
+                                   styleMask:m_windowAttributes
+                                   backing:NSBackingStoreBuffered
+                                   defer:YES];
+//  ### crashes
+//        [panel setFloatingPanel:needFloating];
+//        [panel setWorksWhenModal:worksWhenModal];
+        window = panel;
+        break;
+    }
+
+    default:
+        m_nsWindow  = [[NSWindow alloc] initWithContentRect:frame
+                                            styleMask:m_windowAttributes
+                                            backing:NSBackingStoreBuffered
+                                            defer:YES];
+        break;
+    }
+
+    //qt_syncCocoaTitleBarButtons(window, widget);
+    return window;
+}
+
+