Cocoa: Window type and flags handling.

Bring over code from Qt4's qwidget_mac.mm.
This commit is contained in:
Morten Sorvig 2011-07-01 14:22:16 +02:00
parent 016ac937b9
commit 9252742ba8
2 changed files with 175 additions and 7 deletions

View 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;
};

View File

@ -44,9 +44,12 @@
#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;
}