diff options
author | Morten Johan Sørvig <morten.sorvig@digia.com> | 2013-11-25 09:03:42 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-12-04 14:48:21 +0100 |
commit | c6874106850f64c9d1b38238988110bdd4198336 (patch) | |
tree | a50696155ff3c9ad8544828f8e08a60c124cc1ef /src/plugins/platforms | |
parent | 1983bc9c374fc8b83f608ecc1e6ce6ef4f54e572 (diff) |
Improve expose event handling.
Prevent the cocoa platform plugin from sending expose
events for windows that are off-screen or has invalid
geometry.
Differentiate between initial exposes and geometry
update exposes, in order that e.g. geometry updates
that happen before setVisible() don't trigger expose
events. After the initial expose geometry updates
to and from invalid geometry will trigger obscure
and expose events.
Task-number: QTBUG-35143
Task-number: QTBUG-35091
Change-Id: Ibbff20c69974f098ea7635e9ca38620597840a05
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoawindow.mm | 42 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qnsview.mm | 6 |
3 files changed, 48 insertions, 4 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 4f5a208f43..c7ec315f04 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -159,8 +159,10 @@ public: void registerTouch(bool enable); qreal devicePixelRatio() const; + bool isWindowExposable(); void exposeWindow(); void obscureWindow(); + void updateExposedGeometry(); QWindow *childWindowAt(QPoint windowPoint); protected: // NSWindow handling. The QCocoaWindow/QNSView can either be displayed @@ -202,7 +204,9 @@ public: // for QNSView bool m_hasModalSession; bool m_frameStrutEventsEnabled; + bool m_geometryUpdateExposeAllowed; bool m_isExposed; + QRect m_exposedGeometry; int m_registerTouchCount; bool m_resizableTransientParent; bool m_overrideBecomeKey; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 4da47f4f1f..de99ecf5a5 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -213,6 +213,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_windowCursor(0) , m_hasModalSession(false) , m_frameStrutEventsEnabled(false) + , m_geometryUpdateExposeAllowed(false) , m_isExposed(false) , m_registerTouchCount(0) , m_resizableTransientParent(false) @@ -1078,22 +1079,61 @@ qreal QCocoaWindow::devicePixelRatio() const } } +// Returns whether the window can be expose, which it can +// if it is on screen and has a valid geometry. +bool QCocoaWindow::isWindowExposable() +{ + QSize size = geometry().size(); + bool validGeometry = (size.width() > 0 && size.height() > 0); + bool validScreen = ([[m_contentView window] screen] != 0); + bool nonHiddenSuperView = ![[m_contentView superview] isHidden]; + return (validGeometry && validScreen && nonHiddenSuperView); +} + +// Exposes the window by posting an expose event to QWindowSystemInterface void QCocoaWindow::exposeWindow() { - if (!m_isExposed && ![[m_contentView superview] isHidden]) { + m_geometryUpdateExposeAllowed = true; + + if (!isWindowExposable()) + return; + + if (!m_isExposed) { m_isExposed = true; + m_exposedGeometry = geometry(); QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); } } +// Obscures the window by posting an empty expose event to QWindowSystemInterface void QCocoaWindow::obscureWindow() { if (m_isExposed) { + m_geometryUpdateExposeAllowed = false; m_isExposed = false; QWindowSystemInterface::handleExposeEvent(window(), QRegion()); } } +// Updates window geometry by posting an expose event to QWindowSystemInterface +void QCocoaWindow::updateExposedGeometry() +{ + // updateExposedGeometry is not allowed to send the initial expose. If you want + // that call exposeWindow(); + if (!m_geometryUpdateExposeAllowed) + return; + + if (!isWindowExposable()) + return; + + if (m_exposedGeometry == geometry()) + return; + + m_isExposed = true; + m_exposedGeometry = geometry(); + QWindowSystemInterface::handleExposeEvent(window(), QRegion(geometry())); +} + QWindow *QCocoaWindow::childWindowAt(QPoint windowPoint) { QWindow *targetWindow = window(); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 71c4de3b69..1c15c3b561 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -175,7 +175,7 @@ static QTouchDevice *touchDevice = 0; - (void) globalFrameChanged:(NSNotification*)notification { Q_UNUSED(notification); - QWindowSystemInterface::handleExposeEvent(m_window, m_window->geometry()); + m_platformWindow->updateExposedGeometry(); } - (void)viewDidMoveToSuperview @@ -186,7 +186,7 @@ static QTouchDevice *touchDevice = 0; if ([self superview]) { m_platformWindow->m_contentViewIsEmbedded = true; QWindowSystemInterface::handleGeometryChange(m_window, m_platformWindow->geometry()); - QWindowSystemInterface::handleExposeEvent(m_window, m_platformWindow->geometry()); + m_platformWindow->updateExposedGeometry(); QWindowSystemInterface::flushWindowSystemEvents(); } else { m_platformWindow->m_contentViewIsEmbedded = false; @@ -261,7 +261,7 @@ static QTouchDevice *touchDevice = 0; // Send a geometry change event to Qt, if it's ready to handle events if (!m_platformWindow->m_inConstructor) { QWindowSystemInterface::handleGeometryChange(m_window, geometry); - QWindowSystemInterface::handleExposeEvent(m_window, geometry); + m_platformWindow->updateExposedGeometry(); QWindowSystemInterface::flushWindowSystemEvents(); } } |