qt: introduce `FocusReasonForwarder`
This is useful for getting rid of setCurrentItemFocus()
for good. If delegate or a leaf item does not get the focus reason, we can manually forward using this. Currently, Qt does not expose the last focus reason in QQuickItem
, unlike QQuickControl
.
Request review @chub.
Merge request reports
Activity
added MRStatus::Reviewable label
changed milestone to %4.0
added Component::Interface: Qt label
requested review from @chub
added MRStatus::WaitingForReviewerFeedback label and removed MRStatus::Reviewable label
- modules/gui/qt/util/focusreasonforwarder.hpp 0 → 100644
20 21 #include <QObject> 22 #include <QQmlEngine> 23 #include <QPointer> 24 25 // This class is an ad hoc solution for getting the last focus reason of a QQuickItem, 26 // without using private headers. When Qt makes the focus reason public in QQuickItem, 27 // similar to QQuickControl, this class will serve no more purpose. 28 // This class can be useful in focus scopes (such as views ListView, GridView, ...), 29 // if a delegate or a leaf item gets the active focus but not the focus reason of the 30 // focus scope. 31 32 // An example usage would be as follows: 33 // FocusScope { 34 // readonly property int focusReason: FocusReasonForwarder.focusReason 35 // } Could you apply this in a place or two in our codebase (I don't ask you convert the whole project) so we can see places where this could replace
setCurrentItemFocus
?My understanding is that this could help reduce cases where we have some
Navigation.leftAction: myItem.setCurrentItemFocus(reason)
, I guess we still need some manual code for page switchingDo you know if Qt 6.2 already fixed this problem? If I remember correctly, the problem in Qt 5 was that:
ListView { // This is a focus scope delegate: Control { focus: (index === 0) } }
When we
forceActiveFocus(TabReason)
the focus scope (which isNavigation.item
orKeyNavigation.item
behavior),Control
delegate instance that requests focus (focus: true
) did not have itsfocusReason
adjusted even though it gets the active focus.hum, you can't put raw controls directly in a list, you're supposed to use ItemDelegate or this causes focus & navigation issues (but that may be a misuse in your sample).
When I tested the HomePage MR, I tried to remove the
KeyNavigation.action
and it was working fine for lists, getting initial focus was not working properly with GridView but I assume that's an implementation issue that could be fixed on our side (grid item was getting focus but didn't get the focusReason).to be taken with a grain of salt, I only briefly checked this
hum, you can't put raw controls directly in a list, you're supposed to use ItemDelegate or this causes focus & navigation issues (but that may be a misuse in your sample).
I don't know what makes
ItemDelegate
different fromControl
in this regard. IfItemDelegate
fixes this issue, then we can use it instead in delegate and not proceed with this merge request, but then I would ask whysetCurrentItemFocus()
was brought then.that's an implementation issue that could be fixed on our side (grid item was getting focus but didn't get the focusReason)
My idea was to use this like this to get the focus reason of the view:
GridDelegate { // This derives from Control Binding on focusReason { value: view.FocusReasonForwarder.focusReason } }
This means we get rid of
setCurrentItemFocus()
, but rather simply focus the view. This is a focus scope, the delegate instance that had the focus last time would retain its focus even when it loses its active focus. When the view gets the active focus, the same item would also get the active focus. So we should not need to setfocus
to true or callforceActiveFocus()
in the delegate instance.My idea was to use this like this to get the focus reason of the view
One problem with this approach is that, the delegate may have different focus reason from the view (navigating within the view?). So maybe an all-time binding is not a good idea. Or maybe focus reason must be the same in all active focus items (ancestors)?
added MRStatus::InReview label and removed MRStatus::WaitingForReviewerFeedback label