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>
This commit is contained in:
Richard Moe Gustavsen 2013-01-25 11:49:34 +01:00 committed by Tor Arne Vestbø
parent f2c52d6560
commit 38e6d5a915
2 changed files with 34 additions and 11 deletions

View File

@ -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

View File

@ -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