RFC-0096 - 用户输入架构

RFC-0096:用户输入架构
状态已接受
领域
  • HCI
说明

在具有图形界面和多个运行时的系统上,在 Fuchsia 上提供用户输入事件(键盘、鼠标、触摸等)的概要架构。

问题
Gerrit 更改
作者
审核人
提交日期(年-月-日)2021-04-15
审核日期(年-月-日)2021-05-26

摘要

此 RFC 介绍了用于提供用户输入的目标概要架构 事件(键盘、鼠标、触摸等)事件(在具有图形界面的系统上) 和多个运行时。用户通过 各种方法/设备,包括键盘、鼠标、触摸和按钮。这个 RFC 涵盖 Fuchsia 上的输入事件从驱动程序级原始数据到输入 事件。通过 所述组件自发布之时起仍处于开发阶段。

设计初衷

为了支持 Fuchsia 的包容理念,Fucsia 输入内容必须 为基于不同运行时构建的组件提供平台级支持 (例如 Flutter、Chromium)并允许 以便自定义输入行为。在其他平台上,这些行为 通常内置于特定界面框架的实现中。紫红色 给独立的平台输入处理带来了许多独特的挑战 特定界面框架的细节。

在 Fuchsia 代码中,目前有多条输入路由路径 (root 演示器输入流水线), 关于首选路径和迁移计划的公开指南。此 RFC 概览 Fuchsia 上用户输入路由的目标架构,并提供了指导 如何为未来的用例扩展输入处理功能。

要求

  • 安全性:借助 Fuchsia 输入堆栈,您可以轻松构建安全产品。
    • 输入事件可能包含密码和付款数据等敏感数据, 以及关于用户何时处于活动状态的信息所有用户输入事件 应被视为个人身份信息, 最终用户软件。
    • 如果路由不正确,例如由 恶意界面导致用户点击了他们无意的按钮 点击(“点击劫持”)。
    • 如有可能,Fucsia 平台应鼓励开发者构建 提供易于理解的 API Surface,保障产品安全 以及审核通过系统的用户输入事件流。
  • 正确性:根据用户传送的输入事件 预期。
    • Fuchsia 输入系统负责解读 并将其提供给目前正确的目标组件 运行状态不过,“正确”的定义可能会有所不同 具体取决于活动和商品类型。
    • 即使界面正在以动画形式呈现,输入事件传递也应保持一致 或改变尺寸
    • 事件有时可能会同时分派给多个组件 (例如键盘快捷键)。
  • 性能:用户输入速度足够快。
    • 虽然确切的延迟时间要求因输入设备和产品类型而异, 输入传送对延迟时间特别敏感,应力争 足够快,用户不会察觉到延迟。
    • 输入架构应避免引入不必要的延迟。在 尤其要注意进程上下文切换, 会造成不必要的阻塞调用
  • 可自定义性:系统应支持 在 Fuchsia 平台上构建的不同产品。 * 具体而言,产品 会话 应该有 自定义输入行为的功能。不过,最初的实现 仅能满足部分最终要求 进行自定义(请参阅输入流水线 自定义。)
    • 部分产品需要键盘和鼠标支持,而其他产品则侧重于产品 主要体现在通过触摸和按钮进行互动
    • Fuchsia 平台应提供特定于产品的钩子 自定义输入行为(例如,对 按钮事件)。
    • Fuchsia 应允许产品将输入事件映射到不同类型的事件, 例如,将触摸事件重新解释为鼠标事件 与不支持触摸手势的软件兼容。
  • 可扩展性:Fuchsia 可以添加对新输入模式的支持。
    • 虽然输入需求截然不同的产品可能需要更改 平台,那么应该能够添加对新输入法的支持 而无需大量重写现有输入堆栈。

激励他人的示例

这些用例并不详尽,但能提供一些关于 该架构应该支持的行为类型。

  • 当界面来自多个框架时,可以正确解读触摸屏手势 屏幕上。
  • 当存在多个 文本框(由不同框架支持)显示在屏幕上。
  • 允许使用组合按钮(例如同时使用音量调高按钮和音量调低按钮) 除了这些按钮的常规功能外,还会触发恢复出厂设置。
  • 当设备处于休眠或关闭状态时,禁止在笔记本电脑触摸屏上进行输入。
  • 解读笔记本电脑触控板手势(双指张合缩放、双指滚动)。

