blob: eb4a961202fe16b09ccc2f44c3fcf5145c500eb8 [file] [log] [blame] [view]
# Mozart Input system
This document describes how the input system works inside Mozart.
## Devices
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.
## HID Reports to `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`.
## The life of an `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.
## Input Focus.
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.