summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMorten Johan Sorvig <morten.sorvig@nokia.com>2012-03-13 10:37:53 +0100
committerQt by Nokia <qt-info@nokia.com>2012-03-20 08:29:07 +0100
commit6d9f04422ac2b64e43f0e78c1fdb9ced29e4b187 (patch)
treecb1c9d40c958ba34707d1e341db922cecfabe56b /src
parent5939cd33af5e43308e533a85444da073add8f05a (diff)
Cocoa: Implement support for child windows.
On OS X, child windows (in the Qt sense) are not windows. Add special case to window creation that links the content views instead of creating a NSWindow. Add a similar special case to setGeometry(). Refactor window (re)creation into recreateWindow(), which is called from both the QCocoaWindow constructor and setParent(). m_nsWindow may now be null, add null-pointer checks to all usages. Change winId() to return the m_contentView pointer instead of m_nsWindow. QGLWidget now works, but probably has sibling window stacking issues which we won't be able to fix without moving to client-side compositing. Change-Id: I2e74cf27734dba7076c150e0d8341f0a62d3de2d Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm88
2 files changed, 69 insertions, 21 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index 8bdb5535d5..0920bc7b4b 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -92,6 +92,7 @@ public:
~QCocoaWindow();
void setGeometry(const QRect &rect);
+ void setCocoaGeometry(const QRect &rect);
void setVisible(bool visible);
Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags);
void setWindowTitle(const QString &title);
@@ -117,6 +118,7 @@ public:
protected:
// NSWindow handling. The QCocoaWindow/QNSView can either be displayed
// in an existing NSWindow or in one created by Qt.
+ void recreateWindow(const QPlatformWindow *parentWindow);
NSWindow *createNSWindow();
void setNSWindow(NSWindow *window);
void clearNSWindow(NSWindow *window);
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 5c30e7f38b..d4327405cb 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -90,6 +90,7 @@
QCocoaWindow::QCocoaWindow(QWindow *tlw)
: QPlatformWindow(tlw)
+ , m_nsWindow(0)
, m_glContext(0)
, m_inConstructor(true)
{
@@ -98,8 +99,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
m_contentView = [[QNSView alloc] initWithQWindow:tlw platformWindow:this];
setGeometry(tlw->geometry());
- m_nsWindow = createNSWindow();
- setNSWindow(m_nsWindow);
+ recreateWindow(parent());
m_inConstructor = false;
}
@@ -119,10 +119,18 @@ void QCocoaWindow::setGeometry(const QRect &rect)
qDebug() << "QCocoaWindow::setGeometry" << this << rect;
#endif
QPlatformWindow::setGeometry(rect);
+ setCocoaGeometry(rect);
+}
- NSRect bounds = qt_mac_flipRect(rect, window());
- [m_nsWindow setContentSize : bounds.size];
- [m_nsWindow setFrameOrigin : bounds.origin];
+void QCocoaWindow::setCocoaGeometry(const QRect &rect)
+{
+ if (m_nsWindow) {
+ NSRect bounds = qt_mac_flipRect(rect, window());
+ [m_nsWindow setContentSize : bounds.size];
+ [m_nsWindow setFrameOrigin : bounds.origin];
+ } else {
+ [m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
+ }
}
void QCocoaWindow::setVisible(bool visible)
@@ -151,13 +159,16 @@ void QCocoaWindow::setVisible(bool visible)
// Make sure the QWindow has a frame ready before we show the NSWindow.
QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRect(QPoint(), geometry().size()));
- if ([m_nsWindow canBecomeKeyWindow])
- [m_nsWindow makeKeyAndOrderFront:nil];
- else
- [m_nsWindow orderFront: nil];
+ if (m_nsWindow) {
+ if ([m_nsWindow canBecomeKeyWindow])
+ [m_nsWindow makeKeyAndOrderFront:nil];
+ else
+ [m_nsWindow orderFront: nil];
+ }
} else {
// qDebug() << "close" << this;
- [m_nsWindow orderOut:m_nsWindow];
+ if (m_nsWindow)
+ [m_nsWindow orderOut:m_nsWindow];
}
}
@@ -170,6 +181,8 @@ Qt::WindowFlags QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
void QCocoaWindow::setWindowTitle(const QString &title)
{
QCocoaAutoReleasePool pool;
+ if (!m_nsWindow)
+ return;
CFStringRef windowTitle = QCFString::toCFStringRef(title);
[m_nsWindow setTitle: const_cast<NSString *>(reinterpret_cast<const NSString *>(windowTitle))];
@@ -180,17 +193,21 @@ void QCocoaWindow::raise()
{
//qDebug() << "raise" << this;
// ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm)
- [m_nsWindow orderFront: m_nsWindow];
+ if (m_nsWindow)
+ [m_nsWindow orderFront: m_nsWindow];
}
void QCocoaWindow::lower()
{
- [m_nsWindow orderBack: m_nsWindow];
+ if (m_nsWindow)
+ [m_nsWindow orderBack: m_nsWindow];
}
void QCocoaWindow::propagateSizeHints()
{
QCocoaAutoReleasePool pool;
+ if (!m_nsWindow)
+ return;
[m_nsWindow setMinSize : qt_mac_toNSSize(window()->minimumSize())];
[m_nsWindow setMaxSize : qt_mac_toNSSize(window()->maximumSize())];
@@ -213,6 +230,9 @@ void QCocoaWindow::propagateSizeHints()
bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
{
+ if (!m_nsWindow)
+ return false;
+
if (grab && ![m_nsWindow isKeyWindow])
[m_nsWindow makeKeyWindow];
else if (!grab && [m_nsWindow isKeyWindow])
@@ -222,6 +242,9 @@ bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
bool QCocoaWindow::setMouseGrabEnabled(bool grab)
{
+ if (!m_nsWindow)
+ return false;
+
if (grab && ![m_nsWindow isKeyWindow])
[m_nsWindow makeKeyWindow];
else if (!grab && [m_nsWindow isKeyWindow])
@@ -231,23 +254,19 @@ bool QCocoaWindow::setMouseGrabEnabled(bool grab)
WId QCocoaWindow::winId() const
{
- return WId(m_nsWindow);
+ return WId(m_contentView);
}
-void QCocoaWindow::setParent(const QPlatformWindow *window)
+void QCocoaWindow::setParent(const QPlatformWindow *parentWindow)
{
// recreate the window for compatibility
- clearNSWindow(m_nsWindow);
- [m_nsWindow close];
- [m_nsWindow release];
-
- m_nsWindow = createNSWindow();
- setNSWindow(m_nsWindow);
+ recreateWindow(parentWindow);
+ setCocoaGeometry(geometry());
}
NSView *QCocoaWindow::contentView() const
{
- return [m_nsWindow contentView];
+ return m_contentView;
}
void QCocoaWindow::windowWillMove()
@@ -266,6 +285,9 @@ void QCocoaWindow::windowDidMove()
void QCocoaWindow::windowDidResize()
{
+ if (!m_nsWindow)
+ return;
+
NSRect rect = [[m_nsWindow contentView]frame];
// Call setFrameSize which will trigger a frameDidChangeNotification on QNSView.
[[m_nsWindow contentView] setFrameSize:rect.size];
@@ -286,6 +308,27 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
return m_glContext;
}
+void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow)
+{
+ // Remove current window (if any)
+ if (m_nsWindow) {
+ clearNSWindow(m_nsWindow);
+ [m_nsWindow close];
+ [m_nsWindow release];
+ m_nsWindow = 0;
+ }
+
+ if (!parentWindow) {
+ // Create a new NSWindow if this is a top-level window.
+ m_nsWindow = createNSWindow();
+ setNSWindow(m_nsWindow);
+ } else {
+ // Child windows have no NSWindow, link the NSViews instead.
+ const QCocoaWindow *parentCococaWindow = static_cast<const QCocoaWindow *>(parentWindow);
+ [parentCococaWindow->m_contentView addSubview : m_contentView];
+ }
+}
+
NSWindow * QCocoaWindow::createNSWindow()
{
QCocoaAutoReleasePool pool;
@@ -378,6 +421,9 @@ void QCocoaWindow::clearNSWindow(NSWindow *window)
// Returns the current global screen geometry for the nswindow associated with this window.
QRect QCocoaWindow::windowGeometry() const
{
+ if (!m_nsWindow)
+ return geometry();
+
NSRect rect = [m_nsWindow frame];
QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window());
int flippedY = onScreen->geometry().height() - rect.origin.y - rect.size.height; // account for nswindow inverted y.