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:
parent
3d8a70c045
commit
eecf64f61d
@ -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;
|
||||||
|
@ -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,31 +673,19 @@ 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.
|
// Clean up autoreleased temp objects from orderFront immediately.
|
||||||
// The only solution is to remove and add the child window.
|
// Failure to do so has been observed to cause leaks also beyond any outer
|
||||||
// This will place it on top of all the other NSWindows.
|
// autorelease pool (for example around a complete QWindow
|
||||||
NSWindow *parentNSWindow = m_view.window.parentWindow;
|
// construct-show-raise-hide-delete cyle), counter to expected autoreleasepool
|
||||||
[parentNSWindow removeChildWindow:m_view.window];
|
// behavior.
|
||||||
[parentNSWindow addChildWindow:m_view.window ordered:NSWindowAbove];
|
QMacAutoReleasePool pool;
|
||||||
} else {
|
[m_view.window orderFront:m_view.window];
|
||||||
{
|
}
|
||||||
// Clean up autoreleased temp objects from orderFront immediately.
|
static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
|
||||||
// Failure to do so has been observed to cause leaks also beyond any outer
|
if (raiseProcess) {
|
||||||
// autorelease pool (for example around a complete QWindow
|
[NSApp activateIgnoringOtherApps:YES];
|
||||||
// construct-show-raise-hide-delete cyle), counter to expected autoreleasepool
|
|
||||||
// behavior.
|
|
||||||
QMacAutoReleasePool pool;
|
|
||||||
[m_view.window orderFront:m_view.window];
|
|
||||||
}
|
|
||||||
static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
|
|
||||||
if (raiseProcess) {
|
|
||||||
[NSApp activateIgnoringOtherApps:YES];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -830,26 +696,8 @@ void QCocoaWindow::lower()
|
|||||||
if (!isContentView())
|
if (!isContentView())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (isChildNSWindow() && m_hiddenByClipping)
|
if (m_view.window.visible)
|
||||||
return;
|
[m_view.window orderBack:m_view.window];
|
||||||
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user