macOS: Remove support for child NSWindows

The private feature was only used by QToolBar to solve QTBUG-33082, but
the solution doesn't work, and complicates the macOS platform plugin
quite a bit.

A better solution is likely to use Core Animation layers, which is a
direction we're going in anyways. To make it easier to modernize the
macOS platform plugin, including moving to using layers, we remove the
child NSWindows codepaths for now.

Change-Id: I4b19464be3980fd84dd7af8316d4d5e85ba813b1
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
This commit is contained in:
Tor Arne Vestbø 2017-06-21 13:05:36 +02:00
parent 3d8a70c045
commit eecf64f61d
5 changed files with 39 additions and 336 deletions

View File

@ -93,10 +93,7 @@ public:
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
QRect geometry() const Q_DECL_OVERRIDE; QRect geometry() const Q_DECL_OVERRIDE;
void setCocoaGeometry(const QRect &rect); void setCocoaGeometry(const QRect &rect);
void clipChildWindows();
void clipWindow(const NSRect &clipRect);
void show(bool becauseOfAncestor = false);
void hide(bool becauseOfAncestor = false);
void setVisible(bool visible) Q_DECL_OVERRIDE; void setVisible(bool visible) Q_DECL_OVERRIDE;
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE; void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
@ -202,7 +199,6 @@ public:
ParentChanged = 0x1, ParentChanged = 0x1,
MissingWindow = 0x2, MissingWindow = 0x2,
WindowModalityChanged = 0x4, WindowModalityChanged = 0x4,
ChildNSWindowChanged = 0x8,
ContentViewChanged = 0x10, ContentViewChanged = 0x10,
PanelChanged = 0x20, PanelChanged = 0x20,
}; };
@ -210,14 +206,10 @@ public:
Q_FLAG(RecreationReasons) Q_FLAG(RecreationReasons)
protected: protected:
void foreachChildNSWindow(void (^block)(QCocoaWindow *));
void recreateWindowIfNeeded(); void recreateWindowIfNeeded();
QCocoaNSWindow *createNSWindow(bool shouldBeChildNSWindow, bool shouldBePanel); QCocoaNSWindow *createNSWindow(bool shouldBePanel);
QRect nativeWindowGeometry() const; QRect nativeWindowGeometry() const;
void reinsertChildWindow(QCocoaWindow *child);
void removeChildWindow(QCocoaWindow *child);
Qt::WindowState windowState() const; Qt::WindowState windowState() const;
void applyWindowState(Qt::WindowStates newState); void applyWindowState(Qt::WindowStates newState);
@ -231,14 +223,12 @@ public: // for QNSView
friend class QCocoaNativeInterface; friend class QCocoaNativeInterface;
bool isContentView() const; bool isContentView() const;
bool isChildNSWindow() const;
bool alwaysShowToolWindow() const; bool alwaysShowToolWindow() const;
void removeMonitor(); void removeMonitor();
NSView *m_view; NSView *m_view;
QCocoaNSWindow *m_nsWindow; QCocoaNSWindow *m_nsWindow;
QPointer<QCocoaWindow> m_forwardWindow;
// TODO merge to one variable if possible // TODO merge to one variable if possible
bool m_viewIsEmbedded; // true if the m_view is actually embedded in a "foreign" NSView hiearchy bool m_viewIsEmbedded; // true if the m_view is actually embedded in a "foreign" NSView hiearchy
@ -268,8 +258,6 @@ public: // for QNSView
qreal m_exposedDevicePixelRatio; qreal m_exposedDevicePixelRatio;
int m_registerTouchCount; int m_registerTouchCount;
bool m_resizableTransientParent; bool m_resizableTransientParent;
bool m_hiddenByClipping;
bool m_hiddenByAncestor;
static const int NoAlertRequest; static const int NoAlertRequest;
NSInteger m_alertRequest; NSInteger m_alertRequest;

View File

