aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKari Oikarinen <kari.oikarinen@qt.io>2019-11-26 14:49:20 +0200
committerKari Oikarinen <kari.oikarinen@qt.io>2019-11-26 14:49:20 +0200
commit0d2fc12b65028b4f04bdace3991448813130ab48 (patch)
tree3666621eced42e3a2f663085a6fd969585edada9
parent546539562f2aff985e78f3c2426cb711a865ad65 (diff)
parentf9877da406ad96d82becb15b6eef9b723b8807e3 (diff)
Merge 5.14 into 5.14.0v5.14.0-rc2v5.14.0-rc1v5.14.0
-rw-r--r--src/quicktemplates2/qquickpopup.cpp17
-rw-r--r--tests/auto/controls/data/tst_dial.qml22
-rw-r--r--tests/auto/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml80
-rw-r--r--tests/auto/qquickpopup/tst_qquickpopup.cpp49
4 files changed, 155 insertions, 13 deletions
diff --git a/src/quicktemplates2/qquickpopup.cpp b/src/quicktemplates2/qquickpopup.cpp
index f272c5cf..45cbecf4 100644
--- a/src/quicktemplates2/qquickpopup.cpp
+++ b/src/quicktemplates2/qquickpopup.cpp
@@ -485,11 +485,18 @@ void QQuickPopupPrivate::finalizeExitTransition()
if (hadActiveFocusBeforeExitTransition && window) {
// restore focus to the next popup in chain, or to the window content if there are no other popups open
- QQuickPopup *popup = nullptr;
- if (QQuickOverlay *overlay = QQuickOverlay::overlay(window))
- popup = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups().value(0);
- if (popup && popup->hasFocus()) {
- popup->forceActiveFocus();
+ QQuickPopup *nextFocusPopup = nullptr;
+ if (QQuickOverlay *overlay = QQuickOverlay::overlay(window)) {
+ const auto stackingOrderPopups = QQuickOverlayPrivate::get(overlay)->stackingOrderPopups();
+ for (auto popup : stackingOrderPopups) {
+ if (QQuickPopupPrivate::get(popup)->transitionState != ExitTransition) {
+ nextFocusPopup = popup;
+ break;
+ }
+ }
+ }
+ if (nextFocusPopup && nextFocusPopup->hasFocus()) {
+ nextFocusPopup->forceActiveFocus();
} else {
QQuickApplicationWindow *applicationWindow = qobject_cast<QQuickApplicationWindow*>(window);
if (applicationWindow)
diff --git a/tests/auto/controls/data/tst_dial.qml b/tests/auto/controls/data/tst_dial.qml
index 86999594..26f30c33 100644
--- a/tests/auto/controls/data/tst_dial.qml
+++ b/tests/auto/controls/data/tst_dial.qml
@@ -223,33 +223,39 @@ TestCase {
var minimumExpectedValueCount = data.live ? 2 : 1;
// drag to the left
- mouseDrag(dial, dial.width / 2, dial.height / 2, -dial.width / 2, 0, Qt.LeftButton);
+ // we always add or subtract 1 to ensure we start the drag from the opposite side
+ // of where we're dragging to, for more reliable tests
+ mouseDrag(dial, dial.width / 2 + 1, dial.height / 2, -dial.width / 2, 0, Qt.LeftButton);
fuzzyCompare(dial.value, data.leftValue, 0.1);
- verify(valueSpy.count >= minimumExpectedValueCount);
+ verify(valueSpy.count >= minimumExpectedValueCount, "expected valueChanged to be emitted at least "
+ + minimumExpectedValueCount + " time(s), but it was only emitted " + valueSpy.count + " time(s)");
valueSpy.clear();
verify(moveSpy.count > 0);
moveSpy.clear();
// drag to the top
- mouseDrag(dial, dial.width / 2, dial.height / 2, 0, -dial.height / 2, Qt.LeftButton);
+ mouseDrag(dial, dial.width / 2, dial.height / 2 + 1, 0, -dial.height / 2, Qt.LeftButton);
fuzzyCompare(dial.value, data.topValue, 0.1);
- verify(valueSpy.count >= minimumExpectedValueCount);
+ verify(valueSpy.count >= minimumExpectedValueCount, "expected valueChanged to be emitted at least "
+ + minimumExpectedValueCount + " time(s), but it was only emitted " + valueSpy.count + " time(s)");
valueSpy.clear();
verify(moveSpy.count > 0);
moveSpy.clear();
// drag to the right
- mouseDrag(dial, dial.width / 2, dial.height / 2, dial.width / 2, 0, Qt.LeftButton);
+ mouseDrag(dial, dial.width / 2 - 1, dial.height / 2, dial.width / 2, 0, Qt.LeftButton);
fuzzyCompare(dial.value, data.rightValue, 0.1);
- verify(valueSpy.count >= minimumExpectedValueCount);
+ verify(valueSpy.count >= minimumExpectedValueCount, "expected valueChanged to be emitted at least "
+ + minimumExpectedValueCount + " time(s), but it was only emitted " + valueSpy.count + " time(s)");
valueSpy.clear();
verify(moveSpy.count > 0);
moveSpy.clear();
// drag to the bottom (* 0.6 to ensure we don't go over to the minimum position)
- mouseDrag(dial, dial.width / 2, dial.height / 2, 10, dial.height / 2, Qt.LeftButton);
+ mouseDrag(dial, dial.width / 2, dial.height / 2 - 1, 10, dial.height / 2, Qt.LeftButton);
fuzzyCompare(dial.value, data.bottomValue, 0.1);
- verify(valueSpy.count >= minimumExpectedValueCount);
+ verify(valueSpy.count >= minimumExpectedValueCount, "expected valueChanged to be emitted at least "
+ + minimumExpectedValueCount + " time(s), but it was only emitted " + valueSpy.count + " time(s)");
valueSpy.clear();
verify(moveSpy.count > 0);
moveSpy.clear();
diff --git a/tests/auto/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml b/tests/auto/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml
new file mode 100644
index 00000000..56cf85b6
--- /dev/null
+++ b/tests/auto/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.13
+import QtQuick.Controls 2.13
+
+ApplicationWindow {
+ width: 400
+ height: 400
+
+ property alias button: button
+ property alias popup1: popup1
+ property alias popup2: popup2
+
+ Button {
+ id: button
+ focus: true
+ }
+
+ Popup {
+ id: popup1
+ focus: true
+ enter: Transition { NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200 } }
+ exit: Transition { NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 200 } }
+ }
+
+ Popup {
+ id: popup2
+ focus: true
+ enter: Transition { NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 100 } }
+ exit: Transition { NumberAnimation { property: "opacity"; from: 1.0; to: 0.0; duration: 100 } }
+ }
+}
diff --git a/tests/auto/qquickpopup/tst_qquickpopup.cpp b/tests/auto/qquickpopup/tst_qquickpopup.cpp
index b5c59e02..e852a61e 100644
--- a/tests/auto/qquickpopup/tst_qquickpopup.cpp
+++ b/tests/auto/qquickpopup/tst_qquickpopup.cpp
@@ -72,6 +72,7 @@ private slots:
void activeFocusOnClose1();
void activeFocusOnClose2();
void activeFocusOnClose3();
+ void activeFocusOnClosingSeveralPopups();
void hover_data();
void hover();
void wheel_data();
@@ -666,6 +667,54 @@ void tst_QQuickPopup::activeFocusOnClose3()
QTRY_VERIFY(popup2->hasActiveFocus());
}
+void tst_QQuickPopup::activeFocusOnClosingSeveralPopups()
+{
+ // Test that active focus isn't lost when multiple popup closing simultaneously
+ QQuickApplicationHelper helper(this, QStringLiteral("activeFocusOnClosingSeveralPopups.qml"));
+ QQuickApplicationWindow *window = helper.appWindow;
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+
+ QQuickItem *button = window->property("button").value<QQuickItem *>();
+ QVERIFY(button);
+
+ QQuickPopup *popup1 = window->property("popup1").value<QQuickPopup *>();
+ QVERIFY(popup1);
+
+ QQuickPopup *popup2 = window->property("popup2").value<QQuickPopup *>();
+ QVERIFY(popup2);
+
+ QCOMPARE(button->hasActiveFocus(), true);
+ popup1->open();
+ QTRY_VERIFY(popup1->isOpened());
+ QVERIFY(popup1->hasActiveFocus());
+ popup2->open();
+ QTRY_VERIFY(popup2->isOpened());
+ QVERIFY(popup2->hasActiveFocus());
+ QTRY_COMPARE(button->hasActiveFocus(), false);
+ // close the unfocused popup first
+ popup1->close();
+ popup2->close();
+ QTRY_VERIFY(!popup1->isVisible());
+ QTRY_VERIFY(!popup2->isVisible());
+ QTRY_COMPARE(button->hasActiveFocus(), true);
+
+ popup1->open();
+ QTRY_VERIFY(popup1->isOpened());
+ QVERIFY(popup1->hasActiveFocus());
+ popup2->open();
+ QTRY_VERIFY(popup2->isOpened());
+ QVERIFY(popup2->hasActiveFocus());
+ QTRY_COMPARE(button->hasActiveFocus(), false);
+ // close the focused popup first
+ popup2->close();
+ popup1->close();
+ QTRY_VERIFY(!popup1->isVisible());
+ QTRY_VERIFY(!popup2->isVisible());
+ QTRY_COMPARE(button->hasActiveFocus(), true);
+}
+
void tst_QQuickPopup::hover_data()
{
QTest::addColumn<QString>("source");