Mozart输入子系统


英文原文快照


本文档描述了输入系统在Mozart内部工作的细节。

设备

Zircon通过/dev/class/input下的文件系统提供对设备的访问功能。该目录下都是HID设备,并且有相关的ioctl操作来获取这些设备的描述报告信息,通过向文件系统的简单读取可以返回事件报告。

HID向InputEvent报告。

当通过sysmgr进程启动应用程序时,src/root_presenter作为单例启动,以创建Presentation的根。在启动的过程中,root_presenter启动src/input_reader,它将监视新设备的/dev/class/input目录并发现已存在的现有设备。

无论何时检测到设备(或第一次被发现),InputReader都会读取HID描述报告并将其转换为DeviceDescriptor。

该设备而后通过InputDeviceRegistry注册表来进行注册,该注册表由root presenter的App类实现,而后App通知新设备的任何现有Presentation。它还以InputDevice的形式为该设备创建一个通道,InputReader可以保持对它的引用来转发事件。Presentation创建一个DeviceState(可在lib/input目录下找到),并稍后在进程中被使用。

在设备初始化期间,InputReader会将该设备对应的句柄添加到句柄列表中,以监视其消息循环中的活动。每当检测到活动时,它会读取数据包,并且与此设备关联的InputInterpreter会将报告转换为InputReport

InputReport通过在注册过程中创建的InputDevice通道转发到root presenterApp,后者将InputReport发送到不同的Presentations中。

进一步地,Presentation持有的DeviceStateInputReport转换为InputEvent

InputEvent的生命周期

一旦InputEvent通过DeviceState生成,它就会被转发到src/input_manager下。有ViewAssociate对象专门用于处理实现InputDispatcher服务的输入事件。

每个视图树具有一个InputDispatcherImpl。该视图树由Presentation拥有,因此InputEvent被转发到它们中的每一个。

InputDispatcherImpl查询ViewInspector服务以检索输入焦点链,然后它将通过焦点链发送这些事件。从该链中最深的视图开始并传播事件,直到View表示它已通过InputConnection::InputListener::OnEvent方法处理完事件。

输入焦点

InputEvent是触摸或鼠标按下事件时,使用ViewInspectorInputDispatcherImpl在场景图上运行HitTest,其结果包含一个被命中的节点树。

InputDispatcherImpl使用ViewInspector将节点列表转换为Views,此时它并行请求,不同的视图是否被击中,以及考虑哪个子节点被击中,该过程通过InputConnection::ViewHitTester接口实现完成的。

一旦所有视图都得到响应,InputDispatcherImpl会协调自顶向下遍历节点树上的结果,并使用子视图应该参与的答案来构建感兴趣方面的树。然后,对于每个叶子节点,它将创建焦点链,该焦点链是从该叶子到根的一个分支。

当前的实现中,InputDispatcherImpl选择其中一个链(,但将来可能会改变),而后它告诉ViewInspector哪个链现在是处于聚焦状态。