@ -96,10 +96,6 @@ static void qRegisterNotificationCallbacks()
NSView *view = nullptr; NSView *view = nullptr;
if ([notification.object isKindOfClass:[NSWindow class]]) { if ([notification.object isKindOfClass:[NSWindow class]]) {
NSWindow *window = notification.object; NSWindow *window = notification.object;
// Only top level NSWindows should notify their QNSViews
if (window.parentWindow)
return;
if (!window.contentView) if (!window.contentView)
return; return;
@ -157,8 +153,6 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle)
, m_isExposed(false) , m_isExposed(false)
, m_registerTouchCount(0) , m_registerTouchCount(0)
, m_resizableTransientParent(false) , m_resizableTransientParent(false)
, m_hiddenByClipping(false)
, m_hiddenByAncestor(false)
, m_alertRequest(NoAlertRequest) , m_alertRequest(NoAlertRequest)
, monitor(nil) , monitor(nil)
, m_drawContentBorderGradient(false) , m_drawContentBorderGradient(false)
@ -207,9 +201,7 @@ QCocoaWindow::~QCocoaWindow()
[m_nsWindow makeFirstResponder:nil]; [m_nsWindow makeFirstResponder:nil];
[m_nsWindow setContentView:nil]; [m_nsWindow setContentView:nil];
[m_nsWindow.helper detachFromPlatformWindow]; [m_nsWindow.helper detachFromPlatformWindow];
if (m_view.window.parentWindow) if ([m_view superview])
[m_view.window.parentWindow removeChildWindow:m_view.window];
else if ([m_view superview])
[m_view removeFromSuperview]; [m_view removeFromSuperview];
removeMonitor(); removeMonitor();
@ -225,10 +217,6 @@ QCocoaWindow::~QCocoaWindow()
QCocoaIntegration::instance()->popupWindowStack()->removeAll(this); QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
} }
foreachChildNSWindow(^(QCocoaWindow *childWindow) {
[m_view.window removeChildWindow:childWindow->nativeWindow()];
});
[m_view release]; [m_view release];
[m_nsWindow release]; [m_nsWindow release];
[m_windowCursor release]; [m_windowCursor release];
@ -301,16 +289,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
return; return;
} }
if (isChildNSWindow()) { if (isContentView()) {
QPlatformWindow::setGeometry(rect);
NSWindow *parentNSWindow = m_view.window.parentWindow;
NSRect parentWindowFrame = [parentNSWindow contentRectForFrameRect:parentNSWindow.frame];
clipWindow(parentWindowFrame);
// call this here: updateGeometry in qnsview.mm is a no-op for this case
QWindowSystemInterface::handleGeometryChange(window(), rect);
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
} else if (isContentView()) {
NSRect bounds = qt_mac_flipRect(rect); NSRect bounds = qt_mac_flipRect(rect);
[m_view.window setFrame:[m_view.window frameRectForContentRect:bounds] display:YES animate:NO]; [m_view.window setFrame:[m_view.window frameRectForContentRect:bounds] display:YES animate:NO];
} else { } else {
@ -323,107 +302,10 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
// will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm)
} }
void QCocoaWindow::clipChildWindows()
{
foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->clipWindow(m_view.window.frame);
});
}
void QCocoaWindow::clipWindow(const NSRect &clipRect)
{
if (!isChildNSWindow())
return;
NSRect clippedWindowRect = NSZeroRect;
if (!NSIsEmptyRect(clipRect)) {
NSRect windowFrame = qt_mac_flipRect(QRect(window()->mapToGlobal(QPoint(0, 0)), geometry().size()));
clippedWindowRect = NSIntersectionRect(windowFrame, clipRect);
// Clipping top/left offsets the content. Move it back.
NSPoint contentViewOffset = NSMakePoint(qMax(CGFloat(0), NSMinX(clippedWindowRect) - NSMinX(windowFrame)),
qMax(CGFloat(0), NSMaxY(windowFrame) - NSMaxY(clippedWindowRect)));
[m_view setBoundsOrigin:contentViewOffset];
}
if (NSIsEmptyRect(clippedWindowRect)) {
if (!m_hiddenByClipping) {
// We dont call hide() here as we will recurse further down
[m_view.window orderOut:nil];
m_hiddenByClipping = true;
}
} else {
[m_view.window setFrame:clippedWindowRect display:YES animate:NO];
if (m_hiddenByClipping) {
m_hiddenByClipping = false;
if (!m_hiddenByAncestor) {
[m_view.window orderFront:nil];
static_cast<QCocoaWindow *>(QPlatformWindow::parent())->reinsertChildWindow(this);
}
}
}
// recurse
foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->clipWindow(clippedWindowRect);
});
}
void QCocoaWindow::hide(bool becauseOfAncestor)
{
Q_ASSERT(isContentView());
bool visible = m_view.window.visible;
if (!m_hiddenByAncestor && !visible) // Already explicitly hidden
return;
if (m_hiddenByAncestor && becauseOfAncestor) // Trying to hide some child again
return;
m_hiddenByAncestor = becauseOfAncestor;
if (!visible) // Could have been clipped before
return;
foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->hide(true);
});
[m_view.window orderOut:nil];
}
void QCocoaWindow::show(bool becauseOfAncestor)
{
Q_ASSERT(isContentView());
if (m_view.window.visible)
return;
if (m_view.window.parentWindow && !m_view.window.parentWindow.visible) {
m_hiddenByAncestor = true; // Parent still hidden, don't show now
} else if ((becauseOfAncestor == m_hiddenByAncestor) // Was NEITHER explicitly hidden
&& !m_hiddenByClipping) { // ... NOR clipped
if (isChildNSWindow()) {
m_hiddenByAncestor = false;
setCocoaGeometry(windowGeometry());
}
if (!m_hiddenByClipping) { // setCocoaGeometry() can change the clipping status
[m_view.window orderFront:nil];
if (isChildNSWindow())
static_cast<QCocoaWindow *>(QPlatformWindow::parent())->reinsertChildWindow(this);
foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->show(true);
});
}
}
}
void QCocoaWindow::setVisible(bool visible) void QCocoaWindow::setVisible(bool visible)
{ {
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setVisible" << window() << visible; qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setVisible" << window() << visible;
if (isChildNSWindow() && m_hiddenByClipping)
return;
m_inSetVisible = true; m_inSetVisible = true;
QMacAutoReleasePool pool; QMacAutoReleasePool pool;
@ -494,12 +376,8 @@ void QCocoaWindow::setVisible(bool visible)
[m_view.window makeKeyAndOrderFront:nil]; [m_view.window makeKeyAndOrderFront:nil];
else else
[m_view.window orderFront:nil]; [m_view.window orderFront:nil];
foreachChildNSWindow(^(QCocoaWindow *childWindow) {
childWindow->show(true);
});
} else { } else {
show(); [m_view.window orderFront:nil];
} }
// We want the events to properly reach the popup, dialog, and tool // We want the events to properly reach the popup, dialog, and tool
@ -544,7 +422,8 @@ void QCocoaWindow::setVisible(bool visible)
} }
} }
hide(); [m_view.window orderOut:nil];
if (m_view.window == [NSApp keyWindow] if (m_view.window == [NSApp keyWindow]
&& !(cocoaEventDispatcherPrivate && cocoaEventDispatcherPrivate->currentModalSession())) { && !(cocoaEventDispatcherPrivate && cocoaEventDispatcherPrivate->currentModalSession())) {
// Probably because we call runModalSession: outside [NSApp run] in QCocoaEventDispatcher // Probably because we call runModalSession: outside [NSApp run] in QCocoaEventDispatcher
@ -689,7 +568,7 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
{ {
if (isContentView() && !isChildNSWindow()) { if (isContentView()) {
// While setting style mask we can have -updateGeometry calls on a content // While setting style mask we can have -updateGeometry calls on a content
// view with null geometry, reporting an invalid coordinates as a result. // view with null geometry, reporting an invalid coordinates as a result.
m_inSetStyleMask = true; m_inSetStyleMask = true;
@ -713,10 +592,9 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
m_view.window.collectionBehavior = behavior; m_view.window.collectionBehavior = behavior;
} }
setWindowZoomButton(flags); setWindowZoomButton(flags);
}
if (isContentView())
m_view.window.ignoresMouseEvents = flags & Qt::WindowTransparentForInput; m_view.window.ignoresMouseEvents = flags & Qt::WindowTransparentForInput;
}
m_windowFlags = flags; m_windowFlags = flags;
} }
@ -795,18 +673,7 @@ void QCocoaWindow::raise()
if (!isContentView()) if (!isContentView())
return; return;
if (isChildNSWindow() && m_hiddenByClipping)
return;
if (m_view.window.visible) { if (m_view.window.visible) {
if (isChildNSWindow()) {
// -[NSWindow orderFront:] doesn't work with attached windows.
// The only solution is to remove and add the child window.
// This will place it on top of all the other NSWindows.
NSWindow *parentNSWindow = m_view.window.parentWindow;
[parentNSWindow removeChildWindow:m_view.window];
[parentNSWindow addChildWindow:m_view.window ordered:NSWindowAbove];
} else {
{ {
// Clean up autoreleased temp objects from orderFront immediately. // Clean up autoreleased temp objects from orderFront immediately.
// Failure to do so has been observed to cause leaks also beyond any outer // Failure to do so has been observed to cause leaks also beyond any outer
@ -822,7 +689,6 @@ void QCocoaWindow::raise()
} }
} }
} }
}
void QCocoaWindow::lower() void QCocoaWindow::lower()
{ {
@ -830,27 +696,9 @@ void QCocoaWindow::lower()
if (!isContentView()) if (!isContentView())
return; return;
if (isChildNSWindow() && m_hiddenByClipping) if (m_view.window.visible)
return;
if (m_view.window.visible) {
if (isChildNSWindow()) {
// -[NSWindow orderBack:] doesn't work with attached windows.
// The only solution is to remove and add all the child windows except this one.
// This will keep the current window at the bottom while adding the others on top of it,
// hopefully in the same order (this is not documented anywhere in the Cocoa documentation).
NSWindow *parentNSWindow = m_view.window.parentWindow;
NSArray *children = [parentNSWindow.childWindows copy];
for (NSWindow *child in children)
if (m_view.window != child) {
[parentNSWindow removeChildWindow:child];
[parentNSWindow addChildWindow:child ordered:NSWindowAbove];
}
} else {
[m_view.window orderBack:m_view.window]; [m_view.window orderBack:m_view.window];
} }
}
}
bool QCocoaWindow::isExposed() const bool QCocoaWindow::isExposed() const
{ {
@ -998,9 +846,6 @@ void QCocoaWindow::windowWillMove()
void QCocoaWindow::windowDidMove() void QCocoaWindow::windowDidMove()
{ {
if (isChildNSWindow())
return;
[qnsview_cast(m_view) updateGeometry]; [qnsview_cast(m_view) updateGeometry];
// Moving a window might bring it out of maximized state // Moving a window might bring it out of maximized state
@ -1012,10 +857,6 @@ void QCocoaWindow::windowDidResize()
if (!isContentView()) if (!isContentView())
return; return;
if (isChildNSWindow())
return;
clipChildWindows();
[qnsview_cast(m_view) updateGeometry]; [qnsview_cast(m_view) updateGeometry];
if (!m_view.inLiveResize) if (!m_view.inLiveResize)
@ -1215,16 +1056,6 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
} }
#endif #endif
/*!
Checks if the window is a non-top level QWindow with a NSWindow.
\sa _q_platform_MacUseNSWindow, QT_MAC_USE_NSWINDOW
*/
bool QCocoaWindow::isChildNSWindow() const
{
return m_view.window.parentWindow != nil;
}
/*! /*!
Checks if the window is the content view of its immediate NSWindow. Checks if the window is the content view of its immediate NSWindow.
@ -1232,36 +1063,18 @@ bool QCocoaWindow::isChildNSWindow() const
the highest accessible NSView object in the window's view the highest accessible NSView object in the window's view
hierarchy. hierarchy.
This can only happen in two cases, either if the QWindow is This is the case if the QWindow is a top level window.
itself a top level window, or if it's a child NSWindow.
\sa isChildNSWindow
*/ */
bool QCocoaWindow::isContentView() const bool QCocoaWindow::isContentView() const
{ {
return m_view.window.contentView == m_view; return m_view.window.contentView == m_view;
} }
/*!
Iterates child NSWindows that have a corresponding QCocoaWindow.
*/
void QCocoaWindow::foreachChildNSWindow(void (^block)(QCocoaWindow *))
{
NSArray *windows = m_view.window.childWindows;
[windows enumerateObjectsUsingBlock:^(NSWindow *window, NSUInteger index, BOOL *stop) {
Q_UNUSED(index);
Q_UNUSED(stop);
if (QNSView *view = qnsview_cast(window.contentView))
block(view.platformWindow);
}];
}
/*! /*!
Recreates (or removes) the NSWindow for this QWindow, if needed. Recreates (or removes) the NSWindow for this QWindow, if needed.
A QWindow may need a corresponding NSWindow, depending on whether A QWindow may need a corresponding NSWindow/NSPanel, depending on
or not it's a top level or not (or explicitly set to be a child whether or not it's a top level or not, window flags, etc.
NSWindow), whether it is a NSPanel or not, etc.
*/ */
void QCocoaWindow::recreateWindowIfNeeded() void QCocoaWindow::recreateWindowIfNeeded()
{ {
@ -1287,19 +1100,13 @@ void QCocoaWindow::recreateWindowIfNeeded()
if (m_windowModality != window()->modality()) if (m_windowModality != window()->modality())
recreateReason |= WindowModalityChanged; recreateReason |= WindowModalityChanged;
const bool shouldBeChildNSWindow = parentWindow && qt_mac_resolveOption(NO, const bool shouldBeContentView = !parentWindow && !m_viewIsEmbedded;
window(), "_q_platform_MacUseNSWindow", "QT_MAC_USE_NSWINDOW");
if (isChildNSWindow() != shouldBeChildNSWindow)
recreateReason |= ChildNSWindowChanged;
const bool shouldBeContentView = (!parentWindow && !m_viewIsEmbedded) || shouldBeChildNSWindow;
if (isContentView() != shouldBeContentView) if (isContentView() != shouldBeContentView)
recreateReason |= ContentViewChanged; recreateReason |= ContentViewChanged;
Qt::WindowType type = window()->type(); Qt::WindowType type = window()->type();
const bool isPanel = isContentView() && [m_view.window isKindOfClass:[QNSPanel class]]; const bool isPanel = isContentView() && [m_view.window isKindOfClass:[QNSPanel class]];
const bool shouldBePanel = shouldBeContentView && !shouldBeChildNSWindow && const bool shouldBePanel = shouldBeContentView &&
((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog); ((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog);
if (isPanel != shouldBePanel) if (isPanel != shouldBePanel)
@ -1314,21 +1121,10 @@ void QCocoaWindow::recreateWindowIfNeeded()
QCocoaWindow *parentCocoaWindow = static_cast<QCocoaWindow *>(parentWindow); QCocoaWindow *parentCocoaWindow = static_cast<QCocoaWindow *>(parentWindow);
if (shouldBeChildNSWindow) {
QWindow *parentQWindow = parentWindow->window();
// Ensure that all parents in the hierarchy are also child NSWindows
if (!parentQWindow->property("_q_platform_MacUseNSWindow").toBool()) {
parentQWindow->setProperty("_q_platform_MacUseNSWindow", QVariant(true));
parentCocoaWindow->recreateWindowIfNeeded();
}
}
// Remove current window (if any) // Remove current window (if any)
if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) { if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) {
qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow; qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow;
[m_nsWindow closeAndRelease]; [m_nsWindow closeAndRelease];
if (isChildNSWindow())
[m_view.window.parentWindow removeChildWindow:m_view.window];
if (isContentView()) { if (isContentView()) {
// We explicitly disassociate m_view from the window's contentView, // We explicitly disassociate m_view from the window's contentView,
// as AppKit does not automatically do this in response to removing // as AppKit does not automatically do this in response to removing
@ -1343,13 +1139,7 @@ void QCocoaWindow::recreateWindowIfNeeded()
bool noPreviousWindow = m_nsWindow == 0; bool noPreviousWindow = m_nsWindow == 0;
QCocoaNSWindow *newWindow = nullptr; QCocoaNSWindow *newWindow = nullptr;
if (noPreviousWindow) if (noPreviousWindow)
newWindow = createNSWindow(shouldBeChildNSWindow, shouldBePanel); newWindow = createNSWindow(shouldBePanel);
if (m_view.window.parentWindow) {
if (!shouldBeChildNSWindow || (recreateReason & ParentChanged))
[m_view.window.parentWindow removeChildWindow:m_view.window];
m_forwardWindow = oldParentCocoaWindow;
}
// Move view to new NSWindow if needed // Move view to new NSWindow if needed
if (newWindow) { if (newWindow) {
@ -1371,15 +1161,6 @@ void QCocoaWindow::recreateWindowIfNeeded()
setWindowFlags(window()->flags()); setWindowFlags(window()->flags());
setWindowTitle(window()->title()); setWindowTitle(window()->title());
setWindowState(window()->windowState()); setWindowState(window()->windowState());
} else if (shouldBeChildNSWindow) {
if (!m_hiddenByClipping) {
[parentCocoaWindow->nativeWindow() addChildWindow:m_view.window ordered:NSWindowAbove];
parentCocoaWindow->reinsertChildWindow(this);
}
// Set properties after the window has been made a child NSWindow
setCocoaGeometry(windowGeometry());
setWindowFlags(window()->flags());
} else { } else {
// Child windows have no NSWindow, link the NSViews instead. // Child windows have no NSWindow, link the NSViews instead.
[parentCocoaWindow->m_view addSubview:m_view]; [parentCocoaWindow->m_view addSubview:m_view];
@ -1403,25 +1184,6 @@ void QCocoaWindow::recreateWindowIfNeeded()
updateNSToolbar(); updateNSToolbar();
} }
void QCocoaWindow::reinsertChildWindow(QCocoaWindow *child)
{
const QObjectList &childWindows = window()->children();
int childIndex = childWindows.indexOf(child->window());
Q_ASSERT(childIndex != -1);
for (int i = childIndex; i < childWindows.size(); ++i) {
QWindow *window = static_cast<QWindow *>(childWindows.at(i));
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
if (!cocoaWindow)
continue;
NSWindow *nsChild = cocoaWindow->nativeWindow();
if (i != childIndex)
[m_view.window removeChildWindow:nsChild];
[m_view.window addChildWindow:nsChild ordered:NSWindowAbove];
}
}
void QCocoaWindow::requestActivateWindow() void QCocoaWindow::requestActivateWindow()
{ {
NSWindow *window = [m_view window]; NSWindow *window = [m_view window];
@ -1429,9 +1191,9 @@ void QCocoaWindow::requestActivateWindow()
[window makeKeyWindow]; [window makeKeyWindow];
} }
QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool shouldBePanel) QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
{ {
qCDebug(lcQpaCocoaWindow) << "createNSWindow" << shouldBeChildNSWindow << shouldBePanel; qCDebug(lcQpaCocoaWindow) << "createNSWindow, shouldBePanel =" << shouldBePanel;
QMacAutoReleasePool pool; QMacAutoReleasePool pool;
@ -1464,20 +1226,17 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh
// Create NSWindow // Create NSWindow
Class windowClass = shouldBePanel ? [QNSPanel class] : [QNSWindow class]; Class windowClass = shouldBePanel ? [QNSPanel class] : [QNSWindow class];
NSUInteger styleMask = shouldBeChildNSWindow ? NSBorderlessWindowMask : windowStyleMask(flags);
QCocoaNSWindow *window = [[windowClass alloc] initWithContentRect:frame QCocoaNSWindow *window = [[windowClass alloc] initWithContentRect:frame
screen:cocoaScreen->nativeScreen() styleMask:styleMask qPlatformWindow:this]; screen:cocoaScreen->nativeScreen() styleMask:windowStyleMask(flags) qPlatformWindow:this];
window.restorable = NO; window.restorable = NO;
window.level = shouldBeChildNSWindow ? NSNormalWindowLevel : windowLevel(flags); window.level = windowLevel(flags);
if (!isOpaque()) { if (!isOpaque()) {
window.backgroundColor = [NSColor clearColor]; window.backgroundColor = [NSColor clearColor];
window.opaque = NO; window.opaque = NO;
} }
Q_ASSERT(!(shouldBePanel && shouldBeChildNSWindow));
if (shouldBePanel) { if (shouldBePanel) {
// Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set // Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set
window.hidesOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && !alwaysShowToolWindow(); window.hidesOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && !alwaysShowToolWindow();
@ -1489,13 +1248,6 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh
window.hasShadow = YES; window.hasShadow = YES;
window.animationBehavior = NSWindowAnimationBehaviorUtilityWindow; window.animationBehavior = NSWindowAnimationBehaviorUtilityWindow;
} }
} else if (shouldBeChildNSWindow) {
window.collectionBehavior =
NSWindowCollectionBehaviorManaged
| NSWindowCollectionBehaviorIgnoresCycle
| NSWindowCollectionBehaviorFullScreenAuxiliary;
window.hasShadow = NO;
window.animationBehavior = NSWindowAnimationBehaviorNone;
} }
// Persist modality so we can detect changes later on // Persist modality so we can detect changes later on
@ -1522,7 +1274,7 @@ void QCocoaWindow::removeMonitor()
// Returns the current global screen geometry for the nswindow associated with this window. // Returns the current global screen geometry for the nswindow associated with this window.
QRect QCocoaWindow::nativeWindowGeometry() const QRect QCocoaWindow::nativeWindowGeometry() const
{ {
if (!isContentView() || isChildNSWindow()) if (!isContentView())
return geometry(); return geometry();
NSRect rect = m_view.window.frame; NSRect rect = m_view.window.frame;

View File

@ -281,20 +281,7 @@ static QTouchDevice *touchDevice = 0;
QRect geometry; QRect geometry;
if (self.window.parentWindow) { if (m_platformWindow->isContentView()) {
return;
#if 0
//geometry = QRectF::fromCGRect([self frame]).toRect();
qDebug() << "nsview updateGeometry" << m_platformWindow->window();
QRect screenRect = QRectF::fromCGRect([m_platformWindow->nativeWindow() convertRectToScreen:[self frame]]).toRect();
qDebug() << "screenRect" << screenRect;
screenRect.moveTop(qt_mac_flipYCoordinate(screenRect.y() + screenRect.height()));
geometry = QRect(m_platformWindow->window()->parent()->mapFromGlobal(screenRect.topLeft()), screenRect.size());
qDebug() << "geometry" << geometry;
#endif
//geometry = QRect(screenRect.origin.x, qt_mac_flipYCoordinate(screenRect.origin.y + screenRect.size.height), screenRect.size.width, screenRect.size.height);
} else if (m_platformWindow->isContentView()) {
// top level window, get window rect and flip y. // top level window, get window rect and flip y.
NSRect rect = [self frame]; NSRect rect = [self frame];
NSRect windowRect = [[self window] frame]; NSRect windowRect = [[self window] frame];
@ -639,12 +626,6 @@ static QTouchDevice *touchDevice = 0;
QPointF qtWindowPoint; QPointF qtWindowPoint;
QPointF qtScreenPoint; QPointF qtScreenPoint;
QNSView *targetView = self; QNSView *targetView = self;
if (m_platformWindow && m_platformWindow->m_forwardWindow) {
if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)
targetView = qnsview_cast(m_platformWindow->m_forwardWindow->view());
else
m_platformWindow->m_forwardWindow.clear();
}
if (!targetView.platformWindow) if (!targetView.platformWindow)
return; return;

View File

@ -118,22 +118,6 @@ static bool isMouseEvent(NSEvent *ev)
- (void)handleWindowEvent:(NSEvent *)theEvent - (void)handleWindowEvent:(NSEvent *)theEvent
{ {
QCocoaWindow *pw = self.platformWindow;
if (pw && pw->m_forwardWindow) {
if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) {
QNSView *forwardView = qnsview_cast(pw->view());
if (theEvent.type == NSLeftMouseUp) {
[forwardView mouseUp:theEvent];
pw->m_forwardWindow.clear();
} else {
[forwardView mouseDragged:theEvent];
}
}
if (pw->window()->isTopLevel() && theEvent.type == NSLeftMouseDown) {
pw->m_forwardWindow.clear();
}
}
if (theEvent.type == NSLeftMouseDown) { if (theEvent.type == NSLeftMouseDown) {
self.grabbingMouse = YES; self.grabbingMouse = YES;
} else if (theEvent.type == NSLeftMouseUp) { } else if (theEvent.type == NSLeftMouseUp) {
@ -157,7 +141,8 @@ static bool isMouseEvent(NSEvent *ev)
if (!self.platformWindow) if (!self.platformWindow)
return; // Platform window went away while processing event return; // Platform window went away while processing event
if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) { QCocoaWindow *pw = self.platformWindow;
if (pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
NSPoint loc = [theEvent locationInWindow]; NSPoint loc = [theEvent locationInWindow];
NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]]; NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]];
NSRect contentFrame = [[self.window contentView] frame]; NSRect contentFrame = [[self.window contentView] frame];
@ -217,10 +202,8 @@ static const bool kNoDefer = NO;
- (BOOL)canBecomeKeyWindow - (BOOL)canBecomeKeyWindow
{ {
// Prevent child NSWindows from becoming the key window in
// order keep the active apperance of the top-level window.
QCocoaWindow *pw = self.helper.platformWindow; QCocoaWindow *pw = self.helper.platformWindow;
if (!pw || !pw->window()->isTopLevel()) if (!pw)
return NO; return NO;
if (pw->shouldRefuseKeyWindowAndFirstResponder()) if (pw->shouldRefuseKeyWindowAndFirstResponder())
@ -239,7 +222,7 @@ static const bool kNoDefer = NO;
// Windows with a transient parent (such as combobox popup windows) // Windows with a transient parent (such as combobox popup windows)
// cannot become the main window: // cannot become the main window:
QCocoaWindow *pw = self.helper.platformWindow; QCocoaWindow *pw = self.helper.platformWindow;
if (!pw || !pw->window()->isTopLevel() || pw->window()->transientParent()) if (!pw || pw->window()->transientParent())
canBecomeMain = NO; canBecomeMain = NO;
return canBecomeMain; return canBecomeMain;

View File

@ -85,7 +85,6 @@ void QToolBarPrivate::init()
q->setBackgroundRole(QPalette::Button); q->setBackgroundRole(QPalette::Button);
q->setAttribute(Qt::WA_Hover); q->setAttribute(Qt::WA_Hover);
q->setAttribute(Qt::WA_X11NetWmWindowTypeToolBar); q->setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
q->setProperty("_q_platform_MacUseNSWindow", QVariant(true));
QStyle *style = q->style(); QStyle *style = q->style();
int e = style->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q); int e = style->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q);