背景信息和术语

  • 人机接口设备 (HID) - 一种允许 用户,例如键盘、鼠标、触摸屏或消费者控件 (按钮)。通常情况下,这是指使用 USB-HID 的设备。 规范
  • 输入事件 - 单个用户输入事件,例如按键、移动鼠标 操作或触摸事件。在处理事件时,事件可能会带有 根据当前上下文提供更多信息。
  • 指针事件 - 与网页上的某个位置相对应的用户输入事件 例如触摸或鼠标事件指针事件是 事件。
  • 事件流 - 一组通常发生的相关输入事件 彼此相距不远
  • 输入处理程序 - 执行单个输入阶段的软件 处理。输入处理程序将输入事件作为输入,并发出输入 事件。它可以修改事件或与 系统。
  • 输入管道算法 - 这种算法需要将一个 一系列输入处理程序来处理 Fuchsia 输入。此政策充当 用于输入层,用于在 Fuchsia 上进行输入。
  • 输入流水线实现 - 输入流水线的实现 算法。实际上,这是 fuchsia.git 中的一个组件,负责 将驱动程序级用户输入事件路由到系统的其余部分。
  • Scenic – Fuchsia 图形引擎。风景区还负责 用于路由指针事件
  • 全球场景图 – 由 风景。
  • View - 场景图中的子空间。通常,观看 它对应于屏幕上的某个区域,尽管该区域不一定是 矩形
  • ViewRef - 事件对,与 特定视图此属性用于标识多个 Fuchsia 中的视图 组件。

架构概览

此设计概述了用户输入事件的整体流程 但并没有介绍每种类型的 输入。其中许多细节都在所链接的行业特定设计中得到了解决 。

自下而上:dev/class/input-report ->输入流水线 ->{场景或无障碍
Manager OR IME manager OR 媒体按钮监听器} ->{Chromium OR Flutter OR
Carnelian} ->{View 1 OR view 2 OR view3 OR view 4} 旁边:产品会话
组件 ->{input Pipelines OR root scene component} 根场景组件 ->
风景区内的风景区:焦点管理器、场景图(带有可视化树)
表示法:
绑定 ->指针事件处理程序 ->无障碍快捷方式处理程序 ->媒体按钮处理程序
->其他各种处理程序 ->IME 处理程序 ->
后备

事件按照多个相互关联的规则进行分派,包括, 不限于:

  • 该事件类型的产品政策(例如,所有音量事件都会分派到 设置)
  • 事件在屏幕上的位置(例如触摸或鼠标点击)
  • 当前聚焦的视图(例如,用于文本输入)

输入流水线是一个 Fuchsia 组件,负责 管理这些规则及其互动,以及将用户输入 将事件发送到相应的系统服务,以及 处理这些事件。它实现了输入流水线算法( 链式输入处理程序,每个处理程序在设备输入中执行一个离散步骤 处理中)。此组件充当 Fuchsia 上输入的策略层。通过 输入管道直接从驱动程序层提取事件, 驱动因素以及通过测试和 软件生成的事件,如通过虚拟键盘触发的事件。

事件在输入流水线中移动时,会从全局、低层级 事件(没有语义含义,而是敏感数据),以通过 可由最终用户软件解读的局部含义(手势、 字符等)。驱动程序级输入事件分为两大类:

  • 与屏幕上的特定位置相对应的指针事件。
  • 按钮和切换事件。

将来可能会进行扩展。USB-HID 用法表包含大量数据, 包含多项内容,其中包括飞行模拟器页面、锻炼页面 以及虚拟现实设备

驱动程序级输入事件可转换为:

  • 触摸手势。
  • 鼠标事件(包括滚动)。
  • 文本输入事件。
  • 语义无障碍操作。
  • 按钮事件(例如音量调节、摄像头开启/关闭)。

通常,系统会按如下方式分派每个事件:

