summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h7
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm117
-rw-r--r--tests/manual/cocoa/qt_on_cocoa/main.mm13
-rw-r--r--tests/manual/cocoa/qt_on_cocoa/rasterwindow.cpp5
4 files changed, 92 insertions, 50 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index c650c86379..a93a391358 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -134,11 +134,12 @@ public:
void setEmbeddedInForeignView(bool subwindow);
+ Q_NOTIFICATION_HANDLER(NSViewFrameDidChangeNotification) void viewDidChangeFrame();
+ Q_NOTIFICATION_HANDLER(NSViewGlobalFrameDidChangeNotification) void viewDidChangeGlobalFrame();
+
Q_NOTIFICATION_HANDLER(NSWindowWillMoveNotification) void windowWillMove();
Q_NOTIFICATION_HANDLER(NSWindowDidMoveNotification) void windowDidMove();
Q_NOTIFICATION_HANDLER(NSWindowDidResizeNotification) void windowDidResize();
- Q_NOTIFICATION_HANDLER(NSViewFrameDidChangeNotification) void viewDidChangeFrame();
- Q_NOTIFICATION_HANDLER(NSViewGlobalFrameDidChangeNotification) void viewDidChangeGlobalFrame();
Q_NOTIFICATION_HANDLER(NSWindowDidEndLiveResizeNotification) void windowDidEndLiveResize();
Q_NOTIFICATION_HANDLER(NSWindowDidBecomeKeyNotification) void windowDidBecomeKey();
Q_NOTIFICATION_HANDLER(NSWindowDidResignKeyNotification) void windowDidResignKey();
@@ -148,8 +149,8 @@ public:
Q_NOTIFICATION_HANDLER(NSWindowDidEnterFullScreenNotification) void windowDidEnterFullScreen();
Q_NOTIFICATION_HANDLER(NSWindowWillExitFullScreenNotification) void windowWillExitFullScreen();
Q_NOTIFICATION_HANDLER(NSWindowDidExitFullScreenNotification) void windowDidExitFullScreen();
- Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen();
Q_NOTIFICATION_HANDLER(NSWindowDidOrderOnScreenAndFinishAnimatingNotification) void windowDidOrderOnScreen();
+ Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen();
Q_NOTIFICATION_HANDLER(NSWindowDidChangeOcclusionStateNotification) void windowDidChangeOcclusionState();
Q_NOTIFICATION_HANDLER(NSWindowDidChangeScreenNotification) void windowDidChangeScreen();
Q_NOTIFICATION_HANDLER(NSWindowWillCloseNotification) void windowWillClose();
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 1ef02f5274..a88ec2b0db 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -97,34 +97,30 @@ static void qRegisterNotificationCallbacks()
[center addObserverForName:notificationName.toNSString() object:nil queue:nil
usingBlock:^(NSNotification *notification) {
- NSView *view = nullptr;
+ QVarLengthArray<QCocoaWindow *, 32> cocoaWindows;
if ([notification.object isKindOfClass:[NSWindow class]]) {
- NSWindow *window = notification.object;
- if (!window.contentView)
- return;
-
- view = window.contentView;
+ NSWindow *nsWindow = notification.object;
+ for (const QWindow *window : QGuiApplication::allWindows()) {
+ if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle()))
+ if (cocoaWindow->nativeWindow() == nsWindow)
+ cocoaWindows += cocoaWindow;
+ }
} else if ([notification.object isKindOfClass:[NSView class]]) {
- view = notification.object;
+ if (QNSView *qnsView = qnsview_cast(notification.object))
+ cocoaWindows += qnsView.platformWindow;
} else {
qCWarning(lcQpaCocoaWindow) << "Unhandled notifcation"
<< notification.name << "for" << notification.object;
return;
}
- Q_ASSERT(view);
-
- QCocoaWindow *cocoaWindow = nullptr;
- if (QNSView *qnsView = qnsview_cast(view))
- cocoaWindow = qnsView.platformWindow;
// FIXME: Could be a foreign window, look up by iterating top level QWindows
- if (!cocoaWindow)
- return;
-
- if (!method.invoke(cocoaWindow, Qt::DirectConnection)) {
- qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for"
- << notification.name << "on" << cocoaWindow;
+ for (QCocoaWindow *cocoaWindow : cocoaWindows) {
+ if (!method.invoke(cocoaWindow, Qt::DirectConnection)) {
+ qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for"
+ << notification.name << "on" << cocoaWindow;
+ }
}
}];
}
@@ -844,8 +840,32 @@ void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
m_nsWindow = 0;
}
+// ----------------------- NSView notifications -----------------------
+
+void QCocoaWindow::viewDidChangeFrame()
+{
+ handleGeometryChange();
+}
+
+/*!
+ Callback for NSViewGlobalFrameDidChangeNotification.
+
+ Posted whenever an NSView object that has attached surfaces (that is,
+ NSOpenGLContext objects) moves to a different screen, or other cases
+ where the NSOpenGLContext object needs to be updated.
+*/
+void QCocoaWindow::viewDidChangeGlobalFrame()
+{
+ [m_view setNeedsDisplay:YES];
+}
+
// ----------------------- NSWindow notifications -----------------------
+// Note: The following notifications are delivered to every QCocoaWindow
+// that is a child of the NSWindow that triggered the notification. Each
+// callback should make sure to filter out notifications if they do not
+// apply to that QCocoaWindow, e.g. if the window is not a content view.
+
void QCocoaWindow::windowWillMove()
{
// Close any open popups on window move
@@ -854,6 +874,9 @@ void QCocoaWindow::windowWillMove()
void QCocoaWindow::windowDidMove()
{
+ if (!isContentView())
+ return;
+
handleGeometryChange();
// Moving a window might bring it out of maximized state
@@ -871,30 +894,19 @@ void QCocoaWindow::windowDidResize()
handleWindowStateChanged();
}
-void QCocoaWindow::viewDidChangeFrame()
-{
- handleGeometryChange();
-}
-
-/*!
- Callback for NSViewGlobalFrameDidChangeNotification.
-
- Posted whenever an NSView object that has attached surfaces (that is,
- NSOpenGLContext objects) moves to a different screen, or other cases
- where the NSOpenGLContext object needs to be updated.
-*/
-void QCocoaWindow::viewDidChangeGlobalFrame()
-{
- [m_view setNeedsDisplay:YES];
-}
-
void QCocoaWindow::windowDidEndLiveResize()
{
+ if (!isContentView())
+ return;
+
handleWindowStateChanged();
}
void QCocoaWindow::windowDidBecomeKey()
{
+ if (!isContentView())
+ return;
+
if (isForeignWindow())
return;
@@ -911,6 +923,9 @@ void QCocoaWindow::windowDidBecomeKey()
void QCocoaWindow::windowDidResignKey()
{
+ if (!isContentView())
+ return;
+
if (isForeignWindow())
return;
@@ -927,16 +942,25 @@ void QCocoaWindow::windowDidResignKey()
void QCocoaWindow::windowDidMiniaturize()
{
+ if (!isContentView())
+ return;
+
handleWindowStateChanged();
}
void QCocoaWindow::windowDidDeminiaturize()
{
+ if (!isContentView())
+ return;
+
handleWindowStateChanged();
}
void QCocoaWindow::windowWillEnterFullScreen()
{
+ if (!isContentView())
+ return;
+
// The NSWindow needs to be resizable, otherwise we'll end up with
// the normal window geometry, centered in the middle of the screen
// on a black background. The styleMask will be reset below.
@@ -945,6 +969,9 @@ void QCocoaWindow::windowWillEnterFullScreen()
void QCocoaWindow::windowDidEnterFullScreen()
{
+ if (!isContentView())
+ return;
+
Q_ASSERT_X(m_view.window.qt_fullScreen, "QCocoaWindow",
"FullScreen category processes window notifications first");
@@ -956,6 +983,9 @@ void QCocoaWindow::windowDidEnterFullScreen()
void QCocoaWindow::windowWillExitFullScreen()
{
+ if (!isContentView())
+ return;
+
// The NSWindow needs to be resizable, otherwise we'll end up with
// a weird zoom animation. The styleMask will be reset below.
m_view.window.styleMask |= NSResizableWindowMask;
@@ -963,6 +993,9 @@ void QCocoaWindow::windowWillExitFullScreen()
void QCocoaWindow::windowDidExitFullScreen()
{
+ if (!isContentView())
+ return;
+
Q_ASSERT_X(!m_view.window.qt_fullScreen, "QCocoaWindow",
"FullScreen category processes window notifications first");
@@ -981,14 +1014,14 @@ void QCocoaWindow::windowDidExitFullScreen()
}
}
-void QCocoaWindow::windowDidOrderOffScreen()
+void QCocoaWindow::windowDidOrderOnScreen()
{
- handleExposeEvent(QRegion());
+ [m_view setNeedsDisplay:YES];
}
-void QCocoaWindow::windowDidOrderOnScreen()
+void QCocoaWindow::windowDidOrderOffScreen()
{
- [m_view setNeedsDisplay:YES];
+ handleExposeEvent(QRegion());
}
void QCocoaWindow::windowDidChangeOcclusionState()
@@ -1422,15 +1455,15 @@ QRect QCocoaWindow::nativeWindowGeometry() const
*/
void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
{
+ if (!isContentView())
+ return;
+
const Qt::WindowState currentState = windowState();
const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState);
if (newState == currentState)
return;
- if (!isContentView())
- return;
-
const NSSize contentSize = m_view.frame.size;
if (contentSize.width <= 0 || contentSize.height <= 0) {
// If content view width or height is 0 then the window animations will crash so
diff --git a/tests/manual/cocoa/qt_on_cocoa/main.mm b/tests/manual/cocoa/qt_on_cocoa/main.mm
index 5e3b8fcd39..805ef0d7c2 100644
--- a/tests/manual/cocoa/qt_on_cocoa/main.mm
+++ b/tests/manual/cocoa/qt_on_cocoa/main.mm
@@ -87,8 +87,6 @@
options:NSTrackingActiveInActiveApp | NSTrackingInVisibleRect | NSTrackingCursorUpdate
owner:contentView userInfo:nil]];
- window.contentView = contentView;
-
// Create the QWindow, add its NSView to the content view
m_window = new RasterWindow;
m_window->setObjectName("RasterWindow");
@@ -104,10 +102,15 @@
NSTextField *textField = [[NSTextField alloc] initWithFrame:NSMakeRect(10, 10, 80, 25)];
[(NSView*)childWindow->winId() addSubview:textField];
- [window.contentView addSubview:reinterpret_cast<NSView *>(m_window->winId())];
+ [contentView addSubview:reinterpret_cast<NSView *>(m_window->winId())];
+
+ window.contentView = contentView;
- // Show the NSWindow
- [window makeKeyAndOrderFront:NSApp];
+ // Show the NSWindow delayed, so that we can verify that Qt picks up the right
+ // notifications to expose the window when it does become visible.
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [window makeKeyAndOrderFront:NSApp];
+ });
}
- (void)applicationWillTerminate:(NSNotification *)notification
diff --git a/tests/manual/cocoa/qt_on_cocoa/rasterwindow.cpp b/tests/manual/cocoa/qt_on_cocoa/rasterwindow.cpp
index dca39839dd..6d7cb3e305 100644
--- a/tests/manual/cocoa/qt_on_cocoa/rasterwindow.cpp
+++ b/tests/manual/cocoa/qt_on_cocoa/rasterwindow.cpp
@@ -148,6 +148,11 @@ bool RasterWindow::event(QEvent *e)
void RasterWindow::render()
{
+ if (!isExposed()) {
+ qDebug() << "Skipping render, not exposed";
+ return;
+ }
+
QRect rect(QPoint(), geometry().size());
m_backingStore->resize(rect.size());