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>
This commit is contained in:
parent
5939cd33af
commit
6d9f04422a
@ -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);
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user