diff options
author | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-06-18 14:53:53 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@digia.com> | 2014-07-30 06:29:00 +0200 |
commit | 0240110c58f0d6b694445f6685f0f77b14b769d8 (patch) | |
tree | ad2268b065362ae5e3f95fde52b8176ade366f75 | |
parent | cd89ec830d1a34601540a24fe00a8b56bab8312c (diff) |
QMdiArea: Store focus widget when new QMdiSubWindow is added.
Introduce function QMdiSubWindowPrivate::storeFocusWidget()
to store focus widget and call this when de-activating a
sub window. Change restoreFocus() to return a bool and call
it from QMdiSubWindowPrivate::setActive().
Task-number: QTBUG-38378
Change-Id: I18dbe66ce85213ca5b4907b5a09126544415351a
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
-rw-r--r-- | src/widgets/widgets/qmdisubwindow.cpp | 42 | ||||
-rw-r--r-- | src/widgets/widgets/qmdisubwindow_p.h | 3 | ||||
-rw-r--r-- | tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp | 47 |
3 files changed, 75 insertions, 17 deletions
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp index 9104074122..5521d866b2 100644 --- a/src/widgets/widgets/qmdisubwindow.cpp +++ b/src/widgets/widgets/qmdisubwindow.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -1321,6 +1321,14 @@ void QMdiSubWindowPrivate::setNormalMode() updateMask(); } +inline void QMdiSubWindowPrivate::storeFocusWidget() +{ + if (QWidget *focus = QApplication::focusWidget()) { + if (!restoreFocusWidget && q_func()->isAncestorOf(focus)) + restoreFocusWidget = focus; + } +} + /*! \internal */ @@ -1333,8 +1341,7 @@ void QMdiSubWindowPrivate::setMaximizeMode() isShadeMode = false; isMaximizeMode = true; - if (!restoreFocusWidget && q->isAncestorOf(QApplication::focusWidget())) - restoreFocusWidget = QApplication::focusWidget(); + storeFocusWidget(); #ifndef QT_NO_SIZEGRIP setSizeGripVisible(false); @@ -1436,6 +1443,7 @@ void QMdiSubWindowPrivate::setActive(bool activate, bool changeFocus) Qt::WindowStates oldWindowState = q->windowState(); q->overrideWindowState(q->windowState() & ~Qt::WindowActive); if (changeFocus) { + storeFocusWidget(); QWidget *focusWidget = QApplication::focusWidget(); if (focusWidget && (focusWidget == q || q->isAncestorOf(focusWidget))) focusWidget->clearFocus(); @@ -2026,6 +2034,9 @@ void QMdiSubWindowPrivate::setFocusWidget() return; } + if (!(q->windowState() & Qt::WindowMinimized) && restoreFocus()) + return; + if (QWidget *focusWidget = baseWidget->focusWidget()) { if (!focusWidget->hasFocus() && q->isAncestorOf(focusWidget) && focusWidget->isVisible() && !q->isMinimized() @@ -2048,16 +2059,19 @@ void QMdiSubWindowPrivate::setFocusWidget() q->setFocus(); } -void QMdiSubWindowPrivate::restoreFocus() +bool QMdiSubWindowPrivate::restoreFocus() { - if (!restoreFocusWidget) - return; - if (!restoreFocusWidget->hasFocus() && q_func()->isAncestorOf(restoreFocusWidget) - && restoreFocusWidget->isVisible() - && restoreFocusWidget->focusPolicy() != Qt::NoFocus) { - restoreFocusWidget->setFocus(); + if (restoreFocusWidget.isNull()) + return false; + QWidget *candidate = restoreFocusWidget; + restoreFocusWidget.clear(); + if (!candidate->hasFocus() && q_func()->isAncestorOf(candidate) + && candidate->isVisible() + && candidate->focusPolicy() != Qt::NoFocus) { + candidate->setFocus(); + return true; } - restoreFocusWidget = 0; + return candidate->hasFocus(); } /*! @@ -2605,9 +2619,7 @@ void QMdiSubWindow::showShaded() d->isMaximizeMode = false; - QWidget *currentFocusWidget = QApplication::focusWidget(); - if (!d->restoreFocusWidget && isAncestorOf(currentFocusWidget)) - d->restoreFocusWidget = currentFocusWidget; + d->storeFocusWidget(); if (!d->isShadeRequestFromMinimizeMode) { d->isShadeMode = true; @@ -2621,7 +2633,7 @@ void QMdiSubWindow::showShaded() // showMinimized() will reset Qt::WindowActive, which makes sense // for top level widgets, but in MDI it makes sense to have an // active window which is minimized. - if (hasFocus() || isAncestorOf(currentFocusWidget)) + if (hasFocus() || isAncestorOf(QApplication::focusWidget())) d->ensureWindowState(Qt::WindowActive); #ifndef QT_NO_SIZEGRIP diff --git a/src/widgets/widgets/qmdisubwindow_p.h b/src/widgets/widgets/qmdisubwindow_p.h index 90369ff526..6abbe89b4c 100644 --- a/src/widgets/widgets/qmdisubwindow_p.h +++ b/src/widgets/widgets/qmdisubwindow_p.h @@ -266,7 +266,8 @@ public: QPalette desktopPalette() const; void updateActions(); void setFocusWidget(); - void restoreFocus(); + bool restoreFocus(); + void storeFocusWidget(); void setWindowFlags(Qt::WindowFlags windowFlags); void setVisible(WindowStateAction, bool visible = true); #ifndef QT_NO_ACTION diff --git a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp index ffc3e3b67d..60fd946d52 100644 --- a/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp +++ b/tests/auto/widgets/widgets/qmdisubwindow/tst_qmdisubwindow.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the test suite of the Qt Toolkit. @@ -58,6 +58,7 @@ #include <QStyle> #include <QStyleOptionTitleBar> #include <QPushButton> +#include <QScreen> #include <QSizeGrip> #include "../../../qtest-config.h" @@ -182,6 +183,7 @@ private slots: void mouseDoubleClick(); void setSystemMenu(); void restoreFocus(); + void restoreFocusOverCreation(); void changeFocusWithTab(); void closeEvent(); void setWindowTitle(); @@ -1126,6 +1128,7 @@ void tst_QMdiSubWindow::restoreFocus() expectedFocusWindow->showMinimized(); qApp->processEvents(); QVERIFY(expectedFocusWindow->isMinimized()); + qDebug() << expectedFocusWindow<< qApp->focusWidget(); QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow)); // Minimized -> normal @@ -1178,6 +1181,48 @@ void tst_QMdiSubWindow::restoreFocus() QCOMPARE(qApp->focusWidget(), static_cast<QWidget *>(expectedFocusWindow)); } +class MultiWidget : public QWidget { +public: + explicit MultiWidget(QWidget *parent = 0) : QWidget(parent) + , m_lineEdit1(new QLineEdit(this)), m_lineEdit2(new QLineEdit(this)) + { + QVBoxLayout *lt = new QVBoxLayout(this); + lt->addWidget(m_lineEdit1); + lt->addWidget(m_lineEdit2); + } + + QLineEdit *m_lineEdit1; + QLineEdit *m_lineEdit2; +}; + +void tst_QMdiSubWindow::restoreFocusOverCreation() +{ + // QTBUG-38378, verify that the focus child of a subwindow + // is not "forgotten" when adding yet another subwindow. + QMdiArea mdiArea; + mdiArea.resize(800, 800); + mdiArea.move(QGuiApplication::primaryScreen()->availableGeometry().center() - QPoint(400, 400)); + mdiArea.setWindowTitle(QStringLiteral("restoreFocusOverCreation")); + + MultiWidget *subWidget1 = new MultiWidget; + MultiWidget *subWidget2 = new MultiWidget; + + QMdiSubWindow *subWindow1 = mdiArea.addSubWindow(subWidget1); + subWidget1->m_lineEdit2->setFocus(); + subWindow1->show(); + mdiArea.show(); + QApplication::setActiveWindow(&mdiArea); + QVERIFY(QTest::qWaitForWindowActive(&mdiArea)); + QCOMPARE(QApplication::focusWidget(), subWidget1->m_lineEdit2); + + QMdiSubWindow *subWindow2 = mdiArea.addSubWindow(subWidget2); + subWindow2->show(); + QTRY_COMPARE(QApplication::focusWidget(), subWidget2->m_lineEdit1); + + mdiArea.setActiveSubWindow(subWindow1); + QTRY_COMPARE(QApplication::focusWidget(), subWidget1->m_lineEdit2); +} + void tst_QMdiSubWindow::changeFocusWithTab() { QWidget *widget = new QWidget; |