diff options
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 8 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 33 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 18 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp | 4 |
6 files changed, 60 insertions, 9 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 55f94df45a..e756c375f3 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -202,6 +202,14 @@ static void cleanupCocoaApplicationDelegate() if ([self canQuit]) { if (!startedQuit) { startedQuit = true; + // Close open windows. This is done in order to deliver de-expose + // events while the event loop is still running. + const QWindowList topLevels = QGuiApplication::topLevelWindows(); + for (int i = 0; i < topLevels.size(); ++i) { + QWindow *window = topLevels.at(i); + topLevels.at(i)->close(); + } + QGuiApplication::exit(0); startedQuit = false; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 324a43c8ae..7140a68d49 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -108,6 +108,7 @@ public: void setWindowIcon(const QIcon &icon); void raise(); void lower(); + bool isExposed() const; void propagateSizeHints(); void setOpacity(qreal level); void setMask(const QRegion ®ion); @@ -143,6 +144,8 @@ public: QCocoaMenuBar *menubar() const; qreal devicePixelRatio() const; + void exposeWindow(); + void obscureWindow(); protected: // NSWindow handling. The QCocoaWindow/QNSView can either be displayed // in an existing NSWindow or in one created by Qt. @@ -174,6 +177,7 @@ public: // for QNSView bool m_hasModalSession; bool m_frameStrutEventsEnabled; + bool m_isExposed; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 45100f9906..7c665a35c5 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -194,6 +194,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_menubar(0) , m_hasModalSession(false) , m_frameStrutEventsEnabled(false) + , m_isExposed(false) { #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QCocoaWindow::QCocoaWindow" << this; @@ -273,9 +274,12 @@ void QCocoaWindow::setVisible(bool visible) } - // Make sure the QWindow has a frame ready before we show the NSWindow. - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); - QWindowSystemInterface::flushWindowSystemEvents(); + // This call is here to handle initial window show correctly: + // - top-level windows need to have backing store content ready when the + // window is shown, sendin the expose event here makes that more likely. + // - QNSViews for child windows are initialy not hidden and won't get the + // viewDidUnhide message. + exposeWindow(); if (m_nsWindow) { // setWindowState might have been called while the window was hidden and @@ -327,8 +331,6 @@ void QCocoaWindow::setVisible(bool visible) } else { [m_contentView setHidden:YES]; } - if (!QCoreApplication::closingDown()) - QWindowSystemInterface::handleExposeEvent(window(), QRegion()); } } @@ -478,6 +480,11 @@ void QCocoaWindow::lower() [m_nsWindow orderBack: m_nsWindow]; } +bool QCocoaWindow::isExposed() const +{ + return m_isExposed; +} + void QCocoaWindow::propagateSizeHints() { QCocoaAutoReleasePool pool; @@ -847,6 +854,22 @@ qreal QCocoaWindow::devicePixelRatio() const } } +void QCocoaWindow::exposeWindow() +{ + if (!m_isExposed) { + m_isExposed = true; + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); + } +} + +void QCocoaWindow::obscureWindow() +{ + if (m_isExposed) { + m_isExposed = false; + QWindowSystemInterface::handleExposeEvent(window(), QRegion()); + } +} + QMargins QCocoaWindow::frameMargins() const { NSRect frameW = [m_nsWindow frame]; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index b4b3379a82..2175b24e98 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -79,6 +79,8 @@ QT_END_NAMESPACE - (void)drawRect:(NSRect)dirtyRect; - (void)updateGeometry; - (void)windowNotification : (NSNotification *) windowNotification; +- (void)viewDidHide; +- (void)viewDidUnhide; - (BOOL)isFlipped; - (BOOL)acceptsFirstResponder; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 1d59592e7d..a50cc34893 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -227,10 +227,10 @@ static QTouchDevice *touchDevice = 0; QWindowSystemInterface::handleWindowStateChanged(m_window, Qt::WindowMinimized); } else if (notificationName == NSWindowDidDeminiaturizeNotification) { QWindowSystemInterface::handleWindowStateChanged(m_window, Qt::WindowNoState); - // Qt expects an expose event after restore/deminiaturize. This also needs - // to be a non-synchronous event to make sure it gets processed after - // the state change event sent above. - QWindowSystemInterface::handleExposeEvent(m_window, QRegion(m_window->geometry())); + } else if ([notificationName isEqualToString: @"NSWindowDidOrderOffScreenNotification"]) { + m_platformWindow->obscureWindow(); + } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) { + m_platformWindow->exposeWindow(); } else { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 @@ -246,6 +246,16 @@ static QTouchDevice *touchDevice = 0; } } +- (void)viewDidHide +{ + m_platformWindow->obscureWindow(); +} + +- (void)viewDidUnhide +{ + m_platformWindow->exposeWindow(); +} + - (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset { m_backingStore = backingStore; diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp index f16fe49712..2d3e3c1702 100644 --- a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp +++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp @@ -103,6 +103,10 @@ void tst_QToolTip::task183679() QFETCH(Qt::Key, key); QFETCH(bool, visible); +#ifdef Q_OS_MAC + QSKIP("This test fails in the CI system, QTBUG-30040"); +#endif + Widget_task183679 widget; widget.show(); QApplication::setActiveWindow(&widget); |