Mozart Input system

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.

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.