diff options
author | Jan Arve Saether <jan-arve.saether@qt.io> | 2017-01-03 13:46:46 +0100 |
---|---|---|
committer | Jan Arve Sæther <jan-arve.saether@qt.io> | 2017-02-07 15:01:23 +0000 |
commit | e6cc5382d9b789274d3e16e8601f33075b6a4b1c (patch) | |
tree | b0610f3e02b433fd028773546f1a808b7decfc16 /tests/auto/applicationwindow/tst_applicationwindow.cpp | |
parent | f0ce8b847e2169ad4ae884dbb35b58e6dd0f1859 (diff) |
Fix a crash with focus handling when destructing QQAppWindow
Because QQuickApplicationWindow connected
SIGNAL(activeFocusItemChanged())
to
SLOT(_q_updateActiveFocus()));
it would enter _q_updateActiveFocus() from the dtor of QQuickWindow
(because dtor of QQuickWindow would emit activeFocusItemChanged()).
At that point the QQuickApplicationWindow object for the member function
_q_updateActiveFocus() was already destroyed, so we would crash.
Instead, make sure we clear the focus as early as possible, and then
disconnect in case activeFocusItemChanged() is emitted after
QQuickApplicationWindow is destroyed.
Task-number: QTBUG-57846
Change-Id: I4b1999e647b970394436a2d462b7f352f1c8a811
Reviewed-by: J-P Nurmi <jpnurmi@qt.io>
Diffstat (limited to 'tests/auto/applicationwindow/tst_applicationwindow.cpp')
-rw-r--r-- | tests/auto/applicationwindow/tst_applicationwindow.cpp | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/tests/auto/applicationwindow/tst_applicationwindow.cpp b/tests/auto/applicationwindow/tst_applicationwindow.cpp index 2a3f849c..b72bb8f2 100644 --- a/tests/auto/applicationwindow/tst_applicationwindow.cpp +++ b/tests/auto/applicationwindow/tst_applicationwindow.cpp @@ -72,6 +72,7 @@ private slots: void activeFocusControl_data(); void activeFocusControl(); void focusAfterPopupClosed(); + void clearFocusOnDestruction(); void layout(); }; @@ -685,6 +686,47 @@ void tst_applicationwindow::focusAfterPopupClosed() QCOMPARE(spy.count(), 2); } +void tst_applicationwindow::clearFocusOnDestruction() +{ + QQmlEngine engine; + QQmlComponent component(&engine); + component.loadUrl(testFileUrl("clearfocusondestruction.qml")); + QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow*>(component.create())); + QVERIFY(window); + + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window.data())); + QVERIFY(QGuiApplication::focusWindow() == window.data()); + + QQuickItem* contentItem = window->contentItem(); + QVERIFY(contentItem); + QVERIFY(contentItem->hasActiveFocus()); + + QQuickItem* focusScope = window->property("textfield").value<QQuickItem*>(); + QVERIFY(focusScope); + QVERIFY(focusScope->hasActiveFocus()); + + QSignalSpy spy(window.data(), SIGNAL(activeFocusControlChanged())); + // destroy the window, do not crash + window.reset(); + + /* + QQuickWindow::activeFocusItemChanged() is emitted inconsistently and + only for certain use cases. Ideally it should be emitted whenever a + QQuickWindow with a focus item is destroyed, but it doesn't... It might + also be favorable to not emit it for performance reason. + + However, activeFocusControlChanged() is emitted more consistently, which + of course makes it inconsistent with the emission of + activeFocusItemChanged().... + + Therefore, if you have good reasons to change the behavior (and not emit + it) take the test below with a grain of salt. + */ + QCOMPARE(spy.count(), 1); +} + void tst_applicationwindow::layout() { QQmlEngine engine; |