From d6e19d1ecd9f8a26bbd2c3f38083da98c97d599e Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Mon, 15 Aug 2011 13:44:44 +1000 Subject: FocusScope's focusItem must always be a descendent Task-number: QTBUG-20699 Reviewed-by: Michael Brasser --- src/gui/graphicsview/qgraphicsitem.cpp | 34 ++++++++++++++------------ tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 32 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 2ac2bdf..0c218fc 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -1171,24 +1171,26 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q // Update focus scope item ptr in new scope. QGraphicsItem *newFocusScopeItem = subFocusItem ? subFocusItem : parentFocusScopeItem; if (newFocusScopeItem && newParent) { - if (subFocusItem) { - // Find the subFocusItem's topmost focus scope. - QGraphicsItem *ancestorScope = 0; - QGraphicsItem *p = subFocusItem->d_ptr->parent; - while (p) { - if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) - ancestorScope = p; - if (p->d_ptr->flags & QGraphicsItem::ItemIsPanel) - break; - p = p->d_ptr->parent; - } - if (ancestorScope) - newFocusScopeItem = ancestorScope; - } - QGraphicsItem *p = newParent; while (p) { if (p->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) { + if (subFocusItem && subFocusItem != q_ptr) { + // Find the subFocusItem's topmost focus scope within the new parent's focusscope + QGraphicsItem *ancestorScope = 0; + QGraphicsItem *p2 = subFocusItem->d_ptr->parent; + while (p2 && p2 != p) { + if (p2->d_ptr->flags & QGraphicsItem::ItemIsFocusScope) + ancestorScope = p2; + if (p2->d_ptr->flags & QGraphicsItem::ItemIsPanel) + break; + if (p2 == q_ptr) + break; + p2 = p2->d_ptr->parent; + } + if (ancestorScope) + newFocusScopeItem = ancestorScope; + } + p->d_ptr->focusScopeItem = newFocusScopeItem; newFocusScopeItem->d_ptr->focusScopeItemChange(true); // Ensure the new item is no longer the subFocusItem. The @@ -3297,7 +3299,7 @@ void QGraphicsItemPrivate::setFocusHelper(Qt::FocusReason focusReason, bool clim } if (climb) { - while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible() && f->d_ptr->focusScopeItem != f) + while (f->d_ptr->focusScopeItem && f->d_ptr->focusScopeItem->isVisible()) f = f->d_ptr->focusScopeItem; } diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index 3665b10..9b834d5 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -475,6 +475,7 @@ private slots: void QTBUG_12112_focusItem(); void QTBUG_13473_sceneposchange(); void QTBUG_16374_crashInDestructor(); + void QTBUG_20699_focusScopeCrash(); private: QList paintedItems; @@ -11265,5 +11266,36 @@ void tst_QGraphicsItem::QTBUG_16374_crashInDestructor() QTest::qWaitForWindowShown(&view); } +void tst_QGraphicsItem::QTBUG_20699_focusScopeCrash() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + QGraphicsPixmapItem fs; + fs.setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable); + scene.addItem(&fs); + QGraphicsPixmapItem* fs2 = new QGraphicsPixmapItem(&fs); + fs2->setFlags(QGraphicsItem::ItemIsFocusScope | QGraphicsItem::ItemIsFocusable); + QGraphicsPixmapItem* fi2 = new QGraphicsPixmapItem(&fs); + fi2->setFlags(QGraphicsItem::ItemIsFocusable); + QGraphicsPixmapItem* fi = new QGraphicsPixmapItem(fs2); + fi->setFlags(QGraphicsItem::ItemIsFocusable); + fs.setFocus(); + fi->setFocus(); + + view.show(); + QTest::qWaitForWindowShown(&view); + + fi->setParentItem(fi2); + fi->setFocus(); + fs.setFocus(); + fi->setParentItem(fs2); + fi->setFocus(); + fs2->setFocus(); + fs.setFocus(); + fi->setParentItem(fi2); + fi->setFocus(); + fs.setFocus(); +} + QTEST_MAIN(tst_QGraphicsItem) #include "tst_qgraphicsitem.moc" -- cgit v0.12 From a1b2be3c8a64aee832c648c6dcdff003f22318a3 Mon Sep 17 00:00:00 2001 From: Alan Alpert Date: Tue, 30 Aug 2011 18:03:32 +1000 Subject: QDeclarative::hasActiveFocus should return false for hidden items In graphics view you can be the focus item without being visible, but you still won't receive events. QML should hide these distinctions. Task-number: QTBUG-21045 --- src/declarative/graphicsitems/qdeclarativeitem.cpp | 4 ++-- .../declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp index d36d163..b9d231e 100644 --- a/src/declarative/graphicsitems/qdeclarativeitem.cpp +++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp @@ -3600,8 +3600,8 @@ void QDeclarativeItem::setSize(const QSizeF &size) bool QDeclarativeItem::hasActiveFocus() const { Q_D(const QDeclarativeItem); - return focusItem() == this || - (d->flags & QGraphicsItem::ItemIsFocusScope && focusItem() != 0); + return (focusItem() && focusItem()->isVisible()) && (focusItem() == this || + (d->flags & QGraphicsItem::ItemIsFocusScope && focusItem() != 0)); } /*! diff --git a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp index 362a8ff..2fdeb71 100644 --- a/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp +++ b/tests/auto/declarative/qdeclarativeitem/tst_qdeclarativeitem.cpp @@ -90,6 +90,7 @@ private slots: void testQtQuick11Attributes(); void testQtQuick11Attributes_data(); void qtbug_16871(); + void qtbug_21045(); private: QDeclarativeEngine engine; }; @@ -1238,6 +1239,18 @@ void tst_QDeclarativeItem::qtbug_16871() delete o; } +void tst_QDeclarativeItem::qtbug_21045() +{ + QDeclarativeComponent component(&engine); + QGraphicsScene scene; + component.setData("import QtQuick 1.1\nItem{visible: false; focus: true}", QUrl::fromLocalFile("file:")); + QObject *o = component.create(); + QDeclarativeItem* i = qobject_cast(o); + QVERIFY(i); + scene.addItem(i); + QVERIFY(!i->hasActiveFocus()); +} + QTEST_MAIN(tst_QDeclarativeItem) #include "tst_qdeclarativeitem.moc" -- cgit v0.12