diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-12 10:24:38 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-10-14 05:35:05 +0000 |
commit | 0789923f391f1e5bebe07b676a41c85a820b2533 (patch) | |
tree | bd514620afeea27760752dad3c818d49dc232316 | |
parent | 1551187f9c17bfa15686626d896ccbdd04d1f37a (diff) |
QQuickItem: detect loop in KeyNavigation chain
Task-number: QTBUG-47229
Change-Id: I22dbe5ee1fff4e9a8de4fa69b43e4d9a87677192
Reviewed-by: J-P Nurmi <jpnurmi@theqtcompany.com>
-rw-r--r-- | src/quick/items/qquickitem.cpp | 4 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/data/keynavigationtest_loop.qml | 37 | ||||
-rw-r--r-- | tests/auto/quick/qquickitem2/tst_qquickitem.cpp | 26 |
3 files changed, 66 insertions, 1 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index ab93974f60..fbea3a0ee1 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -724,6 +724,7 @@ void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, co { QQuickItem *initialItem = currentItem; bool isNextItem = false; + QVector<QQuickItem *> visitedItems; do { isNextItem = false; if (currentItem->isVisible() && currentItem->isEnabled()) { @@ -734,13 +735,14 @@ void QQuickKeyNavigationAttached::setFocusNavigation(QQuickItem *currentItem, co if (attached) { QQuickItem *tempItem = qvariant_cast<QQuickItem*>(attached->property(dir)); if (tempItem) { + visitedItems.append(currentItem); currentItem = tempItem; isNextItem = true; } } } } - while (currentItem != initialItem && isNextItem); + while (currentItem != initialItem && isNextItem && !visitedItems.contains(currentItem)); } struct SigMap { diff --git a/tests/auto/quick/qquickitem2/data/keynavigationtest_loop.qml b/tests/auto/quick/qquickitem2/data/keynavigationtest_loop.qml new file mode 100644 index 0000000000..dfac1549f9 --- /dev/null +++ b/tests/auto/quick/qquickitem2/data/keynavigationtest_loop.qml @@ -0,0 +1,37 @@ +import QtQuick 2.0 + +Column { + width: 50; height: 200 + Rectangle { + id: item1 + objectName: "item1" + focus: true + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.down: item2 + } + Rectangle { + id: item2 + objectName: "item2" + enabled: false + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.down: item3 + } + Rectangle { + id: item3 + objectName: "item3" + enabled: false + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.down: item4 + } + Rectangle { + id: item4 + objectName: "item4" + enabled: false + width: 50; height: 50 + color: focus ? "red" : "lightgray" + KeyNavigation.down: item3 + } +} diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp index 69c7250134..f3333df60d 100644 --- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp @@ -85,6 +85,7 @@ private slots: void keyNavigation_skipNotVisible(); void keyNavigation_implicitSetting(); void keyNavigation_focusReason(); + void keyNavigation_loop(); void layoutMirroring(); void layoutMirroringIllegalParent(); void smooth(); @@ -2026,6 +2027,31 @@ void tst_QQuickItem::keyNavigation_focusReason() delete window; } +void tst_QQuickItem::keyNavigation_loop() +{ + // QTBUG-47229 + QQuickView *window = new QQuickView(0); + window->setBaseSize(QSize(240,320)); + + window->setSource(testFileUrl("keynavigationtest_loop.qml")); + window->show(); + window->requestActivate(); + + QVERIFY(QTest::qWaitForWindowActive(window)); + QCOMPARE(QGuiApplication::focusWindow(), window); + + QQuickItem *item = findItem<QQuickItem>(window->rootObject(), "item1"); + QVERIFY(item); + QVERIFY(item->hasActiveFocus()); + + QKeyEvent key = QKeyEvent(QEvent::KeyPress, Qt::Key_Down, Qt::NoModifier, "", false, 1); + QGuiApplication::sendEvent(window, &key); + QVERIFY(key.isAccepted()); + QVERIFY(item->hasActiveFocus()); + + delete window; +} + void tst_QQuickItem::smooth() { QQmlComponent component(&engine); |