Fix handling of a direct child stealing focus from a parent-less item.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Thu, 7 Jun 2012 02:29:07 +0000 (12:29 +1000)
committerQt by Nokia <qt-info@nokia.com>
Fri, 8 Jun 2012 04:17:54 +0000 (06:17 +0200)
When an item gains focus it will remove focus from the previous item
that held focus.  Normally this is the sub-focus item of an ancestor
item, however if the item with focus is at the root of the tree there
will be no sub-focus item and the focus of root item needs to be cleared
instead.  Likewise if an item doesn't have a parent, focus still needs
to be removed from any sub focus item.

Change-Id: I0f192692e21e288c87ba0104f3d597363190f87c
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/quick/items/qquickitem.cpp
tests/auto/quick/qquickitem/tst_qquickitem.cpp

index ae912a2..5eb824c 100644 (file)
@@ -4953,6 +4953,9 @@ void QQuickItem::setFocus(bool focus)
                 QQuickItemPrivate::get(oldSubFocusItem)->updateSubFocusItem(scope, false);
                 QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
                 changed << oldSubFocusItem;
+            } else if (!scope->isFocusScope() && scope->hasFocus()) {
+                QQuickItemPrivate::get(scope)->focus = false;
+                changed << scope;
             }
             d->updateSubFocusItem(scope, focus);
 
@@ -4963,8 +4966,19 @@ void QQuickItem::setFocus(bool focus)
             QQuickCanvasPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1);
         }
     } else {
+        QVarLengthArray<QQuickItem *, 20> changed;
+        QQuickItem *oldSubFocusItem = d->subFocusItem;
+        if (!isFocusScope() && oldSubFocusItem) {
+            QQuickItemPrivate::get(oldSubFocusItem)->updateSubFocusItem(this, false);
+            QQuickItemPrivate::get(oldSubFocusItem)->focus = false;
+            changed << oldSubFocusItem;
+        }
+
         d->focus = focus;
+        changed << this;
         emit focusChanged(focus);
+
+        QQuickCanvasPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1);
     }
 }
 
index 8f4a03b..47f9ff4 100644 (file)
@@ -203,7 +203,7 @@ void tst_qquickitem::noCanvas()
     root->setFocus(true);
     scope->setFocus(true);
     scopedChild2->setFocus(true);
-    QCOMPARE(root->hasFocus(), true);
+    QCOMPARE(root->hasFocus(), false);
     QCOMPARE(child->hasFocus(), false);
     QCOMPARE(scope->hasFocus(), false);
     QCOMPARE(scopedChild->hasFocus(), false);
@@ -822,6 +822,32 @@ void tst_qquickitem::parentItemWithFocus()
     focusState.active(&grandchild);
     FVERIFY();
     }
+
+    {
+    QQuickItem parent;
+    QQuickItem child1;
+    QQuickItem child2;
+
+    FocusState focusState;
+    focusState << &parent << &child1 << &child2;
+    parent.setFocus(true);
+    child1.setParentItem(&parent);
+    child2.setParentItem(&parent);
+    focusState[&parent].set(true, false);
+    focusState[&child1].set(false, false);
+    focusState[&child2].set(false, false);
+    FVERIFY();
+
+    child1.setFocus(true);
+    focusState[&parent].set(false, false);
+    focusState[&child1].set(true, false);
+    FVERIFY();
+
+    parent.setFocus(true);
+    focusState[&parent].set(true, false);
+    focusState[&child1].set(false, false);
+    FVERIFY();
+    }
 }
 
 void tst_qquickitem::reparentFocusedItem()