diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-07-22 22:32:41 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-12-04 22:13:52 +0100 |
commit | 61ee61d8c977ecf876ce1d364cff634467b562a9 (patch) | |
tree | 2fde3d6b2405f5129e7456700951364fb0f699f3 /src/quick | |
parent | b7b5127747e3be2b12a70bf9c460e96d7a711496 (diff) |
Fix setting the focus reason in Qt Quick Controls
Focus might go to the content item, which is a QQuickItem that has no
concept of either focusPolicy or focusReason. For Qt Quick Controls to
update the focusReason property when an item in it's item tree receives
or loses focus, it has to install itself as a notification listener on
the item.
However, QQuickItemChangeListener didn't have any notification type for
focus changes.
Add the new change type, and notify listeners whenever the an item's
focus changes. Focus scoping might mean that an item never loses focus,
but nevertheless loses active focus.
To be able to update items recursively with the correct focusReason, add
the reason parameter to the QQuickDeliveryAgent helper function.
Fixes: QTBUG-75862
Pick-to: 6.2
Change-Id: I3d19b722bb07b55416b8cfbb4a9cdb0edd0da3ec
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/quick')
-rw-r--r-- | src/quick/items/qquickitem.cpp | 9 | ||||
-rw-r--r-- | src/quick/items/qquickitem_p.h | 1 | ||||
-rw-r--r-- | src/quick/util/qquickdeliveryagent.cpp | 23 | ||||
-rw-r--r-- | src/quick/util/qquickdeliveryagent_p_p.h | 2 |
4 files changed, 25 insertions, 10 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index a6a14d7ce3..4ed587fe38 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -7588,6 +7588,7 @@ void QQuickItem::setFocus(bool focus, Qt::FocusReason reason) if (d->focus == focus) return; + bool notifyListeners = false; if (d->window || d->parentItem) { // Need to find our nearest focus scope QQuickItem *scope = parentItem(); @@ -7619,9 +7620,10 @@ void QQuickItem::setFocus(bool focus, Qt::FocusReason reason) d->focus = focus; changed << this; + notifyListeners = true; emit focusChanged(focus); - QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1); + QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1, reason); } } else { QVarLengthArray<QQuickItem *, 20> changed; @@ -7634,10 +7636,13 @@ void QQuickItem::setFocus(bool focus, Qt::FocusReason reason) d->focus = focus; changed << this; + notifyListeners = true; emit focusChanged(focus); - QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1); + QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(changed.data(), changed.count() - 1, reason); } + if (notifyListeners) + d->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, this, reason); } /*! diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 576d392a26..6be15c4f3a 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -331,6 +331,7 @@ public: ImplicitWidth = 0x100, ImplicitHeight = 0x200, Enabled = 0x400, + Focus = 0x800, AllChanges = 0xFFFFFFFF }; diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp index f613e74d53..96a6fee35a 100644 --- a/src/quick/util/qquickdeliveryagent.cpp +++ b/src/quick/util/qquickdeliveryagent.cpp @@ -399,7 +399,9 @@ void QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem *scope, QQuickItem * if (item != rootItem && !(options & DontChangeSubFocusItem)) { QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem; if (oldSubFocusItem) { - QQuickItemPrivate::get(oldSubFocusItem)->focus = false; + QQuickItemPrivate *priv = QQuickItemPrivate::get(oldSubFocusItem); + priv->focus = false; + priv->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, oldSubFocusItem, reason); changed << oldSubFocusItem; } @@ -415,6 +417,7 @@ void QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem *scope, QQuickItem * #endif ) { itemPrivate->focus = true; + itemPrivate->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason); changed << item; } } @@ -454,7 +457,7 @@ void QQuickDeliveryAgentPrivate::setFocusInScope(QQuickItem *scope, QQuickItem * emit rootItem->window()->focusObjectChanged(activeFocusItem); if (!changed.isEmpty()) - notifyFocusChangesRecur(changed.data(), changed.count() - 1); + notifyFocusChangesRecur(changed.data(), changed.count() - 1, reason); if (isSubsceneAgent) { auto da = QQuickWindowPrivate::get(rootItem->window())->deliveryAgent; qCDebug(lcFocus) << " delegating setFocusInScope to" << da; @@ -516,14 +519,18 @@ void QQuickDeliveryAgentPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem if (item != rootItem && !(options & DontChangeSubFocusItem)) { QQuickItem *oldSubFocusItem = scopePrivate->subFocusItem; if (oldSubFocusItem && !(options & DontChangeFocusProperty)) { - QQuickItemPrivate::get(oldSubFocusItem)->focus = false; + QQuickItemPrivate *priv = QQuickItemPrivate::get(oldSubFocusItem); + priv->focus = false; + priv->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, oldSubFocusItem, reason); changed << oldSubFocusItem; } QQuickItemPrivate::get(item)->updateSubFocusItem(scope, false); } else if (!(options & DontChangeFocusProperty)) { - QQuickItemPrivate::get(item)->focus = false; + QQuickItemPrivate *priv = QQuickItemPrivate::get(item); + priv->focus = false; + priv->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason); changed << item; } @@ -550,7 +557,7 @@ void QQuickDeliveryAgentPrivate::clearFocusInScope(QQuickItem *scope, QQuickItem emit rootItem->window()->focusObjectChanged(activeFocusItem); if (!changed.isEmpty()) - notifyFocusChangesRecur(changed.data(), changed.count() - 1); + notifyFocusChangesRecur(changed.data(), changed.count() - 1, reason); if (oldActiveFocusItem == activeFocusItem) qCDebug(lcFocus) << "activeFocusItem remains" << activeFocusItem << "in" << q; @@ -566,24 +573,26 @@ void QQuickDeliveryAgentPrivate::clearFocusObject() clearFocusInScope(rootItem, QQuickItemPrivate::get(rootItem)->subFocusItem, Qt::OtherFocusReason); } -void QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(QQuickItem **items, int remaining) +void QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(QQuickItem **items, int remaining, Qt::FocusReason reason) { QPointer<QQuickItem> item(*items); if (remaining) - notifyFocusChangesRecur(items + 1, remaining - 1); + notifyFocusChangesRecur(items + 1, remaining - 1, reason); if (item) { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); if (itemPrivate->notifiedFocus != itemPrivate->focus) { itemPrivate->notifiedFocus = itemPrivate->focus; + itemPrivate->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason); emit item->focusChanged(itemPrivate->focus); } if (item && itemPrivate->notifiedActiveFocus != itemPrivate->activeFocus) { itemPrivate->notifiedActiveFocus = itemPrivate->activeFocus; itemPrivate->itemChange(QQuickItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus); + itemPrivate->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason); emit item->activeFocusChanged(itemPrivate->activeFocus); } } diff --git a/src/quick/util/qquickdeliveryagent_p_p.h b/src/quick/util/qquickdeliveryagent_p_p.h index 2a795f3e91..3ee295f133 100644 --- a/src/quick/util/qquickdeliveryagent_p_p.h +++ b/src/quick/util/qquickdeliveryagent_p_p.h @@ -95,7 +95,7 @@ public: void setFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { }); void clearFocusInScope(QQuickItem *scope, QQuickItem *item, Qt::FocusReason reason, FocusOptions = { }); - static void notifyFocusChangesRecur(QQuickItem **item, int remaining); + static void notifyFocusChangesRecur(QQuickItem **item, int remaining, Qt::FocusReason reason); void clearFocusObject(); void updateFocusItemTransform(); |