diff options
author | Richard Moe Gustavsen <richard.gustavsen@digia.com> | 2013-01-25 11:49:34 +0100 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@digia.com> | 2013-02-27 23:56:06 +0100 |
commit | 38e6d5a91588bfe823ff6bcb19bd356965d328f7 (patch) | |
tree | 3e1ff8e2b766ecf3693b25d7cbcbe1ddc3408818 | |
parent | f2c52d65608d238ad35ca91099a8751e0c37ef52 (diff) |
iOS: add QIOSWindow::windowLevel() to simplify window stacking
When adding modal windows into the mix, raiseOrLower became
even more messy to write. So do it the usual way instead, and
add a windowLevel variable to each QIOSWindow that we
can sort on. The code becomes more readable, and we can handle
more window types correctly.
Change-Id: I348352473a7d8cf9909c17c1b074b2fe3fab9819
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@digia.com>
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/ios/qioswindow.mm | 42 |
2 files changed, 34 insertions, 11 deletions
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h index b3a94a8d0e..2d7c4c9103 100644 --- a/src/plugins/platforms/ios/qioswindow.h +++ b/src/plugins/platforms/ios/qioswindow.h @@ -89,10 +89,11 @@ private: int m_touchId; QRect m_requestedGeometry; - + int m_windowLevel; qreal m_devicePixelRatio; void raiseOrLower(bool raise); + void updateWindowLevel(); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 91e75bc660..4aa6b8a24e 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -321,6 +321,7 @@ QIOSWindow::QIOSWindow(QWindow *window) , m_view([[EAGLView alloc] initWithQIOSWindow:this]) , m_touchId(0) , m_requestedGeometry(QPlatformWindow::geometry()) + , m_windowLevel(0) , m_devicePixelRatio(1.0) { if (isQtApplication()) @@ -355,6 +356,7 @@ void QIOSWindow::setVisible(bool visible) // Since iOS doesn't do window management the way a Qt application // expects, we need to raise and activate windows ourselves: if (visible) { + updateWindowLevel(); requestActivateWindow(); } else { // Activate top-most visible QWindow: @@ -421,10 +423,8 @@ void QIOSWindow::requestActivateWindow() void QIOSWindow::raiseOrLower(bool raise) { - // Re-insert m_view at the correct index among its sibling views (QWindows), and ensure - // that window flags (staysOnTop, popup) are respected. This function assumes that all - // sibling views are sorted correctly. Note: We sort popup and staysOnTop windows at - // the same level: + // Re-insert m_view at the correct index among its sibling views + // (QWindows) according to their current m_windowLevel: if (!isQtApplication()) return; @@ -432,14 +432,12 @@ void QIOSWindow::raiseOrLower(bool raise) if (subviews.count == 1) return; - const Qt::WindowFlags topFlag = (Qt::Popup | Qt::WindowStaysOnTopHint) & ~Qt::Dialog; - bool thisWindowIsTop = topFlag & window()->flags(); - for (int i = int(subviews.count) - 1; i >= 0; --i) { UIView *view = static_cast<UIView *>([subviews objectAtIndex:i]); - bool otherWindowIsTop = topFlag & view.qwindow->flags(); - if ((raise && (thisWindowIsTop || !otherWindowIsTop)) - || (!raise && (thisWindowIsTop && !otherWindowIsTop))) { + if (view.hidden || view == m_view) + continue; + int level = static_cast<QIOSWindow *>(view.qwindow->handle())->m_windowLevel; + if (m_windowLevel > level || (raise && m_windowLevel == level)) { [m_view.superview insertSubview:m_view aboveSubview:view]; return; } @@ -447,6 +445,30 @@ void QIOSWindow::raiseOrLower(bool raise) [m_view.superview insertSubview:m_view atIndex:0]; } +void QIOSWindow::updateWindowLevel() +{ + Qt::WindowType type = static_cast<Qt::WindowType>(int(window()->flags() & Qt::WindowType_Mask)); + + if (type == Qt::ToolTip) + m_windowLevel = 120; + else if (window()->flags() & Qt::WindowStaysOnTopHint) + m_windowLevel = 100; + else if (window()->isModal()) + m_windowLevel = 30; + else if (type & Qt::Popup & ~Qt::Window) + m_windowLevel = 20; + else if (type == Qt::Tool) + m_windowLevel = 10; + else + m_windowLevel = 0; + + // A window should be in at least the same m_windowLevel as its parent: + QWindow *transientParent = window()->transientParent(); + QIOSWindow *transientParentWindow = transientParent ? static_cast<QIOSWindow *>(transientParent->handle()) : 0; + if (transientParentWindow) + m_windowLevel = qMax(transientParentWindow->m_windowLevel, m_windowLevel); +} + void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) { // Keep the status bar in sync with content orientation. This will ensure |