Driver -> Input Pipeline -> UI System Component -> UI Framework-> UI View
  • 输入流水线组件包含许多称为“输入”的内部阶段 处理程序。输入管道充当输入的策略层,可能会有所不同 。(请参阅输入管道 自定义部分。)
  • 界面系统组件包括风景、无障碍管理器和 IME 但随着我们不断地向 Responsible AI 平台添加功能, 平台。这些组件是 Fuchsia 平台的一部分,位于 fuchsia.git.这些组件与产品无关。
  • 界面系统组件负责决定应该使用哪个(或哪些)视图 接收事件并将该信息传递给界面框架 运行程序。界面系统组件使用 Anthos 中的信息 (通常是焦点链)来确定应接收哪个视图 事件。
  • 界面系统组件也可以使用事件。
  • 界面框架目前包括 Flutter、Chromium 和 Carnelian。我们预计 将来支持其他界面框架/运行时。这些信息可能会用于 但不属于 Fuchsia 平台的一部分。
  • 界面视图是拥有相应屏幕区域的图形组件 称为“视图”(请参阅视图和事件路由 below.)
  • 媒体按钮事件并不总是遵循此模式。最终目的地 可能是设置服务而非界面视图。

在某些情况下,事件在最终传送之前可能会经过其他阶段。 例如,触摸事件可能会通过景观网站分派给 键盘组件,该组件会生成合成按键动作, 通过输入流水线进行分派。

输入管道将指针事件发送到风景,后者负责 将事件分派给正确的运行时实例。这样,街景就可以 对内容在屏幕上的位置保持全球一致, 并避免在动画播放期间出现竞态条件。(请参阅图形路由 事件。)

设计

输入事件的来源

输入事件通常通过输入驱动程序或 通过充当输入设备控制器的 Fuchsia 组件 (例如,蓝牙 HID 设备的 bt-host 组件)。在很多情况下 一开始是人机接口设备 (HID) 事件,但也有一些 异常。驱动程序和控制器以 fuchsia.ui.input/InputReport.一般来说,输入报告 由输入流水线使用和转换的。但在恢复模式下 直接发送到使用 Carnelian 无需任何中间处理

用于测试的输入事件以不同的方式生成。(请参阅测试 below.)

输入管道

输入流水线组件是一个 Fuchsia 系统组件。它 实现了输入流水线算法。输入流水线组件的作用类似于 输入堆栈中的政策层。它负责确定 事件类型以及输入事件应如何 以及管理输入设备。

