This document describes how the input system works inside Mozart.
Zircon provides access to devices through the file system under /dev/class/input
. Those are HID devices and there are associated ioctls to retrieve the description report and simple reads on those devices will return the event reports.
InputEvent
.When launching an application through the sysmgr process, src/root_presenter
is launched as a singleton to create the root of the Presentation
. When starting, root_presenter starts src/input_reader
which will monitor the /dev/class/input
directory for new devices and discover existing devices if they are already present.
Any time a device is detected (or discovered the first time) InputReader
reads the HID description report and converts it into a DeviceDescriptor.
That device is then registered through the InputDeviceRegistry
which is implemented by the root presenter App
class. App
then notifies any existing Presentation
of the new device. It also creates a channel for that device in the form of an InputDevice
which InputReader
can keep a reference to, to forward events. Presentation
creates a DeviceState
(found under lib/input
) which will be used later in the process.
During the initialization of the device, InputReader
will add the handle corresponding to that device to the list of handles to monitor for activity in its message loop. Whenever activity is detected, it reads the packet and the InputInterpreter
associated to this device, will convert the report into an InputReport
.
The InputReport
is forwarded through the InputDevice
channel created during the registration process to the root presenter App
which dispatches it to the different Presentations
.
The DeviceState
held by a Presentation
will convert the InputReport
into an InputEvent
.
InputEvent
.Once an InputEvent
has been generated by a DeviceState
, it's forwarded to src/input_manager
, a ViewAssociate
dedicated to process input events which implements the InputDispatcher
service.
There is one InputDispatcherImpl
per view tree. The view tree is owned by Presentation
. So the InputEvent
is forwarded to each one of them.
An InputDispatcherImpl
will query the ViewInspector
service to retrieve the input focus chain. It will then dispatch those events through the chain. It starts at the deepest view in that chain and propagates the event until the View
says it has handled the event though the InputConnection::InputListener::OnEvent
method.
When the InputEvent
is a touch or mouse down event, InputDispatcherImpl
, using the ViewInspector
, runs the HitTest
on the scene graph. The result contains a tree of nodes that were hit.
InputDispatcherImpl
uses ViewInspector
to convert this list of nodes into Views
, at which point it requests in parallel the different views whether they are hit or not and which of their children should be considered for the hit. This is done through the InputConnection::ViewHitTester
interface.
Once all views have responded, InputDispatcherImpl
reconciles the results walking down the tree from the top and using the answer to which subviews should participate to build a tree of interested parties. For each leaf it will then create focus chain, which is the branch that leads from that leaf to the root.
For now InputDispatcherImpl
picks one of the chain but this will be changed in the future. It then tells the ViewInspector
which chain is now in focus.