From: Andrew den Exter Date: Fri, 30 Mar 2012 07:36:40 +0000 (+1000) Subject: Fix crash when changing the grandparent of an item with focus. X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=9cddbbff9da88ba9c889ae1f306e837c3a66377e;p=konrad%2Fqtdeclarative.git Fix crash when changing the grandparent of an item with focus. When an item was reparented it's sub focus item was cleared and those of it's children were cleared along with those in the tree the item was removed from. Since we now rely on the focus state of an unparented tree to be correct we need to restore the sub focus items of the unparented tree. Change-Id: I236c512751b99092c7e9a39194f4680304bfacc5 Reviewed-by: Martin Jones --- diff --git a/src/quick/items/qquickcanvas.cpp b/src/quick/items/qquickcanvas.cpp index 5d4293a..29733e9 100644 --- a/src/quick/items/qquickcanvas.cpp +++ b/src/quick/items/qquickcanvas.cpp @@ -155,6 +155,10 @@ have a scope focused item), and the other items will have their focus cleared. // #define TOUCH_DEBUG // #define DIRTY_DEBUG +#ifdef FOCUS_DEBUG +void printFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1); +#endif + QQuickItem::UpdatePaintNodeData::UpdatePaintNodeData() : transformNode(0) { diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 117667d..782ae10 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -76,6 +76,7 @@ QT_BEGIN_NAMESPACE #ifdef FOCUS_DEBUG +void printFocusTree(QQuickItem *item, QQuickItem *scope = 0, int depth = 1); void printFocusTree(QQuickItem *item, QQuickItem *scope, int depth) { qWarning() @@ -1958,6 +1959,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem) if (d->canvas) { QQuickCanvasPrivate::get(d->canvas)->clearFocusInScope(scopeItem, scopeFocusedItem, QQuickCanvasPrivate::DontChangeFocusProperty); + if (scopeFocusedItem != this) + QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(this, true); } else { QQuickItemPrivate::get(scopeFocusedItem)->updateSubFocusItem(scopeItem, false); } @@ -4160,7 +4163,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec for (int ii = 0; ii < childItems.count(); ++ii) { QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur( - flags & QQuickItem::ItemIsFocusScope ? q : scope, newEffectiveEnable); + (flags & QQuickItem::ItemIsFocusScope) && scope ? q : scope, newEffectiveEnable); } if (canvas && scope && effectiveEnable && focus) { @@ -4808,6 +4811,7 @@ void QQuickItem::setFocus(bool focus) QVarLengthArray changed; QQuickItem *oldSubFocusItem = QQuickItemPrivate::get(scope)->subFocusItem; if (oldSubFocusItem) { + QQuickItemPrivate::get(oldSubFocusItem)->updateSubFocusItem(scope, false); QQuickItemPrivate::get(oldSubFocusItem)->focus = false; changed << oldSubFocusItem; } diff --git a/tests/auto/quick/qquickitem/tst_qquickitem.cpp b/tests/auto/quick/qquickitem/tst_qquickitem.cpp index afb5c01..a137769 100644 --- a/tests/auto/quick/qquickitem/tst_qquickitem.cpp +++ b/tests/auto/quick/qquickitem/tst_qquickitem.cpp @@ -141,6 +141,7 @@ private slots: void multipleFocusClears(); void focusSubItemInNonFocusScope(); void parentItemWithFocus(); + void reparentFocusedItem(); void constructor(); void setParentItem(); @@ -822,6 +823,34 @@ void tst_qquickitem::parentItemWithFocus() } } +void tst_qquickitem::reparentFocusedItem() +{ + QQuickCanvas canvas; + ensureFocus(&canvas); + QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas); + + QQuickItem parent(canvas.rootItem()); + QQuickItem child(&parent); + QQuickItem sibling(&parent); + QQuickItem grandchild(&child); + + FocusState focusState; + focusState << &parent << &child << &sibling << &grandchild; + FVERIFY(); + + grandchild.setFocus(true); + focusState[&parent].set(false, false); + focusState[&child].set(false, false); + focusState[&sibling].set(false, false); + focusState[&grandchild].set(true, true); + focusState.active(&grandchild); + FVERIFY(); + + // Parenting the item to another item within the same focus scope shouldn't change it's focus. + child.setParentItem(&sibling); + FVERIFY(); +} + void tst_qquickitem::constructor() { QQuickItem *root = new QQuickItem;