输入流水线算法由以下部分组成:

  • 用于转换原始 InputReports 流(不包含任何 转换为 InputEvents (其中可能包含 系统状态)通过流水线传递。
  • 一系列 InputHandlers 可能会修改和/或使用 这些 InputEvents(可能通过将它们分派给其他组件)。
  • (可选)处理未处理的 InputEvent 的回退阶段。

绑定阶段通常会为 InputReports 提供有关 设备状态。示例:

  • 包含鼠标相对移动的 InputReport 会变为带有 屏幕相对坐标。
  • 按键流 InputReports 转换为“按键向下”流和“key up”键 InputEvents。(驱动程序通常只报告在给定时间按下了哪些键 而不是分离出上下事件。)“向上键”可能是 根据之后的 InputReport 中缺少某个键而推断出来。

理论上,产品对输入流水线的使用可由 紫红色产品 会话组件 ,了解所有最新动态。不过, 输入流水线不在会话领域内运行。输入流水线是一种 比会话更大的特权组件,并使用多种 我们目前不希望向会话组件公开的功能。

输入流水线实现作为 Fuchsia 平台。从本 RFC 发布开始,这些实现 和输入处理程序是实现 InputHandler Rust trait,但未来可能会对其进行更改,以允许 以实现优化和可扩展性。

目前,该平台提供两种输入流水线实现,一种是 已针对主要依赖触摸屏交互的设备进行优化,以及 另一个围绕产品使用鼠标和键盘。这种有限的学位 自定义功能在将来可能会得到扩展。(请参阅输入流水线 自定义。)

输入处理程序

输入处理程序 代表输入序列的 处理。输入处理程序是产品所有者 自定义与商品状态相关的输入处理方式。我们有时也指代 作为输入事件的产品政策。输入处理程序

  • 通过添加背景信息(例如,活跃的 键盘布局,或使用鼠标同时按下的按键 点击)。
  • 根据事件周围的事件流更改事件(例如,输入平滑、 触控板手势)。
  • 在处理程序中或通过将事件发送到服务来处理事件 由界面系统组件公开,而界面系统组件则负责分派 将该事件设置为相应的界面视图集。目标视图 取决于“风景”的当前视图焦点。(请参阅下文的重点)。
  • 发送 OutputReports 以控制输入设备的状态 (例如,设置 CapsLock LED 指示灯)。

在短期内,我们会定义一个 Rust 特征 InputHandler,该特征必须 由每个输入处理程序实现从长远来看,可以替换为 FIDL 接口。每个处理程序都必须能够处理输入事件, 应输出输入事件的向量(可能是空的)。

#[async_trait]
pub trait InputHandler: Send {
    /// Returns a vector of InputEvents after handling `input_event`.
    ///
    /// # Parameters
    /// `input_event`: The InputEvent to be handled.
    async fn handle_input_event(
        &mut self,
        input_event: input_device::InputEvent,
    ) -> Vec<input_device::InputEvent>;
}

未来基于 Fuchsia 构建的产品可能需要的输入处理程序示例(例如 都很新奇):

  • 无障碍输入处理程序:在发生相关情况时,将事件发送到无障碍管理器 无障碍功能(例如使用 键盘快捷键)。
  • 快捷键处理程序:确定键盘事件是否与正在运行的 键盘快捷键(可能会调用其他组件)。
  • Locale Handler:应用当前所用语言区域的相关信息 视图。
  • Pointer Event Dispatch Handler:将触摸/鼠标/触控笔事件发送到风景区 来分派给视图。
  • 媒体按钮处理程序:将媒体按钮路由到设置服务(或 )。
  • 键盘布局处理程序:使用当前处于活动状态的键盘事件为键盘事件添加注释 键盘布局。
  • 触控板手势处理程序:触控板手势和向前移动的鼠标 事件。
  • 输入平滑处理程序:通过平均事件减少抖动。
  • 焦点处理程序:使用当前视图的 ViewRef 为键盘事件添加注释 聚焦视图。
  • 睡眠模式处理程序:在设备处于休眠状态时抑制输入。
  • 多点触控华夫饼 Iron 魔法按钮处理程序:解读触摸手势事件 用作媒体按钮

在许多情况下,输入处理程序会将事件分派给 Fuchsia 系统服务 例如风景、无障碍管理器、IME 管理器等。在本课中, 在这种情况下,该事件将被标记为“已处理”并通过 流水线的其余部分。(请参阅事件流 一致性)。

输入流水线自定义

通过指定要包含的处理程序并实例化输入流水线, 它们的显示顺序。这样可以添加处理程序、对 或者非常轻量级地将修改后的流水线实例化。中的示例 Rust:

async fn input_handlers(
 ...
 ...
) -> Vec<Box<dyn InputHandler>> {
    let mut handlers: Vec<Box<dyn InputHandler>> = vec![];
    // Shortcut needs to go before IME.
    add_shortcut_handler(&mut handlers).await;
    add_ime(&mut handlers).await;
    add_touch_handler(..., &mut handlers).await;
    add_mouse_handler(..., &mut handlers).await;
    handlers
}

2021 年,该平台提供了两种输入流水线实现,分别 是作为 fuchsia.git 中的组件实现的,能够利用 特权 API 未在 fuchsia SDK 中发布。这些实现方式 许多输入处理程序(它们运行相同的代码), 它们支持哪些输入法。一种实现针对以下设备进行了优化: 主要依赖于触摸屏交互,而另一种则主要依赖于产品 鼠标和键盘。产品特定的代码仅限于设置 确定要实例化的处理程序的代码。

短期内,可通过以下方法向会话授予有限的可配置性: 公开功能(可能采用 FIDL API 的形式用于配置) 通过会话框架进行中介)以允许会话确定 输入想要启用的输入法此 API 允许在 并在会话启动时生效(即 产品用户体验)。我们无意支持“在 “Fly”在正常产品运行期间重新配置流水线 操作。

随着 Fuchsia 的扩展以支持更多产品类别,这组输入 处理程序和不同的产品配置可能会扩展, 必须公开一项功能,让会话可以选择 也可以直接配置 流水线阶段应该存在,并且按顺序排列。一些输入处理程序 特定于产品,并且需要存在于 fuchsia.git 之外。

