summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/dialogs/qfiledialog
diff options
context:
space:
mode:
authorMitch Curtis <mitch.curtis@qt.io>2017-05-24 17:15:17 +0200
committerMitch Curtis <mitch.curtis@qt.io>2017-05-30 10:49:36 +0000
commitc25ad981a334a4a720ae48cfe800868c4aef51a9 (patch)
tree30c6e54171a4af2dfb9cb4b4f77d4d66595f5be4 /tests/auto/widgets/dialogs/qfiledialog
parent88f30250eb15b520415658c6c32f48fda111b6bf (diff)
QWidgetWindow: don't give focus to windows that are being destroyed
In the referenced bug report, dismissing a QFileDialog while the Qt Virtual Keyboard was in use would result in a crash. Dismissing a file dialog created with e.g. QFileDialog::getOpenFileName() causes it to eventually be destroyed. When this happens, it starts deleting its children. Each child widget's destructor calls clearFocus(). In clearFocus(), there is a block of code that emits QWindow::focusChanged(), passing the result of focusObject() called on that widget's window. QWidgetWindow::focusObject() could end up using itself as a fallback focus object if it had no other focus objects (e.g. children) to use instead, even though it was in the process of being destroyed; as were all of its children. The Qt Virtual Keyboard plugin would then try to use the focus object, even though it was in an invalid state. To fix this problem, we return early from QWidgetWindow::focusObject() if the window is in the process of being destroyed. Task-number: QTBUG-57193 Change-Id: I137cf9415812ce2e0419c0afe8076ce150f248cb Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Jarkko Koivikko <jarkko.koivikko@code-q.fi> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'tests/auto/widgets/dialogs/qfiledialog')
-rw-r--r--tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp34
1 files changed, 33 insertions, 1 deletions
diff --git a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
index 8d209fc241..05410f4a0f 100644
--- a/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
+++ b/tests/auto/widgets/dialogs/qfiledialog/tst_qfiledialog.cpp
@@ -144,6 +144,7 @@ private slots:
#endif
void rejectModalDialogs();
void QTBUG49600_nativeIconProviderCrash();
+ void focusObjectDuringDestruction();
// NOTE: Please keep widgetlessNativeDialog() as the LAST test!
//
@@ -1467,7 +1468,7 @@ public:
}
public slots:
- void rejectFileDialog()
+ virtual void rejectFileDialog()
{
if (QWidget *w = QApplication::activeModalWidget())
if (QDialog *d = qobject_cast<QDialog *>(w))
@@ -1511,5 +1512,36 @@ void tst_QFiledialog::QTBUG49600_nativeIconProviderCrash()
fd.iconProvider();
}
+class qtbug57193DialogRejecter : public DialogRejecter
+{
+public:
+ void rejectFileDialog() override
+ {
+ QCOMPARE(QGuiApplication::topLevelWindows().size(), 1);
+ const QWindow *window = QGuiApplication::topLevelWindows().constFirst();
+
+ const QFileDialog *fileDialog = qobject_cast<QFileDialog*>(QApplication::activeModalWidget());
+ QVERIFY(fileDialog);
+
+ // The problem in QTBUG-57193 was from a platform input context plugin that was
+ // connected to QWindow::focusObjectChanged(), and consequently accessed the focus
+ // object (the QFileDialog) that was in the process of being destroyed. This test
+ // checks that the QFileDialog is never set as the focus object after its destruction process begins.
+ connect(window, &QWindow::focusObjectChanged, [=](QObject *focusObject) {
+ QVERIFY(focusObject != fileDialog);
+ });
+ DialogRejecter::rejectFileDialog();
+ }
+};
+
+void tst_QFiledialog::focusObjectDuringDestruction()
+{
+ QTRY_VERIFY(QGuiApplication::topLevelWindows().isEmpty());
+
+ qtbug57193DialogRejecter dialogRejecter;
+
+ QFileDialog::getOpenFileName(nullptr, QString(), QString(), QString(), nullptr);
+}
+
QTEST_MAIN(tst_QFiledialog)
#include "tst_qfiledialog.moc"