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>
This commit is contained in:
parent
cd89ec830d
commit
0240110c58
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user