每个产品都应该能够使用针对其数据量身打造的输入管道。 包括为该产品提供支持所需的输入处理程序 输入行为。至于具体如何实现这一目的的决策超出了本次讨论的范围 RFC。理想情况下,任何此类配置解决方案都可以利用 平台提供的结构化配置机制 而不是发明一些专门针对输入数据的东西, 公开满足产品要求所需的最低限度的配置 surface 需求。

数据视图和事件路由

Fuchsia 界面可能包含屏幕上同一时间的多个运行时的图形 。界面会整理成一个全局场景图,所有者为 风景,包含构成用户界面的图形内容以及 呈现它所需的信息运行时可以提供用户可见的内容 将其添加到场景中,方法是将其添加到名为“视图”的风景资源中。 安装在场景图中。通常,一个视图对应于 但这些区域不一定是矩形,也不是全部 特定时间显示哪些数据视图因为每个景观都是本地风景资源 不适合在其他组件中引用,我们会关联内核 ViewRef 对象。

视图以分层方式进行整理,子视图仅影响屏幕 父视图边界内的不动产,即严格包含 模型。”如果某个视图是图表中另一个视图的父视图,则该父视图 对子项拥有一定的控制权,尤其是在与内容有关的控制权方面 展示位置和事件路由

查看树

下图说明了场景图根部的结构。

根 ->无障碍视图 ->系统界面 ->{some view, some other view, yet
另一视图}

  • 与无障碍管理器关联的视图允许 来拦截无障碍服务所需的输入事件 以及“在顶部”绘制界面的其余部分 。
  • “sysUI”(系统界面)视图是所有其他视图的父级。此视图 通常用于实现“系统手势”(例如在边缘滑动 和系统键盘快捷键。它还用于 为界面的许多非输入方面进行优化

路由图形事件

对于与屏幕上的特定位置对应的用户事件(例如触摸、 鼠标、触控笔),则输入事件在分派给 与每个视图关联的运行时实例这种方法的优势包括

  • 场景图隔离:“风景”是唯一具备完整 了解哪个视图位于屏幕上的位置我们不允许 组件查询屏幕上给定点(也称为 “命中测试”)。
  • 全球一致性:因为“景观”是给定地点的可信来源 视图显示在屏幕上时,让风景调度事件避免 视图在两个时间之后改变大小、位置或消失的问题 输入事件发生的位置和传送时间。尤其是 并且更新频率可能非常高 与设备互动请注意,Skys 还拥有焦点链, 用于使非指针事件的调度保持一致。
  • 并行调度(手势消除歧义):当视图重叠时, 关注特定事件流的多个视图。例如,一款产品 可能希望实现“系统手势”例如滑动关闭某个 而应用本身可能会解释该手势 。风景负责决定应获得哪些景观 并通过称为“手势”的过程在事件之间进行协调 消除歧义。在此模式下,系统会在 并并行处理多个视图,然后在“手势舞台”中解析,更改为 决定哪个视图最终使用事件流。

专注

为了确定当前正在运行的哪一段软件应该收到 对于给定的输入事件,我们需要一个视图焦点的概念。以上就是 “有效”并准备好接收事件。然而,在实践中 可能会有多次浏览者对每个事件感兴趣。

视图焦点通过焦点链(一个矢量 与聚焦的视图及其在视图中的祖先实体相对应的 ViewRef 树)。焦点链归景观团队所有(因为风景区管理景观),但 其他组件可能会请求更改当前焦点,例如在 响应无障碍功能操作或键盘快捷键。输入流水线 负责监控焦点链中的变化,并提供 信息提供给输入处理程序,后者可能会将事件转发至正确的 客户端组件/视图。焦点链的终端元素对应于 当前聚焦的视图

一些处理程序对单一聚焦视图感兴趣,而其他处理程序则 对整个焦点链感兴趣。例如:

  • 不触发键盘快捷键的键盘事件通常会路由到 当前聚焦的视图
  • 无障碍管理器使用聚焦的视图来确定当前 “有效”屏幕阅读器。
  • 键盘快捷键管理器关注的是整个焦点链、 它可能注册了键盘快捷键和相关联的优先级。

焦点事件作为特殊类型的 InputEvent 在输入流水线中移动, 会与其他输入事件严格有序。

事件流一致性

事件流是一组通常发生的相关 InputEvent 彼此相距不远例如:

  • 键盘:“a”向下键 ->“a”向上键
  • 鼠标:HOVER ->悬停 ->BUTTON_DOWN ->BUTTON_UP
  • 触摸:向下指 ->移动 ->移动 ->移动 ->向上指

系统必须确保事件流在 进行微调这意味着,如果输入处理程序使用 事件,它应该发送相应的“已处理” 事件传递给后续输入处理程序,以便它们可以通知任何客户端。

如果焦点在处理事件流时发生变化,也是如此。从 从客户的角度来看必须与相应的“key” 或“取消”事件(如果焦点发生更改或输入设备断开连接)。通过 鼠标点击和触摸事件流也是如此。输入流水线 负责将事件标记为“handled”并通过 输入流水线,以确保流的一致性。系统服务负责 在直播取消时通知视图。

性能

可接受的延迟时间

用户输入具有时效性。延迟时间(即从某个时间点 事件发生的时间)最好越低越好, 用户的延迟时间的容忍度因输入类型而异用户可能会遇到性能下降的情况 工作效率(他们能否完成一项任务)和满意度, 延迟时间低至 在某些情况下为 10 毫秒。用户体验开始明显下降到 100 毫秒以上,并且 时长超过 300 毫秒是不可接受的。直接操作(例如在 对延迟特别敏感,可能需要预测事件 提供可接受的用户体验。(请参阅此延迟时间 论文,以了解相关背景。)

由于本 RFC 中描述的输入系统在运行级别低于 以及以此为基础构建的界面,用户将体验到系统输入 以及由于处理和呈现广告 对输入事件的响应。因此,输入系统应尽可能快 尽可能多地留出“延迟时间预算”尽可能向应用提供 和运行时。

此外,一致的时间安排也很重要。即使事件平均传送时间 事件时间的波动性太大,会降低用户体验,因此 请务必查看延迟时间的分布和平均值

提高性能

减少输入架构延迟时间的最佳方法是 不必要的进程上下文切换。内核的每个进入和退出 这通常需要运行调度器, 事件的发生时间

将来,我们可能会探索在图形中运行多个组件并 输入堆栈(例如,景观管道和输入管道)作为 以进一步减少进程的跳跃次数。我们可能还会重新审视 将 Rust 作为输入流水线的实现语言,如果我们发现 会导致额外的延迟

引入了针对以下情形的手势消除歧义(也称为并行调度) 在等待事件处理之前, 响应给定事件流的相关组件。为此, 算法的性能,客户必须积极配合,并及时对输入做出响应 事件。系统将需要某种机制来指定和强制执行客户端 延迟时间预期 (SLA)。我们将在未来的设计中详细介绍这一点。

国际化和输入上下文

每个视图都有自己的输入上下文,其中包括活跃的输入 method(“主动键盘”)。输入上下文不同于 信息 fuchsia.intl.Profile 该参数包含用户首选的语言区域,可影响界面。 演示文稿。不过,用户的语言区域设置可能会影响 方法/键盘布局。请参阅Fuchsia 国际化 文档,详细了解 Fuchsia 国际化。

系统应允许不同的视图具有不同的活动输入 方法。例如,用户在聊天时可能会使用一种语言撰写电子邮件 以其他语言显示。产品可以选择强制执行单一系统级语言区域 或主动输入法,但架构必须支持不同的输入 为每个视图提供上下文。到底应该如何存储这些设置 。

除了将事件路由到正确的视图之外,输入管道(以及 相关的系统组件(如 IME 管理器)将使用输入上下文来实现 解读输入事件时使用该视图。例如,输入流水线 使用键盘布局相关信息为实体键盘事件添加注解 在发生事件的输入上下文中处于活跃状态。与聚焦一样 更改,更改当前使用的键盘布局应考虑输入事件 并与其他事件一起处理,以避免与 更改状态。

无障碍

为了让无论能力如何的用户都能使用 Fuchsia 设备, Fuchsia 无障碍功能框架提供了许多无障碍功能, 改变用户与设备的互动方式。具体而言,这可以实现:

  • 一个“放大”的放大镜部分或整个界面上
  • 可让盲人或低视力用户探索和互动的屏幕阅读器 通过“语义树”实现的,与当前界面相对应。

启用这两项功能中的一个或全部后,无障碍功能管理器需要 通过输入流水线拦截输入事件并将它们解释为命令 切换到当前已启用的无障碍功能。这些命令可以使用 具体取决于设备类型例如,工作站 屏幕阅读器主要使用键盘快捷键操作,而屏幕 触摸屏设备上的读取器可能会通过多次点按和滑动来实现。取决于 启用了哪些无障碍功能时,无障碍功能管理器可以 决定只使用一些事件(例如放大镜, 会使用一些手势,但允许其他手势传递至界面)或全部 事件(如同屏幕阅读器一样,它会将事件转换为语义 操作)。

无障碍功能管理器会保持与每个视图的连接,以便 通过 语义 API fuchsia.accessibility.semantics。例如“点按两次” 通常情况下,在启用了屏幕阅读器的情况下, 语义“默认操作”当前选定的语义节点上。

安全注意事项

输入管道和相关系统组件使用许多 未在 SDK 中发布的特权 API。要求会话使用 输入流水线进行输入处理,平台就能够限制 外部软件可用的功能。

考虑界面补救攻击也很重要,例如 点击劫持。误定向的输入事件可用于授予权限,无需 征得用户同意(例如,将点击操作路由到恶意网站上的按钮)。 虽然在平台级别很难完全防止这种情况, 架构必须确保仅将图形事件传送到正确的界面 并且产品所有者可以轻松了解 输入事件发生。

隐私注意事项

对输入流水线的更改应通过隐私权审核, 攻击者可能会通过用户输入来创建一个键盘记录器或其他恶意 软件开发应用。除恢复模式外,输入流水线应该是 只有组件才允许用户直接从驱动程序输入事件, 这个。

测试

测试输入流水线

应使用封闭的集成测试来验证平台输入行为 对应于支持的输入功能(例如触控输入、键盘快捷键) 与使用这些功能的产品代码无关。测试应使用 尽量减少每个支持的运行时中的图形组件,以验证相关的 功能确保独立于特定产品的功能稳定性 它对于开发者构建树外产品非常重要。

封闭测试带来了许多不在上述范围内的挑战 RFC。

测试所有其他内容

端到端测试在很大程度上依赖合成输入事件来模拟用户互动 以可重现的方式进行测试虽然大多数界面框架都包含 注入事件(例如 Flutter 驱动程序),这并不足以测试任何 涉及多个运行时的情况。这意味着 Fuchsia 提供了用于创建虚假输入的适当 API。这完成了 通过 SL4F 和 Fuchsia 输入合成库,该库将事件插入 输入流水线。此 API 应 用于开发者 build,但绝不会用于正式版 build,因为这允许注入 任意输入。

输入行业

支持各种不同类型的输入设备显著增加了复杂性 高级架构。这些详细信息将 在后续 RFC 中处理。主要输入行业包括:

  • 实体键盘(蓝牙和 USB)
  • 虚拟键盘或屏幕键盘
  • 鼠标
  • 触控
  • 触控板

文档

此 RFC 的内容应添加到 Fuchsia 公开文档中 以及实现细节

考虑的备选方案

本部分包含所讨论的部分(详尽)替代方案。

将 root Presenter 演进到流水线

过去,Skys 负责分派所有用户输入事件, 包括没有图形/位置组件的键盘事件。这是 虽然键盘事件具有 已移除。root 中的现有输入处理代码 会扩展 Presenter,从而处理 应用场景。不过,此代码没有达到测试覆盖范围,需要 从而实现所需的一致性和 可配置性,并消除输入处理和 图形 API。

产品特定的风景

因为输入(尤其是基于指针的输入)与 一个选项探索是通过路由输入处理, Scenic,Fuchsia 图形引擎。此架构将是 完全偏离当前状态。在这个版本中,合成器为 在“即时模式”下去除了“风景”和也就是说它必须绘制 每次窗口管理器更改时。Mountain 成为窗口管理器 (假定这是特定于产品的组件,需要 每种产品类别的不同实现方法。输入通过 组件。

虽然这在任何单一产品中都能达到理想效果,但需要任何输入 为具体产品提供定制服务 引擎。这可能意味着,您需要专门实施风景, 为每种新产品类型提供专用值这种方法可能是一种非常实用的优化方法, 但对于目前的应用场景而言被认为过于重量级。