tests/auto/qmdiarea/tst_qmdiarea.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/auto/qmdiarea/tst_qmdiarea.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,2690 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QMdiSubWindow>
+#include <QMdiArea>
+
+#include <QApplication>
+#include <QMainWindow>
+#include <QMenuBar>
+#include <QPushButton>
+#include <QStyle>
+#include <QStyleOption>
+#include <QVBoxLayout>
+#include <QLineEdit>
+#include <QDesktopWidget>
+#include <QDockWidget>
+#include <QScrollBar>
+#include <QTextEdit>
+#ifndef QT_NO_OPENGL
+#include <QtOpenGL>
+#endif
+#include <QMacStyle>
+
+#include "../../shared/util.h"
+
+static const Qt::WindowFlags DefaultWindowFlags
+    = Qt::SubWindow | Qt::WindowSystemMenuHint
+      | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
+
+Q_DECLARE_METATYPE(QMdiArea::WindowOrder)
+Q_DECLARE_METATYPE(QMdiSubWindow *)
+Q_DECLARE_METATYPE(QList<int>)
+Q_DECLARE_METATYPE(QTabWidget::TabPosition)
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+static bool tabBetweenSubWindowsIn(QMdiArea *mdiArea, int tabCount = -1, bool reverse = false)
+{
+    if (!mdiArea) {
+        qWarning("Null pointer to mdi area");
+        return false;
+    }
+
+    QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
+    const bool walkThrough = tabCount == -1;
+
+    if (walkThrough) {
+        QMdiSubWindow *active = reverse ? subWindows.front() : subWindows.back();
+        mdiArea->setActiveSubWindow(active);
+        if (mdiArea->activeSubWindow() != active) {
+            qWarning("Failed to set active sub window");
+            return false;
+        }
+        tabCount = subWindows.size();
+    }
+
+    QWidget *focusWidget = qApp->focusWidget();
+    if (!focusWidget) {
+        qWarning("No focus widget");
+        return false;
+    }
+
+    Qt::KeyboardModifiers modifiers = reverse ? Qt::ShiftModifier : Qt::NoModifier;
+    Qt::Key key;
+#ifdef Q_WS_MAC
+    key = Qt::Key_Meta;
+    modifiers |= Qt::MetaModifier;
+#else
+    key = Qt::Key_Control;
+    modifiers |= Qt::ControlModifier;
+#endif
+
+    QTest::keyPress(focusWidget, key, modifiers);
+    for (int i = 0; i < tabCount; ++i) {
+        QTest::keyPress(focusWidget, reverse ? Qt::Key_Backtab : Qt::Key_Tab, modifiers);
+        if (tabCount > 1)
+            QTest::qWait(500);
+        if (walkThrough) {
+            QRubberBand *rubberBand = qFindChild<QRubberBand *>(mdiArea->viewport());
+            if (!rubberBand) {
+                qWarning("No rubber band");
+                return false;
+            }
+            QMdiSubWindow *subWindow = subWindows.at(reverse ? subWindows.size() -1 - i : i);
+            if (rubberBand->geometry() != subWindow->geometry()) {
+                qWarning("Rubber band has different geometry");
+                return false;
+            }
+        }
+        qApp->processEvents();
+    }
+    QTest::keyRelease(focusWidget, key);
+
+    return true;
+}
+
+static inline QTabBar::Shape tabBarShapeFrom(QTabWidget::TabShape shape, QTabWidget::TabPosition position)
+{
+    const bool rounded = (shape == QTabWidget::Rounded);
+    if (position == QTabWidget::North)
+        return rounded ? QTabBar::RoundedNorth : QTabBar::TriangularNorth;
+    if (position == QTabWidget::South)
+        return rounded ? QTabBar::RoundedSouth : QTabBar::TriangularSouth;
+    if (position == QTabWidget::East)
+        return rounded ? QTabBar::RoundedEast : QTabBar::TriangularEast;
+    if (position == QTabWidget::West)
+        return rounded ? QTabBar::RoundedWest : QTabBar::TriangularWest;
+    return QTabBar::RoundedNorth;
+}
+
+enum Arrangement {
+    Tiled,
+    Cascaded
+};
+
+static bool verifyArrangement(QMdiArea *mdiArea, Arrangement arrangement, const QList<int> &expectedIndices)
+{
+    if (!mdiArea || expectedIndices.isEmpty() || mdiArea->subWindowList().isEmpty())
+        return false;
+
+    const QList<QMdiSubWindow *> subWindows = mdiArea->subWindowList();
+    const QMdiSubWindow *const firstSubWindow = subWindows.at(0);
+
+    switch (arrangement) {
+    case Tiled:
+    {
+        // Calculate the number of rows and columns.
+        const int n = subWindows.count();
+        const int numColumns = qMax(qCeil(qSqrt(qreal(n))), 1);
+        const int numRows = qMax((n % numColumns) ? (n / numColumns + 1) : (n / numColumns), 1);
+
+        // Ensure that the geometry of all the subwindows are as expected by using
+        // QWidget::childAt starting from the middle of the topleft cell and subsequently
+        // adding rowWidth and rowHeight (going from left to right).
+        const int columnWidth = mdiArea->viewport()->width() / numColumns;
+        const int rowHeight = mdiArea->viewport()->height() / numRows;
+        QPoint subWindowPos(columnWidth / 2, rowHeight / 2);
+        for (int i = 0; i < numRows; ++i) {
+            for (int j = 0; j < numColumns; ++j) {
+                const int index = expectedIndices.at(i * numColumns + j);
+                QWidget *actual = mdiArea->viewport()->childAt(subWindowPos);
+                QMdiSubWindow *expected = subWindows.at(index);
+                if (actual != expected && !expected->isAncestorOf(actual))
+                    return false;
+                subWindowPos.rx() += columnWidth;
+            }
+            subWindowPos.rx() = columnWidth / 2;
+            subWindowPos.ry() += rowHeight;
+        }
+        break;
+    }
+    case Cascaded:
+    {
+        // Calculate the delta (dx, dy) between two cascaded subwindows.
+        QStyleOptionTitleBar options;
+        options.initFrom(firstSubWindow);
+        int titleBarHeight = firstSubWindow->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+#ifdef Q_WS_MAC
+        // ### Remove this after the mac style has been fixed
+        if (qobject_cast<QMacStyle *>(firstSubWindow->style()))
+            titleBarHeight -= 4;
+#endif
+        const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
+        const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
+        const int dx = 10;
+
+        // Current activation/stacking order.
+        const QList<QMdiSubWindow *> activationOrderList = mdiArea->subWindowList(QMdiArea::ActivationHistoryOrder);
+
+        // Ensure that the geometry of all the subwindows are as expected by using
+        // QWidget::childAt with the position of the first one and subsequently adding
+        // dx and dy.
+        QPoint subWindowPos(20, 5);
+        foreach (int expectedIndex, expectedIndices) {
+            QMdiSubWindow *expected = subWindows.at(expectedIndex);
+            expected->raise();
+            if (mdiArea->viewport()->childAt(subWindowPos) != expected)
+                return false;
+            expected->lower();
+            subWindowPos.rx() += dx;
+            subWindowPos.ry() += dy;
+        }
+
+        // Restore stacking order.
+        foreach (QMdiSubWindow *subWindow, activationOrderList) {
+            mdiArea->setActiveSubWindow(subWindow);
+            qApp->processEvents();
+        }
+        break;
+    }
+    default:
+        return false;
+    }
+    return true;
+}
+
+class tst_QMdiArea : public QObject
+{
+    Q_OBJECT
+public:
+    tst_QMdiArea();
+public slots:
+    void initTestCase();
+protected slots:
+    void activeChanged(QMdiSubWindow *child);
+
+private slots:
+    // Tests from QWorkspace
+    void subWindowActivated_data();
+    void subWindowActivated();
+    void subWindowActivated2();
+    void subWindowActivatedWithMinimize();
+    void showWindows();
+    void changeWindowTitle();
+    void changeModified();
+    void childSize();
+    void fixedSize();
+    // New tests
+    void minimumSizeHint();
+    void sizeHint();
+    void setActiveSubWindow();
+    void activeSubWindow();
+    void currentSubWindow();
+    void addAndRemoveWindows();
+    void addAndRemoveWindowsWithReparenting();
+    void removeSubWindow_2();
+    void closeWindows();
+    void activateNextAndPreviousWindow();
+    void subWindowList_data();
+    void subWindowList();
+    void setBackground();
+    void setViewport();
+    void tileSubWindows();
+    void cascadeAndTileSubWindows();
+    void resizeMaximizedChildWindows_data();
+    void resizeMaximizedChildWindows();
+    void focusWidgetAfterAddSubWindow();
+    void dontMaximizeSubWindowOnActivation();
+    void delayedPlacement();
+    void iconGeometryInMenuBar();
+    void resizeTimer();
+    void updateScrollBars();
+    void setActivationOrder_data();
+    void setActivationOrder();
+    void tabBetweenSubWindows();
+    void setViewMode();
+    void setTabShape();
+    void setTabPosition_data();
+    void setTabPosition();
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+    void nativeSubWindows();
+#endif
+    void task_209615();
+    void task_236750();
+
+private:
+    QMdiSubWindow *activeWindow;
+    bool accelPressed;
+};
+
+tst_QMdiArea::tst_QMdiArea()
+    : activeWindow(0)
+{
+    qRegisterMetaType<QMdiSubWindow *>();
+}
+
+void tst_QMdiArea::initTestCase()
+{
+#ifdef Q_OS_WINCE //disable magic for WindowsCE
+    qApp->setAutoMaximizeThreshold(-1);
+#endif
+}
+
+// Old QWorkspace tests
+void tst_QMdiArea::activeChanged(QMdiSubWindow *child)
+{
+    activeWindow = child;
+}
+
+void tst_QMdiArea::subWindowActivated_data()
+{
+    // define the test elements we're going to use
+    QTest::addColumn<int>("count");
+
+    // create a first testdata instance and fill it with data
+    QTest::newRow( "data0" ) << 0;
+    QTest::newRow( "data1" ) << 1;
+    QTest::newRow( "data2" ) << 2;
+}
+
+void tst_QMdiArea::subWindowActivated()
+{
+    QMainWindow mw(0) ;
+    mw.menuBar();
+    QMdiArea *workspace = new QMdiArea(&mw);
+    workspace->setObjectName(QLatin1String("testWidget"));
+    mw.setCentralWidget(workspace);
+    QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+    connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+    mw.show();
+    qApp->setActiveWindow(&mw);
+
+    QFETCH( int, count );
+    int i;
+
+    for ( i = 0; i < count; ++i ) {
+        QWidget *widget = new QWidget(workspace, 0);
+        widget->setAttribute(Qt::WA_DeleteOnClose);
+        workspace->addSubWindow(widget)->show();
+        widget->show();
+        qApp->processEvents();
+        QVERIFY( activeWindow == workspace->activeSubWindow() );
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+    }
+
+    QList<QMdiSubWindow *> windows = workspace->subWindowList();
+    QCOMPARE( (int)windows.count(), count );
+
+    for ( i = 0; i < count; ++i ) {
+        QMdiSubWindow *window = windows.at(i);
+        window->showMinimized();
+        qApp->processEvents();
+        QVERIFY( activeWindow == workspace->activeSubWindow() );
+        if ( i == 1 )
+            QVERIFY( activeWindow == window );
+    }
+
+    for ( i = 0; i < count; ++i ) {
+        QMdiSubWindow *window = windows.at(i);
+        window->showNormal();
+        qApp->processEvents();
+        QVERIFY( window == activeWindow );
+        QVERIFY( activeWindow == workspace->activeSubWindow() );
+    }
+    spy.clear();
+
+    while (workspace->activeSubWindow() ) {
+        workspace->activeSubWindow()->close();
+        qApp->processEvents();
+        QVERIFY(activeWindow == workspace->activeSubWindow());
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+    }
+
+    QVERIFY(activeWindow == 0);
+    QVERIFY(workspace->activeSubWindow() == 0);
+    QCOMPARE(workspace->subWindowList().count(), 0);
+
+    {
+        workspace->hide();
+        QWidget *widget = new QWidget(workspace);
+        widget->setAttribute(Qt::WA_DeleteOnClose);
+        QMdiSubWindow *window = workspace->addSubWindow(widget);
+        widget->show();
+        QCOMPARE(spy.count(), 0);
+        workspace->show();
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+        QVERIFY( activeWindow == window );
+        window->close();
+        qApp->processEvents();
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+        QVERIFY( activeWindow == 0 );
+    }
+
+    {
+        workspace->hide();
+        QWidget *widget = new QWidget(workspace);
+        widget->setAttribute(Qt::WA_DeleteOnClose);
+        QMdiSubWindow *window = workspace->addSubWindow(widget);
+        widget->showMaximized();
+        qApp->sendPostedEvents();
+        QCOMPARE(spy.count(), 0);
+        spy.clear();
+        workspace->show();
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+        QVERIFY( activeWindow == window );
+        window->close();
+        qApp->processEvents();
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+        QVERIFY( activeWindow == 0 );
+    }
+
+    {
+        QWidget *widget = new QWidget(workspace);
+        widget->setAttribute(Qt::WA_DeleteOnClose);
+        QMdiSubWindow *window = workspace->addSubWindow(widget);
+        widget->showMinimized();
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+        QVERIFY( activeWindow == window );
+        QVERIFY(workspace->activeSubWindow() == window);
+        window->close();
+        qApp->processEvents();
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+        QVERIFY(workspace->activeSubWindow() == 0);
+        QVERIFY( activeWindow == 0 );
+    }
+}
+
+#ifdef Q_WS_MAC
+#include <Security/AuthSession.h>
+bool macHasAccessToWindowsServer()
+{
+    SecuritySessionId mySession;
+    SessionAttributeBits sessionInfo;
+    SessionGetInfo(callerSecuritySession, &mySession, &sessionInfo);
+    return (sessionInfo & sessionHasGraphicAccess);
+}
+#endif
+
+
+void tst_QMdiArea::subWindowActivated2()
+{
+    QMdiArea mdiArea;
+    QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+    for (int i = 0; i < 5; ++i)
+        mdiArea.addSubWindow(new QWidget);
+    QCOMPARE(spy.count(), 0);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+    QTest::qWait(100);
+
+    QTRY_COMPARE(spy.count(), 5);
+    QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().back());
+    spy.clear();
+
+    // Just to make sure another widget is on top wrt. stacking order.
+    // This will typically become the active window if things are broken.
+    QMdiSubWindow *staysOnTopWindow = mdiArea.subWindowList().at(3);
+    staysOnTopWindow->setWindowFlags(Qt::WindowStaysOnTopHint);
+    mdiArea.setActiveSubWindow(staysOnTopWindow);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(mdiArea.activeSubWindow(), staysOnTopWindow);
+    spy.clear();
+
+    QMdiSubWindow *activeSubWindow = mdiArea.subWindowList().at(2);
+    mdiArea.setActiveSubWindow(activeSubWindow);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+    spy.clear();
+
+    // Check that we only emit _one_ signal and the active window
+    // is unchanged after hide/show.
+    mdiArea.hide();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+    QTest::qWait(100);
+    QTRY_COMPARE(spy.count(), 1);
+    QVERIFY(!mdiArea.activeSubWindow());
+    QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
+    spy.clear();
+
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+    QTest::qWait(100);
+    QTRY_COMPARE(spy.count(), 1);
+    QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+    spy.clear();
+
+    // Check that we only emit _one_ signal and the active window
+    // is unchanged after showMinimized/showNormal.
+    mdiArea.showMinimized();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#elif defined (Q_WS_MAC)
+    if (!macHasAccessToWindowsServer())
+        QEXPECT_FAIL("", "showMinimized doesn't really minimize if you don't have access to the server", Abort);
+#endif
+    QTest::qWait(10);
+#if defined(Q_WS_QWS)
+    QEXPECT_FAIL("", "task 168682", Abort);
+#endif
+#ifdef Q_OS_WINCE
+    QSKIP("Not fixed yet. See Task 197453", SkipAll);
+#endif
+    QTRY_COMPARE(spy.count(), 1);
+    QVERIFY(!mdiArea.activeSubWindow());
+    QCOMPARE(mdiArea.currentSubWindow(), activeSubWindow);
+    spy.clear();
+
+    mdiArea.showNormal();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+    QTest::qWait(100);
+    QTRY_COMPARE(spy.count(), 1);
+    QCOMPARE(mdiArea.activeSubWindow(), activeSubWindow);
+    spy.clear();
+}
+
+void tst_QMdiArea::subWindowActivatedWithMinimize()
+{
+    QMainWindow mw(0) ;
+    mw.menuBar();
+    QMdiArea *workspace = new QMdiArea(&mw);
+    workspace->setObjectName(QLatin1String("testWidget"));
+    mw.setCentralWidget(workspace);
+    QSignalSpy spy(workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+    connect( workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)) );
+    mw.show();
+    qApp->setActiveWindow(&mw);
+    QWidget *widget = new QWidget(workspace);
+    widget->setAttribute(Qt::WA_DeleteOnClose);
+    QMdiSubWindow *window1 = workspace->addSubWindow(widget);
+    QWidget *widget2 = new QWidget(workspace);
+    widget2->setAttribute(Qt::WA_DeleteOnClose);
+    QMdiSubWindow *window2 = workspace->addSubWindow(widget2);
+
+    widget->showMinimized();
+    QVERIFY( activeWindow == window1 );
+    widget2->showMinimized();
+    QVERIFY( activeWindow == window2 );
+
+    window2->close();
+    qApp->processEvents();
+    QVERIFY( activeWindow == window1 );
+
+    window1->close();
+    qApp->processEvents();
+    QVERIFY(workspace->activeSubWindow() == 0);
+    QVERIFY( activeWindow == 0 );
+
+    QVERIFY( workspace->subWindowList().count() == 0 );
+}
+
+void tst_QMdiArea::showWindows()
+{
+    QMdiArea *ws = new QMdiArea( 0 );
+
+    QWidget *widget = 0;
+    ws->show();
+
+    widget = new QWidget(ws);
+    widget->show();
+    QVERIFY( widget->isVisible() );
+
+    widget = new QWidget(ws);
+    widget->showMaximized();
+    QVERIFY( widget->isMaximized() );
+    widget->showNormal();
+    QVERIFY( !widget->isMaximized() );
+
+    widget = new QWidget(ws);
+    widget->showMinimized();
+    QVERIFY( widget->isMinimized() );
+    widget->showNormal();
+    QVERIFY( !widget->isMinimized() );
+
+    ws->hide();
+
+    widget = new QWidget(ws);
+    ws->show();
+    QVERIFY( widget->isVisible() );
+
+    ws->hide();
+
+    widget = new QWidget(ws);
+    widget->showMaximized();
+    QVERIFY( widget->isMaximized() );
+    ws->show();
+    QVERIFY( widget->isVisible() );
+    QVERIFY( widget->isMaximized() );
+    ws->hide();
+
+    widget = new QWidget(ws);
+    widget->showMinimized();
+    ws->show();
+    QVERIFY( widget->isMinimized() );
+    ws->hide();
+
+    delete ws;
+}
+
+
+//#define USE_SHOW
+
+void tst_QMdiArea::changeWindowTitle()
+{
+    const QString mwc = QString::fromLatin1("MainWindow's Caption");
+    const QString mwc2 = QString::fromLatin1("MainWindow's New Caption");
+    const QString wc = QString::fromLatin1("Widget's Caption");
+    const QString wc2 = QString::fromLatin1("Widget's New Caption");
+
+    QMainWindow *mw = new QMainWindow;
+    mw->setWindowTitle( mwc );
+    QMdiArea *ws = new QMdiArea( mw );
+    mw->setCentralWidget( ws );
+    mw->menuBar();
+    mw->show();
+    QTest::qWaitForWindowShown(mw);
+
+    QWidget *widget = new QWidget( ws );
+    widget->setWindowTitle( wc );
+    ws->addSubWindow(widget);
+
+    QCOMPARE( mw->windowTitle(), mwc );
+
+#ifdef USE_SHOW
+    widget->showMaximized();
+#else
+    widget->setWindowState(Qt::WindowMaximized);
+#endif
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+#endif
+
+    mw->hide();
+    qApp->processEvents();
+    mw->show();
+    qApp->processEvents();
+    QTest::qWaitForWindowShown(mw);
+
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+#endif
+
+#ifdef USE_SHOW
+    widget->showNormal();
+#else
+    widget->setWindowState(Qt::WindowNoState);
+#endif
+    qApp->processEvents();
+    QCOMPARE( mw->windowTitle(), mwc );
+
+#ifdef USE_SHOW
+    widget->showMaximized();
+#else
+    widget->setWindowState(Qt::WindowMaximized);
+#endif
+    qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QTRY_COMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc) );
+    widget->setWindowTitle( wc2 );
+    QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc).arg(wc2) );
+    mw->setWindowTitle( mwc2 );
+    QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+
+    mw->show();
+    qApp->setActiveWindow(mw);
+
+#ifdef USE_SHOW
+    mw->showFullScreen();
+#else
+    mw->setWindowState(Qt::WindowFullScreen);
+#endif
+
+    qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+#ifdef USE_SHOW
+    widget->showNormal();
+#else
+    widget->setWindowState(Qt::WindowNoState);
+#endif
+    qApp->processEvents();
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+    QCOMPARE(mw->windowTitle(), mwc);
+#else
+    QCOMPARE( mw->windowTitle(), mwc2 );
+#endif
+
+#ifdef USE_SHOW
+    widget->showMaximized();
+#else
+    widget->setWindowState(Qt::WindowMaximized);
+#endif
+    qApp->processEvents();
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QCOMPARE( mw->windowTitle(), QString::fromLatin1("%1 - [%2]").arg(mwc2).arg(wc2) );
+#endif
+
+#ifdef USE_SHOW
+    mw->showNormal();
+#else
+    mw->setWindowState(Qt::WindowNoState);
+#endif
+    qApp->processEvents();
+#ifdef USE_SHOW
+    widget->showNormal();
+#else
+    widget->setWindowState(Qt::WindowNoState);
+#endif
+
+    delete mw;
+}
+
+void tst_QMdiArea::changeModified()
+{
+    const QString mwc = QString::fromLatin1("MainWindow's Caption");
+    const QString wc = QString::fromLatin1("Widget's Caption[*]");
+
+    QMainWindow *mw = new QMainWindow(0);
+    mw->setWindowTitle( mwc );
+    QMdiArea *ws = new QMdiArea( mw );
+    mw->setCentralWidget( ws );
+    mw->menuBar();
+    mw->show();
+
+    QWidget *widget = new QWidget( ws );
+    widget->setWindowTitle( wc );
+    ws->addSubWindow(widget);
+
+    QCOMPARE( mw->isWindowModified(), false);
+    QCOMPARE( widget->isWindowModified(), false);
+    widget->setWindowState(Qt::WindowMaximized);
+    QCOMPARE( mw->isWindowModified(), false);
+    QCOMPARE( widget->isWindowModified(), false);
+
+    widget->setWindowState(Qt::WindowNoState);
+    QCOMPARE( mw->isWindowModified(), false);
+    QCOMPARE( widget->isWindowModified(), false);
+
+    widget->setWindowModified(true);
+    QCOMPARE( mw->isWindowModified(), false);
+    QCOMPARE( widget->isWindowModified(), true);
+    widget->setWindowState(Qt::WindowMaximized);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QCOMPARE( mw->isWindowModified(), true);
+#endif
+    QCOMPARE( widget->isWindowModified(), true);
+
+    widget->setWindowState(Qt::WindowNoState);
+    QCOMPARE( mw->isWindowModified(), false);
+    QCOMPARE( widget->isWindowModified(), true);
+
+    widget->setWindowState(Qt::WindowMaximized);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QCOMPARE( mw->isWindowModified(), true);
+#endif
+    QCOMPARE( widget->isWindowModified(), true);
+
+    widget->setWindowModified(false);
+    QCOMPARE( mw->isWindowModified(), false);
+    QCOMPARE( widget->isWindowModified(), false);
+
+    widget->setWindowModified(true);
+#if !defined(Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QCOMPARE( mw->isWindowModified(), true);
+#endif
+    QCOMPARE( widget->isWindowModified(), true);
+
+    widget->setWindowState(Qt::WindowNoState);
+    QCOMPARE( mw->isWindowModified(), false);
+    QCOMPARE( widget->isWindowModified(), true);
+
+    delete mw;
+}
+
+class MyChild : public QWidget
+{
+public:
+    MyChild(QWidget *parent = 0) : QWidget(parent) {}
+    QSize sizeHint() const { return QSize(234, 123); }
+};
+
+void tst_QMdiArea::childSize()
+{
+    QMdiArea ws;
+
+    MyChild *child = new MyChild(&ws);
+    child->show();
+    QCOMPARE(child->size(), child->sizeHint());
+    delete child;
+
+    child = new MyChild(&ws);
+    child->setFixedSize(200, 200);
+    child->show();
+    QCOMPARE(child->size(), child->minimumSize());
+    delete child;
+
+    child = new MyChild(&ws);
+    child->resize(150, 150);
+    child->show();
+    QCOMPARE(child->size(), QSize(150,150));
+    delete child;
+}
+
+void tst_QMdiArea::fixedSize()
+{
+    QMdiArea *ws = new QMdiArea;
+    int i;
+
+    ws->resize(500, 500);
+//     ws->show();
+
+    QSize fixed(300, 300);
+    for (i = 0; i < 4; ++i) {
+        QWidget *child = new QWidget(ws);
+        child->setFixedSize(fixed);
+        child->show();
+    }
+
+    QList<QMdiSubWindow *> windows = ws->subWindowList();
+    for (i = 0; i < (int)windows.count(); ++i) {
+        QMdiSubWindow *child = windows.at(i);
+        QCOMPARE(child->size(), fixed);
+    }
+
+    ws->cascadeSubWindows();
+    ws->resize(800, 800);
+    for (i = 0; i < (int)windows.count(); ++i) {
+        QMdiSubWindow *child = windows.at(i);
+        QCOMPARE(child->size(), fixed);
+    }
+    ws->resize(500, 500);
+
+    ws->tileSubWindows();
+    ws->resize(800, 800);
+    for (i = 0; i < (int)windows.count(); ++i) {
+        QMdiSubWindow *child = windows.at(i);
+        QCOMPARE(child->size(), fixed);
+    }
+    ws->resize(500, 500);
+
+    for (i = 0; i < (int)windows.count(); ++i) {
+        QMdiSubWindow *child = windows.at(i);
+        delete child;
+    }
+
+    delete ws;
+}
+
+class LargeWidget : public QWidget
+{
+public:
+    LargeWidget(QWidget *parent = 0) : QWidget(parent) {}
+    QSize sizeHint() const { return QSize(1280, 1024); }
+    QSize minimumSizeHint() const { return QSize(300, 300); }
+};
+
+// New tests
+void tst_QMdiArea::minimumSizeHint()
+{
+    QMdiArea workspace;
+    workspace.show();
+    QSize expectedSize(workspace.style()->pixelMetric(QStyle::PM_MDIMinimizedWidth),
+                       workspace.style()->pixelMetric(QStyle::PM_TitleBarHeight));
+    qApp->processEvents();
+    QAbstractScrollArea dummyScrollArea;
+    dummyScrollArea.setFrameStyle(QFrame::NoFrame);
+    expectedSize = expectedSize.expandedTo(dummyScrollArea.minimumSizeHint());
+    QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
+
+    QWidget *window = workspace.addSubWindow(new QWidget);
+    qApp->processEvents();
+    window->show();
+    QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(window->minimumSizeHint()));
+
+    QMdiSubWindow *subWindow = workspace.addSubWindow(new LargeWidget);
+    subWindow->show();
+    QCOMPARE(workspace.minimumSizeHint(), expectedSize.expandedTo(subWindow->minimumSizeHint()));
+
+    workspace.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    workspace.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    QCOMPARE(workspace.minimumSizeHint(), expectedSize);
+}
+
+void tst_QMdiArea::sizeHint()
+{
+    QMdiArea workspace;
+    workspace.show();
+    QSize desktopSize = QApplication::desktop()->size();
+    QSize expectedSize(desktopSize.width() * 2/3, desktopSize.height() * 2/3);
+    QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(qApp->globalStrut()));
+
+    QWidget *window = workspace.addSubWindow(new QWidget);
+    qApp->processEvents();
+    window->show();
+    QCOMPARE(workspace.sizeHint(), expectedSize.expandedTo(window->sizeHint()));
+
+    QMdiSubWindow *nested = workspace.addSubWindow(new QMdiArea);
+    expectedSize = QSize(desktopSize.width() * 2/6, desktopSize.height() * 2/6);
+    QCOMPARE(nested->widget()->sizeHint(), expectedSize);
+}
+
+void tst_QMdiArea::setActiveSubWindow()
+{
+    QMdiArea workspace;
+    workspace.show();
+
+    QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+    connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+    qApp->setActiveWindow(&workspace);
+
+    // Activate hidden windows
+    const int windowCount = 10;
+    QMdiSubWindow *windows[windowCount];
+    for (int i = 0; i < windowCount; ++i) {
+        windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+        qApp->processEvents();
+        QVERIFY(windows[i]->isHidden());
+        workspace.setActiveSubWindow(windows[i]);
+    }
+    QCOMPARE(spy.count(), 0);
+    QVERIFY(!activeWindow);
+    spy.clear();
+
+    // Activate visible windows
+    for (int i = 0; i < windowCount; ++i) {
+        windows[i]->show();
+        QVERIFY(!windows[i]->isHidden());
+        workspace.setActiveSubWindow(windows[i]);
+        qApp->processEvents();
+        QCOMPARE(spy.count(), 1);
+        QCOMPARE(activeWindow, windows[i]);
+        spy.clear();
+    }
+
+    // Deactivate active window
+    QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+    workspace.setActiveSubWindow(0);
+    QCOMPARE(spy.count(), 1);
+    QVERIFY(!activeWindow);
+    QVERIFY(!workspace.activeSubWindow());
+
+    // Activate widget which is not child of any window inside workspace
+    QMdiSubWindow fakeWindow;
+    QTest::ignoreMessage(QtWarningMsg, "QMdiArea::setActiveSubWindow: window is not inside workspace");
+    workspace.setActiveSubWindow(&fakeWindow);
+
+}
+
+void tst_QMdiArea::activeSubWindow()
+{
+    QMainWindow mainWindow;
+
+    QMdiArea *mdiArea = new QMdiArea;
+    QLineEdit *subWindowLineEdit = new QLineEdit;
+    QMdiSubWindow *subWindow = mdiArea->addSubWindow(subWindowLineEdit);
+    mainWindow.setCentralWidget(mdiArea);
+
+    QDockWidget *dockWidget = new QDockWidget(QLatin1String("Dock Widget"), &mainWindow);
+    dockWidget->setAllowedAreas(Qt::LeftDockWidgetArea);
+    QLineEdit *dockWidgetLineEdit = new QLineEdit;
+    dockWidget->setWidget(dockWidgetLineEdit);
+    mainWindow.addDockWidget(Qt::LeftDockWidgetArea, dockWidget);
+
+    mainWindow.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+    qApp->setActiveWindow(&mainWindow);
+    QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+    QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
+
+    dockWidgetLineEdit->setFocus();
+    QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
+    QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+    QEvent deactivateEvent(QEvent::WindowDeactivate);
+    qApp->sendEvent(subWindow, &deactivateEvent);
+    QVERIFY(!mdiArea->activeSubWindow());
+    QCOMPARE(qApp->focusWidget(), (QWidget *)dockWidgetLineEdit);
+
+    QEvent activateEvent(QEvent::WindowActivate);
+    qApp->sendEvent(subWindow, &activateEvent);
+    QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+    QCOMPARE(qApp->focusWidget(), (QWidget *)subWindowLineEdit);
+
+    QLineEdit dummyTopLevel;
+    dummyTopLevel.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&dummyTopLevel);
+#endif
+
+    qApp->setActiveWindow(&dummyTopLevel);
+    QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+    qApp->setActiveWindow(&mainWindow);
+    QCOMPARE(mdiArea->activeSubWindow(), subWindow);
+
+#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
+    qApp->setActiveWindow(0);
+    QVERIFY(!mdiArea->activeSubWindow());
+#endif
+
+    //task 202657
+    dockWidgetLineEdit->setFocus();
+    qApp->setActiveWindow(&mainWindow);
+    QVERIFY(dockWidgetLineEdit->hasFocus());
+}
+
+void tst_QMdiArea::currentSubWindow()
+{
+    QMdiArea mdiArea;
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    for (int i = 0; i < 5; ++i)
+        mdiArea.addSubWindow(new QLineEdit)->show();
+
+    qApp->setActiveWindow(&mdiArea);
+    QCOMPARE(qApp->activeWindow(), (QWidget *)&mdiArea);
+
+    // Check that the last added window is the active and the current.
+    QMdiSubWindow *active = mdiArea.activeSubWindow();
+    QVERIFY(active);
+    QCOMPARE(mdiArea.subWindowList().back(), active);
+    QCOMPARE(mdiArea.currentSubWindow(), active);
+
+    QLineEdit dummyTopLevel;
+    dummyTopLevel.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&dummyTopLevel);
+#endif
+
+    // Move focus to another top-level and check that we still
+    // have an active window.
+    qApp->setActiveWindow(&dummyTopLevel);
+    QCOMPARE(qApp->activeWindow(), (QWidget *)&dummyTopLevel);
+    QVERIFY(mdiArea.activeSubWindow());
+
+    delete active;
+    active = 0;
+
+    // We just deleted the current sub-window -> current should then
+    // be the next in list (which in this case is the first sub-window).
+    QVERIFY(mdiArea.currentSubWindow());
+    QCOMPARE(mdiArea.currentSubWindow(), mdiArea.subWindowList().front());
+
+    // Activate mdi area and check that active == current.
+    qApp->setActiveWindow(&mdiArea);
+    active = mdiArea.activeSubWindow();
+    QVERIFY(active);
+    QCOMPARE(mdiArea.activeSubWindow(), mdiArea.subWindowList().front());
+
+    active->hide();
+    QCOMPARE(mdiArea.activeSubWindow(), active);
+    QCOMPARE(mdiArea.currentSubWindow(), active);
+
+    qApp->setActiveWindow(&dummyTopLevel);
+    QVERIFY(mdiArea.activeSubWindow());
+    QCOMPARE(mdiArea.currentSubWindow(), active);
+
+    qApp->setActiveWindow(&mdiArea);
+    active->show();
+    QCOMPARE(mdiArea.activeSubWindow(), active);
+
+    mdiArea.setActiveSubWindow(0);
+    QVERIFY(!mdiArea.activeSubWindow());
+    QVERIFY(!mdiArea.currentSubWindow());
+
+    mdiArea.setActiveSubWindow(active);
+    QCOMPARE(mdiArea.activeSubWindow(), active);
+    QEvent windowDeactivate(QEvent::WindowDeactivate);
+    qApp->sendEvent(active, &windowDeactivate);
+    QVERIFY(!mdiArea.activeSubWindow());
+    QVERIFY(!mdiArea.currentSubWindow());
+
+    QEvent windowActivate(QEvent::WindowActivate);
+    qApp->sendEvent(active, &windowActivate);
+    QVERIFY(mdiArea.activeSubWindow());
+    QVERIFY(mdiArea.currentSubWindow());
+
+#if !defined(Q_WS_MAC) && !defined(Q_WS_WIN)
+    qApp->setActiveWindow(0);
+    QVERIFY(!mdiArea.activeSubWindow());
+    QVERIFY(mdiArea.currentSubWindow());
+#endif
+}
+
+void tst_QMdiArea::addAndRemoveWindows()
+{
+    QMdiArea workspace;
+    workspace.resize(800, 600);
+    workspace.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+    { // addSubWindow with large widget
+    QCOMPARE(workspace.subWindowList().count(), 0);
+    QWidget *window = workspace.addSubWindow(new LargeWidget);
+    QVERIFY(window);
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 1);
+    QVERIFY(window->windowFlags() == DefaultWindowFlags);
+    QCOMPARE(window->size(), workspace.viewport()->size());
+    }
+
+    { // addSubWindow, minimumSize set.
+    QMdiSubWindow *window = new QMdiSubWindow;
+    window->setMinimumSize(900, 900);
+    workspace.addSubWindow(window);
+    QVERIFY(window);
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 2);
+    QVERIFY(window->windowFlags() == DefaultWindowFlags);
+    QCOMPARE(window->size(), window->minimumSize());
+    }
+
+    { // addSubWindow, resized
+    QMdiSubWindow *window = new QMdiSubWindow;
+    window->setWidget(new QWidget);
+    window->resize(1500, 1500);
+    workspace.addSubWindow(window);
+    QVERIFY(window);
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 3);
+    QVERIFY(window->windowFlags() == DefaultWindowFlags);
+    QCOMPARE(window->size(), QSize(1500, 1500));
+    }
+
+    { // addSubWindow with 0 pointer
+    QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
+    QWidget *window = workspace.addSubWindow(0);
+    QVERIFY(!window);
+    QCOMPARE(workspace.subWindowList().count(), 3);
+    }
+
+    { // addChildWindow
+    QMdiSubWindow *window = new QMdiSubWindow;
+    workspace.addSubWindow(window);
+    qApp->processEvents();
+    QVERIFY(window->windowFlags() == DefaultWindowFlags);
+    window->setWidget(new QWidget);
+    QCOMPARE(workspace.subWindowList().count(), 4);
+    QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
+    workspace.addSubWindow(window);
+    }
+
+    { // addChildWindow with 0 pointer
+    QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: null pointer to widget");
+    workspace.addSubWindow(0);
+    QCOMPARE(workspace.subWindowList().count(), 4);
+    }
+
+    // removeSubWindow
+    foreach (QWidget *window, workspace.subWindowList()) {
+        workspace.removeSubWindow(window);
+        delete window;
+    }
+    QCOMPARE(workspace.subWindowList().count(), 0);
+
+    // removeSubWindow with 0 pointer
+    QTest::ignoreMessage(QtWarningMsg, "QMdiArea::removeSubWindow: null pointer to widget");
+    workspace.removeSubWindow(0);
+
+    workspace.addSubWindow(new QPushButton(QLatin1String("Dummy to make workspace non-empty")));
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 1);
+
+    // removeSubWindow with window not inside workspace
+    QTest::ignoreMessage(QtWarningMsg,"QMdiArea::removeSubWindow: window is not inside workspace");
+    QMdiSubWindow *fakeWindow = new QMdiSubWindow;
+    workspace.removeSubWindow(fakeWindow);
+    delete fakeWindow;
+
+    // Check that newly added windows don't occupy maximized windows'
+    // restore space.
+    workspace.closeAllSubWindows();
+    workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+    workspace.show();
+    QMdiSubWindow *window1 = workspace.addSubWindow(new QWidget);
+    window1->show();
+    const QRect window1RestoreGeometry = window1->geometry();
+    QCOMPARE(window1RestoreGeometry.topLeft(), QPoint(0, 0));
+
+    window1->showMinimized();
+
+    // Occupy space.
+    QMdiSubWindow *window2 = workspace.addSubWindow(new QWidget);
+    window2->show();
+    const QRect window2RestoreGeometry = window2->geometry();
+    QCOMPARE(window2RestoreGeometry.topLeft(), QPoint(0, 0));
+
+    window2->showMaximized();
+
+    // Don't occupy space.
+    QMdiSubWindow *window3 = workspace.addSubWindow(new QWidget);
+    window3->show();
+    QCOMPARE(window3->geometry().topLeft(), QPoint(window2RestoreGeometry.right() + 1, 0));
+}
+
+void tst_QMdiArea::addAndRemoveWindowsWithReparenting()
+{
+    QMdiArea workspace;
+    QMdiSubWindow window(&workspace);
+    QVERIFY(window.windowFlags() == DefaultWindowFlags);
+
+    // 0 because the window list contains widgets and not actual
+    // windows. Silly, but that's the behavior.
+    QCOMPARE(workspace.subWindowList().count(), 0);
+    window.setWidget(new QWidget);
+    qApp->processEvents();
+
+    QCOMPARE(workspace.subWindowList().count(), 1);
+    window.setParent(0); // Will also reset window flags
+    QCOMPARE(workspace.subWindowList().count(), 0);
+    window.setParent(&workspace);
+    QCOMPARE(workspace.subWindowList().count(), 1);
+    QVERIFY(window.windowFlags() == DefaultWindowFlags);
+
+    QTest::ignoreMessage(QtWarningMsg, "QMdiArea::addSubWindow: window is already added");
+    workspace.addSubWindow(&window);
+    QCOMPARE(workspace.subWindowList().count(), 1);
+}
+
+class MySubWindow : public QMdiSubWindow
+{
+public:
+    using QObject::receivers;
+};
+
+static int numberOfConnectedSignals(MySubWindow *subWindow)
+{
+    if (!subWindow)
+        return 0;
+
+    int numConnectedSignals = 0;
+    for (int i = 0; i < subWindow->metaObject()->methodCount(); ++i) {
+        QMetaMethod method = subWindow->metaObject()->method(i);
+        if (method.methodType() == QMetaMethod::Signal) {
+            QString signature(QLatin1String("2"));
+            signature += QLatin1String(method.signature());
+            numConnectedSignals += subWindow->receivers(signature.toLatin1());
+        }
+    }
+    return numConnectedSignals;
+}
+
+void tst_QMdiArea::removeSubWindow_2()
+{
+    QMdiArea mdiArea;
+    MySubWindow *subWindow = new MySubWindow;
+    QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+
+    // Connected to aboutToActivate() and windowStateChanged().
+    mdiArea.addSubWindow(subWindow);
+    QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
+
+    // Ensure we disconnect from all signals.
+    mdiArea.removeSubWindow(subWindow);
+    QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+
+    mdiArea.addSubWindow(subWindow);
+    QVERIFY(numberOfConnectedSignals(subWindow) >= 2);
+    subWindow->setParent(0);
+    QCOMPARE(numberOfConnectedSignals(subWindow), 0);
+}
+
+void tst_QMdiArea::closeWindows()
+{
+    QMdiArea workspace;
+    workspace.show();
+    qApp->setActiveWindow(&workspace);
+
+    // Close widget
+    QWidget *widget = new QWidget;
+    QMdiSubWindow *subWindow = workspace.addSubWindow(widget);
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 1);
+    subWindow->close();
+    QCOMPARE(workspace.subWindowList().count(), 0);
+
+    // Close window
+    QWidget *window = workspace.addSubWindow(new QWidget);
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 1);
+    window->close();
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 0);
+
+    const int windowCount = 10;
+
+    // Close active window
+    for (int i = 0; i < windowCount; ++i)
+        workspace.addSubWindow(new QWidget)->show();
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), windowCount);
+    int activeSubWindowCount = 0;
+    while (workspace.activeSubWindow()) {
+        workspace.activeSubWindow()->close();
+        qApp->processEvents();
+        ++activeSubWindowCount;
+    }
+    QCOMPARE(activeSubWindowCount, windowCount);
+    QCOMPARE(workspace.subWindowList().count(), 0);
+
+    // Close all windows
+    for (int i = 0; i < windowCount; ++i)
+        workspace.addSubWindow(new QWidget)->show();
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), windowCount);
+    QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+    connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+    workspace.closeAllSubWindows();
+    qApp->processEvents();
+    QCOMPARE(workspace.subWindowList().count(), 0);
+    QCOMPARE(spy.count(), 1);
+    QVERIFY(!activeWindow);
+}
+
+void tst_QMdiArea::activateNextAndPreviousWindow()
+{
+    QMdiArea workspace;
+    workspace.show();
+    qApp->setActiveWindow(&workspace);
+
+    const int windowCount = 10;
+    QMdiSubWindow *windows[windowCount];
+    for (int i = 0; i < windowCount; ++i) {
+        windows[i] = qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget));
+        windows[i]->show();
+        qApp->processEvents();
+    }
+
+    QSignalSpy spy(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+    connect(&workspace, SIGNAL(subWindowActivated(QMdiSubWindow *)), this, SLOT(activeChanged(QMdiSubWindow *)));
+
+    // activateNextSubWindow
+    for (int i = 0; i < windowCount; ++i) {
+        workspace.activateNextSubWindow();
+        qApp->processEvents();
+        QCOMPARE(workspace.activeSubWindow(), windows[i]);
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+    }
+    QVERIFY(activeWindow);
+    QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+    QCOMPARE(workspace.activeSubWindow(), activeWindow);
+
+    // activatePreviousSubWindow
+    for (int i = windowCount - 2; i >= 0; --i) {
+        workspace.activatePreviousSubWindow();
+        qApp->processEvents();
+        QCOMPARE(workspace.activeSubWindow(), windows[i]);
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+        if (i % 2 == 0)
+            windows[i]->hide(); // 10, 8, 6, 4, 2, 0
+    }
+    QVERIFY(activeWindow);
+    QCOMPARE(workspace.activeSubWindow(), windows[0]);
+    QCOMPARE(workspace.activeSubWindow(), activeWindow);
+
+    // activateNextSubWindow with every 2nd window hidden
+    for (int i = 0; i < windowCount / 2; ++i) {
+        workspace.activateNextSubWindow(); // 1, 3, 5, 7, 9
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+    }
+    QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+
+    // activatePreviousSubWindow with every 2nd window hidden
+    for (int i = 0; i < windowCount / 2; ++i) {
+        workspace.activatePreviousSubWindow(); // 7, 5, 3, 1, 9
+        QCOMPARE(spy.count(), 1);
+        spy.clear();
+    }
+    QCOMPARE(workspace.activeSubWindow(), windows[windowCount - 1]);
+
+    workspace.setActiveSubWindow(0);
+    QVERIFY(!activeWindow);
+}
+
+void tst_QMdiArea::subWindowList_data()
+{
+    QTest::addColumn<QMdiArea::WindowOrder>("windowOrder");
+    QTest::addColumn<int>("windowCount");
+    QTest::addColumn<int>("activeSubWindow");
+    QTest::addColumn<int>("staysOnTop1");
+    QTest::addColumn<int>("staysOnTop2");
+
+    QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 10 << 4 << 8 << 5;
+    QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 10 << 6 << 3 << 9;
+    QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 10 << 7 << 2 << 1;
+}
+void tst_QMdiArea::subWindowList()
+{
+    QFETCH(QMdiArea::WindowOrder, windowOrder);
+    QFETCH(int, windowCount);
+    QFETCH(int, activeSubWindow);
+    QFETCH(int, staysOnTop1);
+    QFETCH(int, staysOnTop2);
+
+    QMdiArea workspace;
+    workspace.show();
+    qApp->setActiveWindow(&workspace);
+
+    QList<QMdiSubWindow *> activationOrder;
+    QVector<QMdiSubWindow *> windows;
+    for (int i = 0; i < windowCount; ++i) {
+        windows.append(qobject_cast<QMdiSubWindow *>(workspace.addSubWindow(new QWidget)));
+        windows[i]->show();
+        activationOrder.append(windows[i]);
+    }
+
+    {
+    QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
+    QCOMPARE(widgets.count(), windowCount);
+    for (int i = 0; i < widgets.count(); ++i)
+        QCOMPARE(widgets.at(i), windows[i]);
+    }
+
+    windows[staysOnTop1]->setWindowFlags(windows[staysOnTop1]->windowFlags() | Qt::WindowStaysOnTopHint);
+    workspace.setActiveSubWindow(windows[activeSubWindow]);
+    qApp->processEvents();
+    QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
+    activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
+
+    QList<QMdiSubWindow *> subWindows = workspace.subWindowList(windowOrder);
+    if (windowOrder == QMdiArea::CreationOrder) {
+        QCOMPARE(subWindows.at(activeSubWindow), windows[activeSubWindow]);
+        QCOMPARE(subWindows.at(staysOnTop1), windows[staysOnTop1]);
+        for (int i = 0; i < windowCount; ++i)
+            QCOMPARE(subWindows.at(i), windows[i]);
+        return;
+    }
+
+    if (windowOrder == QMdiArea::StackingOrder) {
+        QCOMPARE(subWindows.at(subWindows.count() - 1), windows[staysOnTop1]);
+        QCOMPARE(subWindows.at(subWindows.count() - 2), windows[activeSubWindow]);
+        QCOMPARE(subWindows.count(), windowCount);
+    } else { // ActivationHistoryOrder
+        QCOMPARE(subWindows, activationOrder);
+    }
+
+    windows[staysOnTop2]->setWindowFlags(windows[staysOnTop2]->windowFlags() | Qt::WindowStaysOnTopHint);
+    workspace.setActiveSubWindow(windows[staysOnTop2]);
+    qApp->processEvents();
+    QCOMPARE(workspace.activeSubWindow(), windows[staysOnTop2]);
+    activationOrder.move(activationOrder.indexOf(windows[staysOnTop2]), windowCount - 1);
+
+    workspace.setActiveSubWindow(windows[activeSubWindow]);
+    qApp->processEvents();
+    QCOMPARE(workspace.activeSubWindow(), windows[activeSubWindow]);
+    activationOrder.move(activationOrder.indexOf(windows[activeSubWindow]), windowCount - 1);
+
+    QList<QMdiSubWindow *> widgets = workspace.subWindowList(windowOrder);
+    QCOMPARE(widgets.count(), windowCount);
+    if (windowOrder == QMdiArea::StackingOrder) {
+        QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
+        QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+        QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+    } else { // ActivationHistory
+        QCOMPARE(widgets, activationOrder);
+    }
+
+    windows[activeSubWindow]->raise();
+    windows[staysOnTop2]->lower();
+
+    widgets = workspace.subWindowList(windowOrder);
+    if (windowOrder == QMdiArea::StackingOrder) {
+        QCOMPARE(widgets.at(widgets.count() - 1), windows[activeSubWindow]);
+        QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+        QCOMPARE(widgets.at(0), windows[staysOnTop2]);
+    } else { // ActivationHistoryOrder
+        QCOMPARE(widgets, activationOrder);
+    }
+
+    windows[activeSubWindow]->stackUnder(windows[staysOnTop1]);
+    windows[staysOnTop2]->raise();
+
+    widgets = workspace.subWindowList(windowOrder);
+    if (windowOrder == QMdiArea::StackingOrder) {
+        QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop2]);
+        QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop1]);
+        QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+    } else { // ActivationHistoryOrder
+        QCOMPARE(widgets, activationOrder);
+    }
+
+    workspace.setActiveSubWindow(windows[staysOnTop1]);
+    activationOrder.move(activationOrder.indexOf(windows[staysOnTop1]), windowCount - 1);
+
+    widgets = workspace.subWindowList(windowOrder);
+    if (windowOrder == QMdiArea::StackingOrder) {
+        QCOMPARE(widgets.at(widgets.count() - 1), windows[staysOnTop1]);
+        QCOMPARE(widgets.at(widgets.count() - 2), windows[staysOnTop2]);
+        QCOMPARE(widgets.at(widgets.count() - 3), windows[activeSubWindow]);
+    } else { // ActivationHistoryOrder
+        QCOMPARE(widgets, activationOrder);
+    }
+}
+
+void tst_QMdiArea::setBackground()
+{
+    QMdiArea workspace;
+    QCOMPARE(workspace.background(), workspace.palette().brush(QPalette::Dark));
+    workspace.setBackground(QBrush(Qt::green));
+    QCOMPARE(workspace.background(), QBrush(Qt::green));
+}
+
+void tst_QMdiArea::setViewport()
+{
+    QMdiArea workspace;
+    workspace.show();
+
+    QWidget *firstViewport = workspace.viewport();
+    QVERIFY(firstViewport);
+
+    const int windowCount = 10;
+    for (int i = 0; i < windowCount; ++i) {
+        QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
+        window->show();
+        if (i % 2 == 0) {
+            window->showMinimized();
+            QVERIFY(window->isMinimized());
+        } else {
+            window->showMaximized();
+            QVERIFY(window->isMaximized());
+        }
+    }
+
+    qApp->processEvents();
+    QList<QMdiSubWindow *> windowsBeforeViewportChange = workspace.subWindowList();
+    QCOMPARE(windowsBeforeViewportChange.count(), windowCount);
+
+    workspace.setViewport(new QWidget);
+    qApp->processEvents();
+    QVERIFY(workspace.viewport() != firstViewport);
+
+    QList<QMdiSubWindow *> windowsAfterViewportChange = workspace.subWindowList();
+    QCOMPARE(windowsAfterViewportChange.count(), windowCount);
+    QCOMPARE(windowsAfterViewportChange, windowsBeforeViewportChange);
+
+    //    for (int i = 0; i < windowCount; ++i) {
+    //        QMdiSubWindow *window = windowsAfterViewportChange.at(i);
+    //        if (i % 2 == 0)
+    //            QVERIFY(!window->isMinimized());
+    //else
+    //    QVERIFY(!window->isMaximized());
+    //    }
+
+    QTest::ignoreMessage(QtWarningMsg, "QMdiArea: Deleting the view port is undefined, "
+                                       "use setViewport instead.");
+    delete workspace.viewport();
+    qApp->processEvents();
+
+    QCOMPARE(workspace.subWindowList().count(), 0);
+    QVERIFY(!workspace.activeSubWindow());
+}
+
+void tst_QMdiArea::tileSubWindows()
+{
+    QMdiArea workspace;
+    workspace.resize(600,480);
+    workspace.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+    const int windowCount = 10;
+    for (int i = 0; i < windowCount; ++i) {
+        QMdiSubWindow *subWindow = workspace.addSubWindow(new QWidget);
+        subWindow->setMinimumSize(50, 30);
+        subWindow->show();
+    }
+    workspace.tileSubWindows();
+    workspace.setActiveSubWindow(0);
+    QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+    QList<QMdiSubWindow *> windows = workspace.subWindowList();
+    for (int i = 0; i < windowCount; ++i) {
+        QMdiSubWindow *window = windows.at(i);
+        for (int j = 0; j < windowCount; ++j) {
+            if (i == j)
+                continue;
+            QVERIFY(!window->geometry().intersects(windows.at(j)->geometry()));
+        }
+    }
+
+    // Keep the views tiled through any subsequent resize events.
+    for (int i = 0; i < 5; ++i) {
+        workspace.resize(workspace.size() - QSize(10, 10));
+        qApp->processEvents();
+    }
+    workspace.setActiveSubWindow(0);
+#ifndef Q_OS_WINCE //See Task 197453 ToDo
+    QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+#endif
+
+    QMdiSubWindow *window = windows.at(0);
+
+    // Change the geometry of one of the children and verify
+    // that the views are not tiled anymore.
+    window->move(window->x() + 1, window->y());
+    workspace.resize(workspace.size() - QSize(10, 10));
+    workspace.setActiveSubWindow(0);
+    QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+    qApp->processEvents();
+
+    // Re-tile.
+    workspace.tileSubWindows();
+    workspace.setActiveSubWindow(0);
+    QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+    // Close one of the children and verify that the views
+    // are not tiled anymore.
+    window->close();
+    workspace.resize(workspace.size() - QSize(10, 10));
+    workspace.setActiveSubWindow(0);
+    QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+    qApp->processEvents();
+
+    // Re-tile.
+    workspace.tileSubWindows();
+    workspace.setActiveSubWindow(0);
+    QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+    window = windows.at(1);
+
+    // Maximize one of the children and verify that the views
+    // are not tiled anymore.
+    workspace.tileSubWindows();
+    window->showMaximized();
+    workspace.resize(workspace.size() - QSize(10, 10));
+    workspace.setActiveSubWindow(0);
+    QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+    qApp->processEvents();
+
+    // Re-tile.
+    workspace.tileSubWindows();
+    workspace.setActiveSubWindow(0);
+    QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+    // Minimize one of the children and verify that the views
+    // are not tiled anymore.
+    workspace.tileSubWindows();
+    window->showMinimized();
+    workspace.resize(workspace.size() - QSize(10, 10));
+    workspace.setActiveSubWindow(0);
+    QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+    qApp->processEvents();
+
+    // Re-tile.
+    workspace.tileSubWindows();
+    workspace.setActiveSubWindow(0);
+    QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+    // Active/deactivate windows and verify that the views are tiled.
+    workspace.setActiveSubWindow(windows.at(5));
+    workspace.resize(workspace.size() - QSize(10, 10));
+    workspace.setActiveSubWindow(0);
+    QTest::qWait(250); // delayed re-arrange of minimized windows
+    QTRY_COMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+    // Add another window and verify that the views are not tiled anymore.
+    workspace.addSubWindow(new QPushButton(QLatin1String("I'd like to mess up tiled views")))->show();
+    workspace.resize(workspace.size() - QSize(10, 10));
+    workspace.setActiveSubWindow(0);
+    QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+
+    // Re-tile.
+    workspace.tileSubWindows();
+    workspace.setActiveSubWindow(0);
+    QCOMPARE(workspace.viewport()->childrenRect(), workspace.viewport()->rect());
+
+    // Cascade and verify that the views are not tiled anymore.
+    workspace.cascadeSubWindows();
+    workspace.resize(workspace.size() - QSize(10, 10));
+    workspace.setActiveSubWindow(0);
+    QVERIFY(workspace.viewport()->childrenRect() != workspace.viewport()->rect());
+
+    // Make sure the active window is placed in top left corner regardless
+    // of whether we have any windows with staysOnTopHint or not.
+    windows.at(3)->setWindowFlags(windows.at(3)->windowFlags() | Qt::WindowStaysOnTopHint);
+    QMdiSubWindow *activeSubWindow = windows.at(6);
+    workspace.setActiveSubWindow(activeSubWindow);
+    QCOMPARE(workspace.activeSubWindow(), activeSubWindow);
+    workspace.tileSubWindows();
+    QCOMPARE(activeSubWindow->geometry().topLeft(), QPoint(0, 0));
+
+    // Verify that we try to resize the area such that all sub-windows are visible.
+    // It's important that tiled windows are NOT overlapping.
+    workspace.resize(350, 150);
+    qApp->processEvents();
+    QTRY_COMPARE(workspace.size(), QSize(350, 150));
+
+    const QSize minSize(300, 100);
+    foreach (QMdiSubWindow *subWindow, workspace.subWindowList())
+        subWindow->setMinimumSize(minSize);
+
+    QCOMPARE(workspace.size(), QSize(350, 150));
+    workspace.tileSubWindows();
+    // The sub-windows are now tiled like this:
+    // | win 1 || win 2 || win 3 |
+    // +-------++-------++-------+
+    // +-------++-------++-------+
+    // | win 4 || win 5 || win 6 |
+    // +-------++-------++-------+
+    // +-------++-------++-------+
+    // | win 7 || win 8 || win 9 |
+    workspace.setActiveSubWindow(0);
+    int frameWidth = 0;
+    if (workspace.style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, &workspace))
+        frameWidth = workspace.style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+    const int spacing = 2 * frameWidth + 2;
+    const QSize expectedViewportSize(3 * minSize.width() + spacing, 3 * minSize.height() + spacing);
+#ifdef Q_OS_WINCE
+    QSKIP("Not fixed yet! See task 197453", SkipAll);
+#endif
+    QTRY_COMPARE(workspace.viewport()->rect().size(), expectedViewportSize);
+
+    // Not enough space for all sub-windows to be visible -> provide scroll bars.
+    workspace.resize(150, 150);
+    qApp->processEvents();
+    QTRY_COMPARE(workspace.size(), QSize(150, 150));
+
+    // Horizontal scroll bar.
+    QScrollBar *hBar = workspace.horizontalScrollBar();
+    QCOMPARE(workspace.horizontalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
+    QTRY_VERIFY(hBar->isVisible());
+    QCOMPARE(hBar->value(), 0);
+    QCOMPARE(hBar->minimum(), 0);
+
+    // Vertical scroll bar.
+    QScrollBar *vBar = workspace.verticalScrollBar();
+    QCOMPARE(workspace.verticalScrollBarPolicy(), Qt::ScrollBarAsNeeded);
+    QVERIFY(vBar->isVisible());
+    QCOMPARE(vBar->value(), 0);
+    QCOMPARE(vBar->minimum(), 0);
+
+    workspace.tileSubWindows();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&workspace);
+#endif
+    qApp->processEvents();
+
+    QTRY_VERIFY(workspace.size() != QSize(150, 150));
+    QTRY_VERIFY(!vBar->isVisible());
+    QTRY_VERIFY(!hBar->isVisible());
+}
+
+void tst_QMdiArea::cascadeAndTileSubWindows()
+{
+    QMdiArea workspace;
+    workspace.resize(400, 400);
+    workspace.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&workspace);
+#endif
+
+    const int windowCount = 10;
+    QList<QMdiSubWindow *> windows;
+    for (int i = 0; i < windowCount; ++i) {
+        QMdiSubWindow *window = workspace.addSubWindow(new MyChild);
+        if (i % 3 == 0) {
+            window->showMinimized();
+            QVERIFY(window->isMinimized());
+        } else {
+            window->showMaximized();
+            QVERIFY(window->isMaximized());
+        }
+        windows.append(window);
+    }
+
+    // cascadeSubWindows
+    qApp->processEvents();
+    workspace.cascadeSubWindows();
+    qApp->processEvents();
+
+    // Check dy between two cascaded windows
+    QStyleOptionTitleBar options;
+    options.initFrom(windows.at(1));
+    int titleBarHeight = windows.at(1)->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
+    // ### Remove this after the mac style has been fixed
+    if (windows.at(1)->style()->inherits("QMacStyle"))
+        titleBarHeight -= 4;
+    const QFontMetrics fontMetrics = QFontMetrics(QApplication::font("QWorkspaceTitleBar"));
+    const int dy = qMax(titleBarHeight - (titleBarHeight - fontMetrics.height()) / 2, 1);
+    QCOMPARE(windows.at(2)->geometry().top() - windows.at(1)->geometry().top(), dy);
+
+    for (int i = 0; i < windows.count(); ++i) {
+        QMdiSubWindow *window = windows.at(i);
+        if (i % 3 == 0) {
+            QVERIFY(window->isMinimized());
+        } else {
+            QVERIFY(!window->isMaximized());
+            QCOMPARE(window->size(), window->sizeHint());
+            window->showMaximized();
+            QVERIFY(window->isMaximized());
+        }
+    }
+}
+
+void tst_QMdiArea::resizeMaximizedChildWindows_data()
+{
+    QTest::addColumn<int>("startSize");
+    QTest::addColumn<int>("increment");
+    QTest::addColumn<int>("windowCount");
+
+    QTest::newRow("multiple children") << 400 << 20 << 10;
+}
+
+void tst_QMdiArea::resizeMaximizedChildWindows()
+{
+    QFETCH(int, startSize);
+    QFETCH(int, increment);
+    QFETCH(int, windowCount);
+
+    QMdiArea workspace;
+    workspace.show();
+#if defined(Q_WS_X11)
+    qt_x11_wait_for_window_manager(&workspace);
+#endif
+    QTest::qWait(100);
+    workspace.resize(startSize, startSize);
+    workspace.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+    QSize workspaceSize = workspace.size();
+    QVERIFY(workspaceSize.isValid());
+    QCOMPARE(workspaceSize, QSize(startSize, startSize));
+
+    QList<QMdiSubWindow *> windows;
+    for (int i = 0; i < windowCount; ++i) {
+        QMdiSubWindow *window = workspace.addSubWindow(new QWidget);
+        windows.append(window);
+        qApp->processEvents();
+        window->showMaximized();
+        QTest::qWait(100);
+        QVERIFY(window->isMaximized());
+        QSize windowSize = window->size();
+        QVERIFY(windowSize.isValid());
+        QCOMPARE(window->rect(), workspace.contentsRect());
+
+        workspace.resize(workspaceSize + QSize(increment, increment));
+        QTest::qWait(100);
+        qApp->processEvents();
+        QTRY_COMPARE(workspace.size(), workspaceSize + QSize(increment, increment));
+        QTRY_COMPARE(window->size(), windowSize + QSize(increment, increment));
+        workspaceSize = workspace.size();
+    }
+
+    int newSize = startSize + increment * windowCount;
+    QCOMPARE(workspaceSize, QSize(newSize, newSize));
+    foreach (QWidget *window, windows)
+        QCOMPARE(window->rect(), workspace.contentsRect());
+}
+
+// QWidget::setParent clears focusWidget so make sure
+// we restore it after QMdiArea::addSubWindow.
+void tst_QMdiArea::focusWidgetAfterAddSubWindow()
+{
+    QWidget *view = new QWidget;
+    view->setLayout(new QVBoxLayout);
+
+    QLineEdit *lineEdit1 = new QLineEdit;
+    QLineEdit *lineEdit2 = new QLineEdit;
+    view->layout()->addWidget(lineEdit1);
+    view->layout()->addWidget(lineEdit2);
+
+    lineEdit2->setFocus();
+    QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
+
+    QMdiArea mdiArea;
+    mdiArea.addSubWindow(view);
+    QCOMPARE(view->focusWidget(), static_cast<QWidget *>(lineEdit2));
+
+    mdiArea.show();
+    view->show();
+    qApp->setActiveWindow(&mdiArea);
+    QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(lineEdit2));
+}
+
+void tst_QMdiArea::dontMaximizeSubWindowOnActivation()
+{
+    QMdiArea mdiArea;
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+    qApp->setActiveWindow(&mdiArea);
+
+    // Add one maximized window.
+    mdiArea.addSubWindow(new QWidget)->showMaximized();
+    QVERIFY(mdiArea.activeSubWindow());
+    QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+
+    // Add few more windows and verify that they are maximized.
+    for (int i = 0; i < 5; ++i) {
+        QMdiSubWindow *window = mdiArea.addSubWindow(new QWidget);
+        window->show();
+        QVERIFY(window->isMaximized());
+        qApp->processEvents();
+    }
+
+    // Verify that activated windows still are maximized on activation.
+    QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+    for (int i = 0; i < subWindows.count(); ++i) {
+        mdiArea.activateNextSubWindow();
+        QMdiSubWindow *window = subWindows.at(i);
+        QCOMPARE(mdiArea.activeSubWindow(), window);
+        QVERIFY(window->isMaximized());
+        qApp->processEvents();
+    }
+
+    // Restore active window and verify that other windows aren't
+    // maximized on activation.
+    mdiArea.activeSubWindow()->showNormal();
+    for (int i = 0; i < subWindows.count(); ++i) {
+        mdiArea.activateNextSubWindow();
+        QMdiSubWindow *window = subWindows.at(i);
+        QCOMPARE(mdiArea.activeSubWindow(), window);
+        QVERIFY(!window->isMaximized());
+        qApp->processEvents();
+    }
+
+    // Enable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
+    mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation);
+    mdiArea.activeSubWindow()->showMaximized();
+    int indexOfMaximized = subWindows.indexOf(mdiArea.activeSubWindow());
+
+    // Verify that windows are not maximized on activation.
+    for (int i = 0; i < subWindows.count(); ++i) {
+        mdiArea.activateNextSubWindow();
+        QMdiSubWindow *window = subWindows.at(i);
+        QCOMPARE(mdiArea.activeSubWindow(), window);
+        if (indexOfMaximized != i)
+            QVERIFY(!window->isMaximized());
+        qApp->processEvents();
+    }
+    QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+
+    // Minimize all windows.
+    foreach (QMdiSubWindow *window, subWindows) {
+        window->showMinimized();
+        QVERIFY(window->isMinimized());
+        qApp->processEvents();
+    }
+
+    // Disable 'DontMaximizedSubWindowOnActivation' and maximize the active window.
+    mdiArea.setOption(QMdiArea::DontMaximizeSubWindowOnActivation, false);
+    mdiArea.activeSubWindow()->showMaximized();
+
+    // Verify that minimized windows are maximized on activation.
+    for (int i = 0; i < subWindows.count(); ++i) {
+        mdiArea.activateNextSubWindow();
+        QMdiSubWindow *window = subWindows.at(i);
+        QCOMPARE(mdiArea.activeSubWindow(), window);
+        QVERIFY(window->isMaximized());
+        qApp->processEvents();
+    }
+
+    // Verify that activated windows are maximized after closing
+    // the active window
+    for (int i = 0; i < subWindows.count(); ++i) {
+        QVERIFY(mdiArea.activeSubWindow());
+        QVERIFY(mdiArea.activeSubWindow()->isMaximized());
+        mdiArea.activeSubWindow()->close();
+        qApp->processEvents();
+    }
+
+    QVERIFY(!mdiArea.activeSubWindow());
+    QCOMPARE(mdiArea.subWindowList().size(), 0);
+
+    // Verify that new windows are not maximized.
+    mdiArea.addSubWindow(new QWidget)->show();
+    QVERIFY(mdiArea.activeSubWindow());
+    QVERIFY(!mdiArea.activeSubWindow()->isMaximized());
+}
+
+void tst_QMdiArea::delayedPlacement()
+{
+    QMdiArea mdiArea;
+
+    QMdiSubWindow *window1 = mdiArea.addSubWindow(new QWidget);
+    QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
+
+    QMdiSubWindow *window2 = mdiArea.addSubWindow(new QWidget);
+    QCOMPARE(window2->geometry().topLeft(), QPoint(0, 0));
+
+    QMdiSubWindow *window3 = mdiArea.addSubWindow(new QWidget);
+    QCOMPARE(window3->geometry().topLeft(), QPoint(0, 0));
+
+    mdiArea.resize(window3->minimumSizeHint().width() * 3, 400);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    QCOMPARE(window1->geometry().topLeft(), QPoint(0, 0));
+    QCOMPARE(window2->geometry().topLeft(), window1->geometry().topRight() + QPoint(1, 0));
+    QCOMPARE(window3->geometry().topLeft(), window2->geometry().topRight() + QPoint(1, 0));
+}
+
+void tst_QMdiArea::iconGeometryInMenuBar()
+{
+#if !defined (Q_WS_MAC) && !defined(Q_OS_WINCE)
+    QMainWindow mainWindow;
+    QMenuBar *menuBar = mainWindow.menuBar();
+    QMdiArea *mdiArea = new QMdiArea;
+    QMdiSubWindow *subWindow = mdiArea->addSubWindow(new QWidget);
+    mainWindow.setCentralWidget(mdiArea);
+    mainWindow.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mainWindow);
+#endif
+
+    subWindow->showMaximized();
+    QVERIFY(subWindow->isMaximized());
+
+    QWidget *leftCornerWidget = menuBar->cornerWidget(Qt::TopLeftCorner);
+    QVERIFY(leftCornerWidget);
+    int topMargin = (menuBar->height() - leftCornerWidget->height()) / 2;
+    int leftMargin = qApp->style()->pixelMetric(QStyle::PM_MenuBarHMargin)
+                   + qApp->style()->pixelMetric(QStyle::PM_MenuBarPanelWidth);
+    QPoint pos(leftMargin, topMargin);
+    QRect geometry = QStyle::visualRect(qApp->layoutDirection(), menuBar->rect(),
+                                        QRect(pos, leftCornerWidget->size()));
+    QCOMPARE(leftCornerWidget->geometry(), geometry);
+#endif
+}
+
+class EventSpy : public QObject
+{
+public:
+    EventSpy(QObject *object, QEvent::Type event)
+        : eventToSpy(event), _count(0)
+    {
+        if (object)
+            object->installEventFilter(this);
+    }
+
+    int count() const { return _count; }
+    void clear() { _count = 0; }
+
+protected:
+    bool eventFilter(QObject *object, QEvent *event)
+    {
+        if (event->type() == eventToSpy)
+            ++_count;
+        return  QObject::eventFilter(object, event);
+    }
+
+private:
+    QEvent::Type eventToSpy;
+    int _count;
+};
+
+void tst_QMdiArea::resizeTimer()
+{
+    QMdiArea mdiArea;
+    QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+#ifndef Q_OS_WINCE
+    int time = 250;
+#else
+    int time = 1000;
+#endif
+
+    QTest::qWait(time);
+
+    EventSpy timerEventSpy(subWindow, QEvent::Timer);
+    QCOMPARE(timerEventSpy.count(), 0);
+
+    mdiArea.tileSubWindows();
+    QTest::qWait(time); // Wait for timer events to occur.
+    QCOMPARE(timerEventSpy.count(), 1);
+    timerEventSpy.clear();
+
+    mdiArea.resize(mdiArea.size() + QSize(2, 2));
+    QTest::qWait(time); // Wait for timer events to occur.
+    QCOMPARE(timerEventSpy.count(), 1);
+    timerEventSpy.clear();
+
+    // Check that timers are killed.
+    QTest::qWait(time); // Wait for timer events to occur.
+    QCOMPARE(timerEventSpy.count(), 0);
+}
+
+void tst_QMdiArea::updateScrollBars()
+{
+    QMdiArea mdiArea;
+    mdiArea.setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+    mdiArea.setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+
+    QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(new QWidget);
+    QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(new QWidget);
+
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+    qApp->processEvents();
+
+    QScrollBar *hbar = mdiArea.horizontalScrollBar();
+    QVERIFY(hbar);
+    QVERIFY(!hbar->isVisible());
+
+    QScrollBar *vbar = mdiArea.verticalScrollBar();
+    QVERIFY(vbar);
+    QVERIFY(!vbar->isVisible());
+
+    // Move sub-window 2 away.
+    subWindow2->move(10000, 10000);
+    qApp->processEvents();
+    QVERIFY(hbar->isVisible());
+    QVERIFY(vbar->isVisible());
+
+    for (int i = 0; i < 2; ++i) {
+    // Maximize sub-window 1 and make sure we don't have any scroll bars.
+    subWindow1->showMaximized();
+    qApp->processEvents();
+    QVERIFY(subWindow1->isMaximized());
+    QVERIFY(!hbar->isVisible());
+    QVERIFY(!vbar->isVisible());
+
+    // We still shouldn't get any scroll bars.
+    mdiArea.resize(mdiArea.size() - QSize(20, 20));
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+    qApp->processEvents();
+    QVERIFY(subWindow1->isMaximized());
+    QVERIFY(!hbar->isVisible());
+    QVERIFY(!vbar->isVisible());
+
+    // Restore sub-window 1 and make sure we have scroll bars again.
+    subWindow1->showNormal();
+    qApp->processEvents();
+    QVERIFY(!subWindow1->isMaximized());
+    QVERIFY(hbar->isVisible());
+    QVERIFY(vbar->isVisible());
+        if (i == 0) {
+            // Now, do the same when the viewport is scrolled.
+            hbar->setValue(1000);
+            vbar->setValue(1000);
+        }
+    }
+}
+
+void tst_QMdiArea::setActivationOrder_data()
+{
+    QTest::addColumn<QMdiArea::WindowOrder>("activationOrder");
+    QTest::addColumn<int>("subWindowCount");
+    QTest::addColumn<int>("staysOnTopIndex");
+    QTest::addColumn<int>("firstActiveIndex");
+    QTest::addColumn<QList<int> >("expectedActivationIndices");
+    // The order of expectedCascadeIndices:
+    // window 1 -> (index 0)
+    //   window 2 -> (index 1)
+    //     window 3 -> (index 2)
+    // ....
+    QTest::addColumn<QList<int> >("expectedCascadeIndices");
+
+    // The order of expectedTileIndices (the same as reading a book LTR).
+    // +--------------------+--------------------+--------------------+
+    // | window 1 (index 0) | window 2 (index 1) | window 3 (index 2) |
+    // |                    +--------------------+--------------------+
+    // |          (index 3) | window 4 (index 4) | window 5 (index 5) |
+    // +--------------------------------------------------------------+
+    QTest::addColumn<QList<int> >("expectedTileIndices");
+
+    QList<int> list;
+    QList<int> list2;
+    QList<int> list3;
+
+    list << 2 << 1 << 0 << 1 << 2 << 3 << 4;
+    list2 << 0 << 1 << 2 << 3 << 4;
+    list3 << 1 << 4 << 3 << 1 << 2 << 0;
+    QTest::newRow("CreationOrder") << QMdiArea::CreationOrder << 5 << 3 << 1 << list << list2 << list3;
+
+    list = QList<int>();
+    list << 3 << 1 << 4 << 3 << 1 << 2 << 0;
+    list2 = QList<int>();
+    list2 << 0 << 2 << 4 << 1 << 3;
+    list3 = QList<int>();
+    list3 << 1 << 3 << 4 << 1 << 2 << 0;
+    QTest::newRow("StackingOrder") << QMdiArea::StackingOrder << 5 << 3 << 1 << list << list2 << list3;
+
+    list = QList<int>();
+    list << 0 << 1 << 0 << 1 << 4 << 3 << 2;
+    list2 = QList<int>();
+    list2 << 0 << 2 << 3 << 4 << 1;
+    list3 = QList<int>();
+    list3 << 1 << 4 << 3 << 1 << 2 << 0;
+    QTest::newRow("ActivationHistoryOrder") << QMdiArea::ActivationHistoryOrder << 5 << 3 << 1 << list << list2 << list3;
+}
+
+void tst_QMdiArea::setActivationOrder()
+{
+    QFETCH(QMdiArea::WindowOrder, activationOrder);
+    QFETCH(int, subWindowCount);
+    QFETCH(int, staysOnTopIndex);
+    QFETCH(int, firstActiveIndex);
+    QFETCH(QList<int>, expectedActivationIndices);
+    QFETCH(QList<int>, expectedCascadeIndices);
+    QFETCH(QList<int>, expectedTileIndices);
+
+    // Default order.
+    QMdiArea mdiArea;
+    QCOMPARE(mdiArea.activationOrder(), QMdiArea::CreationOrder);
+
+    // New order.
+    mdiArea.setActivationOrder(activationOrder);
+    QCOMPARE(mdiArea.activationOrder(), activationOrder);
+
+    QList<QMdiSubWindow *> subWindows;
+    for (int i = 0; i < subWindowCount; ++i)
+        subWindows << mdiArea.addSubWindow(new QPushButton(tr("%1").arg(i)));
+    QCOMPARE(mdiArea.subWindowList(activationOrder), subWindows);
+
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    for (int i = 0; i < subWindows.count(); ++i) {
+        mdiArea.activateNextSubWindow();
+        QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(i));
+        qApp->processEvents();
+    }
+
+    QMdiSubWindow *staysOnTop = subWindows.at(staysOnTopIndex);
+    staysOnTop->setWindowFlags(staysOnTop->windowFlags() | Qt::WindowStaysOnTopHint);
+    staysOnTop->raise();
+
+    mdiArea.setActiveSubWindow(subWindows.at(firstActiveIndex));
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(firstActiveIndex));
+
+    // Verify the actual arrangement/geometry.
+    mdiArea.tileSubWindows();
+    QTest::qWait(100);
+    QVERIFY(verifyArrangement(&mdiArea, Tiled, expectedTileIndices));
+
+    mdiArea.cascadeSubWindows();
+    QVERIFY(verifyArrangement(&mdiArea, Cascaded, expectedCascadeIndices));
+    QTest::qWait(100);
+
+    mdiArea.activateNextSubWindow();
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+    mdiArea.activatePreviousSubWindow();
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+    mdiArea.activatePreviousSubWindow();
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+
+    for (int i = 0; i < subWindowCount; ++i) {
+        mdiArea.closeActiveSubWindow();
+        qApp->processEvents();
+        if (i == subWindowCount - 1) { // Last window closed.
+            QVERIFY(!mdiArea.activeSubWindow());
+            break;
+        }
+        QVERIFY(mdiArea.activeSubWindow());
+        QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(expectedActivationIndices.takeFirst()));
+    }
+
+    QVERIFY(mdiArea.subWindowList(activationOrder).isEmpty());
+    QVERIFY(expectedActivationIndices.isEmpty());
+}
+
+void tst_QMdiArea::tabBetweenSubWindows()
+{
+    QMdiArea mdiArea;
+    QList<QMdiSubWindow *> subWindows;
+    for (int i = 0; i < 5; ++i)
+        subWindows << mdiArea.addSubWindow(new QLineEdit);
+
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    qApp->setActiveWindow(&mdiArea);
+    QWidget *focusWidget = subWindows.back()->widget();
+    QCOMPARE(qApp->focusWidget(), focusWidget);
+
+    QSignalSpy spy(&mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)));
+    QCOMPARE(spy.count(), 0);
+
+    // Walk through the entire list of sub windows.
+    QVERIFY(tabBetweenSubWindowsIn(&mdiArea));
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.back());
+    QCOMPARE(spy.count(), 0);
+
+    mdiArea.setActiveSubWindow(subWindows.front());
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
+    spy.clear();
+
+    // Walk through the entire list of sub windows in the opposite direction (Ctrl-Shift-Tab).
+    QVERIFY(tabBetweenSubWindowsIn(&mdiArea, -1, true));
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.front());
+    QCOMPARE(spy.count(), 0);
+
+    // Ctrl-Tab-Tab-Tab
+    QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 3));
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
+    QCOMPARE(spy.count(), 1);
+
+    mdiArea.setActiveSubWindow(subWindows.at(1));
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(1));
+    spy.clear();
+
+    // Quick switch (Ctrl-Tab once) -> switch back to the previously active sub-window.
+    QVERIFY(tabBetweenSubWindowsIn(&mdiArea, 1));
+    QCOMPARE(mdiArea.activeSubWindow(), subWindows.at(3));
+    QCOMPARE(spy.count(), 1);
+}
+
+void tst_QMdiArea::setViewMode()
+{
+    QMdiArea mdiArea;
+
+    QPixmap iconPixmap(16, 16);
+    iconPixmap.fill(Qt::red);
+    for (int i = 0; i < 5; ++i) {
+        QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QWidget);
+        subWindow->setWindowTitle(QString(QLatin1String("Title %1")).arg(i));
+        subWindow->setWindowIcon(iconPixmap);
+    }
+
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    QMdiSubWindow *activeSubWindow = mdiArea.activeSubWindow();
+    const QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList();
+
+    // Default.
+    QVERIFY(!activeSubWindow->isMaximized());
+    QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+    QVERIFY(!tabBar);
+    QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
+
+    // Tabbed view.
+    mdiArea.setViewMode(QMdiArea::TabbedView);
+    QCOMPARE(mdiArea.viewMode(), QMdiArea::TabbedView);
+    tabBar = qFindChild<QTabBar *>(&mdiArea);
+    QVERIFY(tabBar);
+    QVERIFY(tabBar->isVisible());
+
+    QCOMPARE(tabBar->count(), subWindows.count());
+    QVERIFY(activeSubWindow->isMaximized());
+    QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
+
+    // Check that tabIcon and tabText are set properly.
+    for (int i = 0; i < subWindows.size(); ++i) {
+        QMdiSubWindow *subWindow = subWindows.at(i);
+        QCOMPARE(tabBar->tabText(i), subWindow->windowTitle());
+        QCOMPARE(tabBar->tabIcon(i), subWindow->windowIcon());
+    }
+
+    // Check that tabText and tabIcon are updated.
+    activeSubWindow->setWindowTitle(QLatin1String("Dude, I want another window title"));
+    QCOMPARE(tabBar->tabText(tabBar->currentIndex()), activeSubWindow->windowTitle());
+    iconPixmap.fill(Qt::green);
+    activeSubWindow->setWindowIcon(iconPixmap);
+    QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), activeSubWindow->windowIcon());
+
+    // If there's an empty window title, tabText should return "(Untitled)" (as in firefox).
+    activeSubWindow->setWindowTitle(QString());
+    QCOMPARE(tabBar->tabText(tabBar->currentIndex()), QLatin1String("(Untitled)"));
+
+    // If there's no window icon, tabIcon should return ... an empty icon :)
+    activeSubWindow->setWindowIcon(QIcon());
+    QCOMPARE(tabBar->tabIcon(tabBar->currentIndex()), QIcon());
+
+    // Check that the current tab changes when activating another sub-window.
+    for (int i = 0; i < subWindows.size(); ++i) {
+        mdiArea.activateNextSubWindow();
+        activeSubWindow = mdiArea.activeSubWindow();
+        QCOMPARE(tabBar->currentIndex(), subWindows.indexOf(activeSubWindow));
+    }
+
+    activeSubWindow = mdiArea.activeSubWindow();
+    const int tabIndex = tabBar->currentIndex();
+
+    // The current tab should not change when the sub-window is hidden.
+    activeSubWindow->hide();
+    QCOMPARE(tabBar->currentIndex(), tabIndex);
+    activeSubWindow->show();
+    QCOMPARE(tabBar->currentIndex(), tabIndex);
+
+    // Disable the tab when the sub-window is hidden and another sub-window is activated.
+    activeSubWindow->hide();
+    mdiArea.activateNextSubWindow();
+    QVERIFY(tabBar->currentIndex() != tabIndex);
+    QVERIFY(!tabBar->isTabEnabled(tabIndex));
+
+    // Enable it again.
+    activeSubWindow->show();
+    QCOMPARE(tabBar->currentIndex(), tabIndex);
+    QVERIFY(tabBar->isTabEnabled(tabIndex));
+
+    // Remove sub-windows and make sure the tab is removed.
+    foreach (QMdiSubWindow *subWindow, subWindows) {
+        if (subWindow != activeSubWindow)
+            mdiArea.removeSubWindow(subWindow);
+    }
+    QCOMPARE(tabBar->count(), 1);
+
+    // Go back to default (QMdiArea::SubWindowView).
+    mdiArea.setViewMode(QMdiArea::SubWindowView);
+    QVERIFY(!activeSubWindow->isMaximized());
+    tabBar = qFindChild<QTabBar *>(&mdiArea);
+    QVERIFY(!tabBar);
+    QCOMPARE(mdiArea.viewMode(), QMdiArea::SubWindowView);
+}
+
+void tst_QMdiArea::setTabShape()
+{
+    QMdiArea mdiArea;
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    // Default.
+    QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
+
+    // Triangular.
+    mdiArea.setTabShape(QTabWidget::Triangular);
+    QCOMPARE(mdiArea.tabShape(), QTabWidget::Triangular);
+
+    mdiArea.setViewMode(QMdiArea::TabbedView);
+
+    QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+    QVERIFY(tabBar);
+    QCOMPARE(tabBar->shape(), QTabBar::TriangularNorth);
+
+    // Back to default (Rounded).
+    mdiArea.setTabShape(QTabWidget::Rounded);
+    QCOMPARE(mdiArea.tabShape(), QTabWidget::Rounded);
+    QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
+}
+
+void tst_QMdiArea::setTabPosition_data()
+{
+    QTest::addColumn<QTabWidget::TabPosition>("tabPosition");
+    QTest::addColumn<bool>("hasLeftMargin");
+    QTest::addColumn<bool>("hasTopMargin");
+    QTest::addColumn<bool>("hasRightMargin");
+    QTest::addColumn<bool>("hasBottomMargin");
+
+    QTest::newRow("North") << QTabWidget::North << false << true << false << false;
+    QTest::newRow("South") << QTabWidget::South << false << false << false << true;
+    QTest::newRow("East") << QTabWidget::East << false << false << true << false;
+    QTest::newRow("West") << QTabWidget::West << true << false << false << false;
+}
+
+void tst_QMdiArea::setTabPosition()
+{
+    QFETCH(QTabWidget::TabPosition, tabPosition);
+    QFETCH(bool, hasLeftMargin);
+    QFETCH(bool, hasTopMargin);
+    QFETCH(bool, hasRightMargin);
+    QFETCH(bool, hasBottomMargin);
+
+    QMdiArea mdiArea;
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    // Make sure there are no margins.
+    mdiArea.setContentsMargins(0, 0, 0, 0);
+
+    // Default.
+    QCOMPARE(mdiArea.tabPosition(), QTabWidget::North);
+    mdiArea.setViewMode(QMdiArea::TabbedView);
+    QTabBar *tabBar = qFindChild<QTabBar *>(&mdiArea);
+    QVERIFY(tabBar);
+    QCOMPARE(tabBar->shape(), QTabBar::RoundedNorth);
+
+    // New position.
+    mdiArea.setTabPosition(tabPosition);
+    QCOMPARE(mdiArea.tabPosition(), tabPosition);
+    QCOMPARE(tabBar->shape(), tabBarShapeFrom(QTabWidget::Rounded, tabPosition));
+
+    const Qt::LayoutDirection originalLayoutDirection = qApp->layoutDirection();
+
+    // Check that we have correct geometry in both RightToLeft and LeftToRight.
+    for (int i = 0; i < 2; ++i) {
+        // Check viewportMargins.
+        const QRect viewportGeometry = mdiArea.viewport()->geometry();
+        const int left = viewportGeometry.left();
+        const int top = viewportGeometry.y();
+        const int right = mdiArea.width() - viewportGeometry.width();
+        const int bottom = mdiArea.height() - viewportGeometry.height();
+
+        const QSize sizeHint = tabBar->sizeHint();
+
+        if (hasLeftMargin)
+            QCOMPARE(qApp->isLeftToRight() ? left : right, sizeHint.width());
+        if (hasRightMargin)
+            QCOMPARE(qApp->isLeftToRight() ? right : left, sizeHint.width());
+        if (hasTopMargin || hasBottomMargin)
+            QCOMPARE(hasTopMargin ? top : bottom, sizeHint.height());
+
+        // Check actual tab bar geometry.
+        const QRegion expectedTabBarGeometry = QRegion(mdiArea.rect()).subtracted(viewportGeometry);
+        QVERIFY(!expectedTabBarGeometry.isEmpty());
+        QCOMPARE(QRegion(tabBar->geometry()), expectedTabBarGeometry);
+
+        if (i == 0)
+            qApp->setLayoutDirection(originalLayoutDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight);
+        qApp->processEvents();
+    }
+
+    qApp->setLayoutDirection(originalLayoutDirection);
+}
+
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+void tst_QMdiArea::nativeSubWindows()
+{
+    { // Add native widgets after show.
+    QMdiArea mdiArea;
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    // No native widgets.
+    QVERIFY(!mdiArea.viewport()->internalWinId());
+    foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+        QVERIFY(!subWindow->internalWinId());
+
+    QWidget *nativeWidget = new QWidget;
+    QVERIFY(nativeWidget->winId()); // enforce native window.
+    mdiArea.addSubWindow(nativeWidget);
+
+    // The viewport and all the sub-windows must be native.
+    QVERIFY(mdiArea.viewport()->internalWinId());
+    foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+        QVERIFY(subWindow->internalWinId());
+
+    // Add a non-native widget. This should become native.
+    QMdiSubWindow *subWindow = new QMdiSubWindow;
+    subWindow->setWidget(new QWidget);
+    QVERIFY(!subWindow->internalWinId());
+    mdiArea.addSubWindow(subWindow);
+    QVERIFY(subWindow->internalWinId());
+    }
+
+    { // Add native widgets before show.
+    QMdiArea mdiArea;
+    mdiArea.addSubWindow(new QWidget);
+    QWidget *nativeWidget = new QWidget;
+    (void)nativeWidget->winId();
+    mdiArea.addSubWindow(nativeWidget);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    // The viewport and all the sub-windows must be native.
+    QVERIFY(mdiArea.viewport()->internalWinId());
+    foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+        QVERIFY(subWindow->internalWinId());
+    }
+
+    { // Make a sub-window native *after* it's added to the area.
+    QMdiArea mdiArea;
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    QMdiSubWindow *nativeSubWindow = mdiArea.subWindowList().last();
+    QVERIFY(!nativeSubWindow->internalWinId());
+    (void)nativeSubWindow->winId();
+
+    // All the sub-windows should be native at this point
+    QVERIFY(mdiArea.viewport()->internalWinId());
+    foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+            QVERIFY(subWindow->internalWinId());
+    }
+
+#ifndef QT_NO_OPENGL
+    {
+    if (!QGLFormat::hasOpenGL())
+        QSKIP("QGL not supported on this platform", SkipAll);
+
+    QMdiArea mdiArea;
+    QGLWidget *glViewport = new QGLWidget;
+    mdiArea.setViewport(glViewport);
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.addSubWindow(new QWidget);
+    mdiArea.show();
+#ifdef Q_WS_X11
+    qt_x11_wait_for_window_manager(&mdiArea);
+#endif
+
+    const QGLContext *context = glViewport->context();
+    if (!context || !context->isValid())
+        QSKIP("QGL is broken, cannot continue test", SkipAll);
+
+    // The viewport and all the sub-windows must be native.
+    QVERIFY(mdiArea.viewport()->internalWinId());
+    foreach (QMdiSubWindow *subWindow, mdiArea.subWindowList())
+        QVERIFY(subWindow->internalWinId());
+    }
+#endif
+}
+#endif
+
+void tst_QMdiArea::task_209615()
+{
+    QTabWidget tabWidget;
+    QMdiArea *mdiArea1 = new QMdiArea;
+    QMdiArea *mdiArea2 = new QMdiArea;
+    QMdiSubWindow *subWindow = mdiArea1->addSubWindow(new QLineEdit);
+
+    tabWidget.addTab(mdiArea1, QLatin1String("1"));
+    tabWidget.addTab(mdiArea2, QLatin1String("2"));
+    tabWidget.show();
+
+    mdiArea1->removeSubWindow(subWindow);
+    mdiArea2->addSubWindow(subWindow);
+
+    // Please do not assert/crash.
+    tabWidget.setCurrentIndex(1);
+}
+
+void tst_QMdiArea::task_236750()
+{
+    QMdiArea mdiArea;
+    QMdiSubWindow *subWindow = mdiArea.addSubWindow(new QTextEdit);
+    mdiArea.show();
+
+    subWindow->setWindowFlags(subWindow->windowFlags() | Qt::FramelessWindowHint);
+    // Please do not crash (floating point exception).
+    subWindow->showMinimized();
+}
+
+QTEST_MAIN(tst_QMdiArea)
+#include "tst_qmdiarea.moc"
+