|
|
|
# Keyboard navigation
|
|
|
|
|
|
|
|
## general principle
|
|
|
|
|
|
|
|
VLC aims to be navigable using a keyboard. to achieve this we implemented a
|
|
|
|
navigation mechanism that goes beyond Qt's tab/backtab handling. I allows to
|
|
|
|
define which element should be focused when navigating using left/right/up/down
|
|
|
|
direction or on a cancel/back action.
|
|
|
|
|
|
|
|
Navigation is defined hierarchically, each level (qml file) will define
|
|
|
|
how navigation should behave internally, this is the responsibility of the
|
|
|
|
object instantiating an item to define how it should behave with its siblings.
|
|
|
|
|
|
|
|
Each navigable object should define what is its navigation parent, when an
|
|
|
|
object receive a navigation request, it will either handle the request directly
|
|
|
|
if it has an item or action defined, otherwise, the request will be forwarded to
|
|
|
|
the parent recursively, if it reaches the to level with no-one to handle the
|
|
|
|
request, the requests is ignored.
|
|
|
|
|
|
|
|
two types of behavior can be defined for an event, either a target item
|
|
|
|
(`rightItem`) or a javascript function (`rightAction`)
|
|
|
|
|
|
|
|
## sample application
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
on the following scenario, if the user has the focus on the ItemB,
|
|
|
|
pressing left will set the focus on the ItemA, pressing right will set the focus
|
|
|
|
on the playlist, pressing up will set the focus on the navigation bar, and
|
|
|
|
pressing down will have no effect.
|
|
|
|
|
|
|
|
If the user has the focus on the navigation bar, and press down, the focus will
|
|
|
|
be set on mainView, this is not the responsibility of Navigation to define where
|
|
|
|
the focus should be set internally when entering a component. In practice, qml
|
|
|
|
use the principle of focus chain, so restoring the focus on the parent element
|
|
|
|
will restore the active focus on the child item.
|
|
|
|
|
|
|
|
It is important to be familiar with the concept of active focus [^1] and how the
|
|
|
|
input focus [^2] works in Qml.
|
|
|
|
|
|
|
|
[^1] https://doc.qt.io/qt-5/qml-qtquick-item.html#activeFocus-prop
|
|
|
|
[^2] https://doc.qt.io/qt-5/qtquick-input-focus.html
|
|
|
|
|
|
|
|
|
|
|
|
## sample code usage
|
|
|
|
|
|
|
|
```qml
|
|
|
|
MyRootObject {
|
|
|
|
id: root
|
|
|
|
|
|
|
|
MyItem {
|
|
|
|
id: myItemOnLeft
|
|
|
|
|
|
|
|
// if the item receive keyboard input directly, you may have to
|
|
|
|
// forward keyboard events to the Navigation system
|
|
|
|
Keys.priority: Keys.AfterItem
|
|
|
|
Keys.onPressed: Navigation.defaultKeyAction(event)
|
|
|
|
|
|
|
|
// who is the Navigation parent of the object
|
|
|
|
Navigation.parentItem: root
|
|
|
|
|
|
|
|
// navigation within our view, don't access objects outside our parentItem
|
|
|
|
Navigation.rightItem: myItemOnRight
|
|
|
|
Navigation.leftAction: function() {
|
|
|
|
// this block is evaluated when navigation left from this object
|
|
|
|
if (whatever) {
|
|
|
|
someElement.forceActiveFocus(Qt.BacktabFocusReason)
|
|
|
|
} else {
|
|
|
|
// call manually the parent default handler
|
|
|
|
root.Navigation.defaultNavigationLeft()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
OtherItem {
|
|
|
|
id: myItemOnRight
|
|
|
|
|
|
|
|
Navigation.parentItem: root
|
|
|
|
// reciprocal navigation is not automatic and should
|
|
|
|
// be explicited
|
|
|
|
Navigation.leftItem: myItemOnLeft
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## see
|
|
|
|
|
|
|
|
* widgets/native/navigation_attached.cpp |