Commit 6a843907 authored by Andrew den Exter's avatar Andrew den Exter Committed by Qt by Nokia

Update item focus when the enabled property is changed.

Remove active focus from an item when it is disabled, and give active
focus to an enabled item if it has focus within a scope with active
focus.

Task-number: QTBUG-22404
Change-Id: Iff2b774a9ff784e6107a4ed6524c93e749ae0182
Reviewed-by: default avatarMichael Brasser <michael.brasser@nokia.com>
parent e7224de6
......@@ -379,11 +379,14 @@ void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
QVarLengthArray<QQuickItem *, 20> changed;
// Does this change the active focus?
if (item == rootItem || scopePrivate->activeFocus) {
if (item == rootItem || scopePrivate->activeFocus && item->isEnabled()) {
oldActiveFocusItem = activeFocusItem;
newActiveFocusItem = item;
while (newActiveFocusItem->isFocusScope() && newActiveFocusItem->scopedFocusItem())
while (newActiveFocusItem->isFocusScope()
&& newActiveFocusItem->scopedFocusItem()
&& newActiveFocusItem->scopedFocusItem()->isEnabled()) {
newActiveFocusItem = newActiveFocusItem->scopedFocusItem();
}
if (oldActiveFocusItem) {
#ifndef QT_NO_IM
......@@ -405,7 +408,7 @@ void QQuickCanvasPrivate::setFocusInScope(QQuickItem *scope, QQuickItem *item, F
}
}
if (item != rootItem) {
if (item != rootItem && !(options & DontChangeSubFocusItem)) {
QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
// Correct focus chain in scope
if (oldSubFocusItem) {
......@@ -513,7 +516,7 @@ void QQuickCanvasPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem *item,
}
}
if (item != rootItem) {
if (item != rootItem && !(options & DontChangeSubFocusItem)) {
QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem;
// Correct focus chain in scope
if (oldSubFocusItem) {
......
......@@ -135,6 +135,7 @@ public:
QList<QQuickItem*> hoverItems;
enum FocusOption {
DontChangeFocusProperty = 0x01,
DontChangeSubFocusItem = 0x02
};
Q_DECLARE_FLAGS(FocusOptions, FocusOption)
......
......@@ -1913,7 +1913,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
QQuickItemPrivate::get(d->parentItem)->addChild(this);
d->setEffectiveVisibleRecur(d->calcEffectiveVisible());
d->setEffectiveEnableRecur(d->calcEffectiveEnable());
d->setEffectiveEnableRecur(0, d->calcEffectiveEnable());
if (scopeFocusedItem && d->parentItem && d->canvas) {
// We need to test whether this item becomes scope focused
......@@ -3901,7 +3901,11 @@ void QQuickItem::setEnabled(bool e)
d->explicitEnable = e;
d->setEffectiveEnableRecur(d->calcEffectiveEnable());
QQuickItem *scope = parentItem();
while (scope && !scope->isFocusScope())
scope = scope->parentItem();
d->setEffectiveEnableRecur(scope, d->calcEffectiveEnable());
}
bool QQuickItemPrivate::calcEffectiveVisible() const
......@@ -3959,12 +3963,10 @@ bool QQuickItemPrivate::calcEffectiveEnable() const
return explicitEnable && (!parentItem || QQuickItemPrivate::get(parentItem)->effectiveEnable);
}
void QQuickItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffectiveEnable)
{
Q_Q(QQuickItem);
// XXX todo - need to fixup focus
if (newEffectiveEnable && !explicitEnable) {
// This item locally overrides enable
return;
......@@ -3981,10 +3983,21 @@ void QQuickItemPrivate::setEffectiveEnableRecur(bool newEffectiveEnable)
QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas);
if (canvasPriv->mouseGrabberItem == q)
q->ungrabMouse();
if (scope && !effectiveEnable && activeFocus) {
canvasPriv->clearFocusInScope(
scope, q, QQuickCanvasPrivate::DontChangeFocusProperty | QQuickCanvasPrivate::DontChangeSubFocusItem);
}
}
for (int ii = 0; ii < childItems.count(); ++ii)
QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(newEffectiveEnable);
for (int ii = 0; ii < childItems.count(); ++ii) {
QQuickItemPrivate::get(childItems.at(ii))->setEffectiveEnableRecur(
flags & QQuickItem::ItemIsFocusScope ? q : scope, newEffectiveEnable);
}
if (canvas && scope && effectiveEnable && focus) {
QQuickCanvasPrivate::get(canvas)->setFocusInScope(
scope, q, QQuickCanvasPrivate::DontChangeFocusProperty | QQuickCanvasPrivate::DontChangeSubFocusItem);
}
emit q->enabledChanged();
}
......
......@@ -476,7 +476,7 @@ public:
bool calcEffectiveVisible() const;
void setEffectiveVisibleRecur(bool);
bool calcEffectiveEnable() const;
void setEffectiveEnableRecur(bool);
void setEffectiveEnableRecur(QQuickItem *scope, bool);
// XXX todo
enum DirtyType {
......
......@@ -136,6 +136,7 @@ private slots:
void visible();
void enabled();
void enabledFocus();
void mouseGrab();
void touchEventAccept();
......@@ -801,6 +802,144 @@ void tst_qquickitem::enabled()
delete child2;
}
void tst_qquickitem::enabledFocus()
{
QQuickCanvas canvas;
ensureFocus(&canvas);
QQuickFocusScope root;
root.setFocus(true);
root.setEnabled(false);
QCOMPARE(root.isEnabled(), false);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), false);
root.setParentItem(canvas.rootItem());
QCOMPARE(root.isEnabled(), false);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
root.setEnabled(true);
QCOMPARE(root.isEnabled(), true);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), true);
QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
QQuickItem child1;
child1.setParentItem(&root);
QCOMPARE(child1.isEnabled(), true);
QCOMPARE(child1.hasFocus(), false);
QCOMPARE(child1.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
QQuickItem child2;
child2.setFocus(true);
child2.setParentItem(&root);
QCOMPARE(root.isEnabled(), true);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), true);
QCOMPARE(child2.isEnabled(), true);
QCOMPARE(child2.hasFocus(), true);
QCOMPARE(child2.hasActiveFocus(), true);
QCOMPARE(canvas.activeFocusItem(), &child2);
child2.setEnabled(false);
QCOMPARE(root.isEnabled(), true);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), true);
QCOMPARE(child1.isEnabled(), true);
QCOMPARE(child1.hasFocus(), false);
QCOMPARE(child1.hasActiveFocus(), false);
QCOMPARE(child2.isEnabled(), false);
QCOMPARE(child2.hasFocus(), true);
QCOMPARE(child2.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
child1.setEnabled(false);
QCOMPARE(child1.isEnabled(), false);
QCOMPARE(child1.hasFocus(), false);
QCOMPARE(child1.hasActiveFocus(), false);
child1.setFocus(true);
QCOMPARE(child1.isEnabled(), false);
QCOMPARE(child1.hasFocus(), true);
QCOMPARE(child1.hasActiveFocus(), false);
QCOMPARE(child2.isEnabled(), false);
QCOMPARE(child2.hasFocus(), false);
QCOMPARE(child2.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
child1.setEnabled(true);
QCOMPARE(child1.isEnabled(), true);
QCOMPARE(child1.hasFocus(), true);
QCOMPARE(child1.hasActiveFocus(), true);
QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&child1));
root.setFocus(false);
QCOMPARE(root.isEnabled(), true);
QCOMPARE(root.hasFocus(), false);
QCOMPARE(root.hasActiveFocus(), false);
QCOMPARE(child1.isEnabled(), true);
QCOMPARE(child1.hasFocus(), true);
QCOMPARE(child1.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
child2.forceActiveFocus();
QCOMPARE(root.isEnabled(), true);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), true);
QCOMPARE(child1.isEnabled(), true);
QCOMPARE(child1.hasFocus(), false);
QCOMPARE(child1.hasActiveFocus(), false);
QCOMPARE(child2.isEnabled(), false);
QCOMPARE(child2.hasFocus(), true);
QCOMPARE(child2.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
root.setEnabled(false);
QCOMPARE(root.isEnabled(), false);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), false);
QCOMPARE(child1.isEnabled(), false);
QCOMPARE(child1.hasFocus(), false);
QCOMPARE(child1.hasActiveFocus(), false);
QCOMPARE(child2.isEnabled(), false);
QCOMPARE(child2.hasFocus(), true);
QCOMPARE(child2.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
child1.forceActiveFocus();
QCOMPARE(root.isEnabled(), false);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), false);
QCOMPARE(child1.isEnabled(), false);
QCOMPARE(child1.hasFocus(), true);
QCOMPARE(child1.hasActiveFocus(), false);
QCOMPARE(child2.isEnabled(), false);
QCOMPARE(child2.hasFocus(), false);
QCOMPARE(child2.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
root.setEnabled(true);
QCOMPARE(root.isEnabled(), true);
QCOMPARE(root.hasFocus(), true);
QCOMPARE(root.hasActiveFocus(), true);
QCOMPARE(child1.isEnabled(), true);
QCOMPARE(child1.hasFocus(), true);
QCOMPARE(child1.hasActiveFocus(), true);
QCOMPARE(child2.isEnabled(), false);
QCOMPARE(child2.hasFocus(), false);
QCOMPARE(child2.hasActiveFocus(), false);
QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&child1));
}
void tst_qquickitem::mouseGrab()
{
QQuickCanvas *canvas = new QQuickCanvas;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment