aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@theqtcompany.com>2015-10-12 10:24:38 +0200
committerLiang Qi <liang.qi@theqtcompany.com>2015-10-14 05:35:05 +0000
commit0789923f391f1e5bebe07b676a41c85a820b2533 (patch)
treebd514620afeea27760752dad3c818d49dc232316
parent1551187f9c17bfa15686626d896ccbdd04d1f37a (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.cpp4
-rw-r--r--tests/auto/quick/qquickitem2/data/keynavigationtest_loop.qml37
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp26
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);