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
持有的DeviceState
将InputReport
转换为InputEvent
。
InputEvent
的生命周期
一旦InputEvent
通过DeviceState
生成,它就会被转发到src/input_manager
下。有ViewAssociate
对象专门用于处理实现InputDispatcher
服务的输入事件。
每个视图树具有一个InputDispatcherImpl
。该视图树由Presentation
拥有,因此InputEvent
被转发到它们中的每一个。
InputDispatcherImpl
查询ViewInspector
服务以检索输入焦点链,然后它将通过焦点链发送这些事件。从该链中最深的视图开始并传播事件,直到View
表示它已通过InputConnection::InputListener::OnEvent
方法处理完事件。
输入焦点
当InputEvent
是触摸或鼠标按下事件时,使用ViewInspector
的InputDispatcherImpl
在场景图上运行HitTest
,其结果包含一个被命中的节点树。
InputDispatcherImpl
使用ViewInspector
将节点列表转换为Views
,此时它并行请求,不同的视图是否被击中,以及考虑哪个子节点被击中,该过程通过InputConnection::ViewHitTester
接口实现完成的。
一旦所有视图都得到响应,InputDispatcherImpl
会协调自顶向下遍历节点树上的结果,并使用子视图应该参与的答案来构建感兴趣方面的树。然后,对于每个叶子节点,它将创建焦点链,该焦点链是从该叶子到根的一个分支。
当前的实现中,InputDispatcherImpl
选择其中一个链(,但将来可能会改变),而后它告诉ViewInspector
哪个链现在是处于聚焦状态。