RFC-0147:查看系统

RFC-0147:视图系统
状态已接受
领域
  • 显卡
  • 人机交互
  • 查看系统
说明

介绍了 Fuchsia 平台的窗口系统,并说明了其在平台中的作用。

问题
  • 83310
Gerrit 更改
  • 602783
作者
审核人
提交日期(年-月-日)2021-11-03
审核日期(年-月-日)2022-01-05

总结

此 RFC 概述了 Fuchsia View 系统:一组 API,用于对可视区域(“视图”)及其生命周期进行推断并与之交互。这组功能在其他平台上通常也称为窗口系统。此 RFC 的范围仅限于具有单个显示屏的产品。未来的 RFC 中会介绍为适应无头设备和/或多个显示屏而进行的变更。

View 是一个图形内容区域,是 Fuchsia 上图形和用户互动的基本单位。视图连接形成一个视图树层次结构,并具有可区分的根视图。Fuchsia 的图形合成器 Scenic 从 View 树中的每个 View 中渲染图形内容,以生成显示屏的输出。View 和输入流水线负责将面向界面的用户输入(例如键盘、鼠标和触摸)路由到正确的视图。

视图系统是 Fuchsia 平台对“自带运行时”的支持的关键部分,也是产品开发者使用多个运行时中的图形内容在 Fuchsia 上构建安全的视觉用户体验的机制。Fuchsia 的组合 API(Flatland 和 GFX)基于 View System 构建。

设计初衷

此 RFC 旨在记录和确认“世界状态”(涉及 View 系统)。具体而言,我们希望批准以下决定。

  1. 希望在 Fuchsia 上显示图形的组件必须使用视图系统创建视图。唯一的例外情况是单窗口实用程序界面(如 Virtcon 和恢复界面),它们不使用窗口功能,并且设计为在“Scape 未运行”时资源有限的情形下运行。这些界面直接与显示控制器通信。
  2. 只有通过视图系统,组件才能与 Fuchsia 平台对用户触摸、鼠标、键盘和无障碍服务的支持集成。
  3. View 系统与所使用的合成策略(GFX 与 Flatland)无关,并为 Fuchsia 上的所有合成器实现提供共享基础。

修改这些决定需要额外的 RFC 和/或对此 RFC 的更新。

利益相关方

教员

hjfreyer@google.com

审核者

此部分预计会在审核期间更新

  • 图形:reveman@google.com、jjosh@google.com、emircan@google.com
  • 输入:quiche@google.com
  • 组件:ypomortsev@google.com
  • 安全:kostyak@google.com
  • 常规:wez@google.com

咨询人员

sanjayc@google.com、hjfreyer@google.com、jjosh@google.com、lindkvist@google.com、geb@google.com

社交

草稿文档已发送给“Scape”和“Input”团队进行讨论。

术语库

  • 场景
    • Fuchsia 平台中的图形合成组件
    • View System API 的唯一实现者,包括其与图形组合 API 和 HCI API 的关联。
  • 查看
    • 图形内容的视觉区域。
    • 它具有坐标系、边界框以及通过视图树与其祖先实体定义的空间关系。
  • 查看树
    • 系统上 View 的结构,通过父子关系连接。视图树的根视图通常附加到显示屏。
  • 屏幕
    • 基于像素的输出设备;也称为屏幕。视图系统目前支持一次连接到系统的一个屏幕。
    • 该屏幕通过显示控制器进行管理。
  • 显示控制器
    • 此驱动程序负责管理与计算机相连的屏幕。
    • 只和“Scape”对话。
    • 不适用于树外客户端。
  • 场景管理器
    • 用于将根 View 附加到屏幕的平台组件。
  • 无障碍管理器
    • 实现无障碍功能 API 的平台组件。
    • 它具有访问 View 系统的特权。
  • 系统 shell(“Sys UI”“系统界面”)
    • 负责产品用户体验的组件,例如 Ermine。该组件通常特定于特定商品。
    • 系统 shell 负责窗口管理,包括顶级视图的焦点处理和管理,而 View 系统负责处理窗口系统
  • 开发者 shell ("tiles", "present_view")
    • 用于测试的系统 shell。通常,这允许开发者单独启动 Fuchsia 组件。
  • 界面客户端
    • 这是指代 View 所有者的通用方式,在整个 RFC 中一直使用。
    • 示例:具有多个顶级 View 的 Flutter 应用 Chromium。

设计

数据视图的定义

Fuchsia 视图是 Fuchsia 上图形和互动的基本单元。View 定义了一个可向用户显示图形内容的视觉区域。在指定时间,并非所有视图都会显示。每个视图的图形内容由 Fuchsia 组件提供。对管理 View 及其内容合成到屏幕上的平台支持由 Sense 实现。

每个数据视图:

  • 可以整合另一个 View(其子 View)的内容,形成 View 树
  • 定义用于放置子内容的坐标系。
  • 具有边界框,用于定义该视图的可见部分(还可选择互动部分)。
  • 可与“风景景树”连接和断开。(未连接的 View 可能存在,但不会将其内容渲染到屏幕上,也不会接收输入。)

Views 支持的任何图形组合 API(例如 fuchsia.ui.compositionfuchsia.ui.scenic)必须提供创建 View 并管理其生命周期的方法。任何未来的组合 API 还必须在 View 系统上运行。Fuchsia 平台 HCI API(例如指针键盘)使用视图来路由输入。(如需了解详情,请参阅下文的输入部分)。

查看树

有一个全局 View 树,由 Snow 拥有并实现。View 树有一个连接到屏幕的标识根 View。shortcuts 是唯一一个直接操控所有 View 及其位置的 Fuchsia 组件。

View 树中的每个 View 均在其坐标系中定义边界,以及在父 View 的坐标系中表示的位置和方向。这些因素共同决定了图形内容在屏幕上最终可见的区域,以及响应用户输入的区域。

子视图

通过在一个 View 的坐标系中创建空占位符,可以从另一个 View 嵌入其他图形内容;该占位符称为“viewport”。这两个 View 在 View 树中形成父子关系,其中父 View 的视口会嵌入子 View 的图形内容。为了建立这种关系,父级和子级必须在创建各自的视图和视口时提供匹配的令牌。这些令牌以内核对象的形式实现,并且不可克隆。父级和子级可以通过各种方式获取这些匹配令牌,这些方式在 View 系统之外。

从视图树中附加或分离父视图也会附加/分离其子视图。即使子树与全局 View 树分离,子树中 View 之间的连接也会保留。

视图隔离

虽然一个 View 可以嵌入另一个 View,但 View 系统不会向 View 授予对任何其他 View 的图形内容的访问权限。这种隔离保证是视图安全性的基础之一。

地图屏幕浏览量

“Sthere”组件是唯一与屏幕控制器通信的组件。它利用整个 View 树的图形内容以及在树中编码的关系来创建单张图片(可能会具有多个图层)。然后,它会对硬件进行编程,以显示最终的屏幕图像。

查看所有权

View 中的内容由单个 FIDL 通道提供给图形组合 API(由 Views 实现)。连接到 Views 的 FIDL 通道的每个客户端端点都称为“界面客户端”,界面客户端最多可以创建一个 View。

视图可能来自各种组件,包括面向用户的组件(例如浏览器)、系统界面以及属于 Fuchsia 平台的组件,例如无障碍管理器。一个组件可能会创建多个频道,进而创建多个 View。因此,在某些情况下,单个组件可能会同时提供父 View 和该 View 的子 View。

为了组合多个组件的图形,开发者应该在每个组件中创建一个或多个 View,并使用子 View 和 View 树进行组合。请务必注意,视图树层次结构不需要与组件实例层次结构匹配。在许多情况下,我们特意设计了这些结构,使它们看起来截然不同。

Runtimes

对于使用更高级别语言(如 Dart 或 JavaScript)编写的组件,运行程序实现通常负责创建和管理视图。使用这些语言的开发者可能不知道底层操作系统的许多细节;运行程序需负责将 View 生命周期转换为特定于语言或特定于运行时的机制。

窗口管理、窗口系统与组合

Fuchsia 将三项功能有时在其他平台上合并使用。

  • 窗口管理纳入了特定于产品的政策和窗口行为方式的特定选择。在 Fuchsia 上,由系统界面负责,完全不在平台内运行。
  • 窗口系统指的是低级窗口管理。在 Fuchsia 上,这由视图系统处理。
  • 组合是指合并来自多个来源的图片以生成用于显示的图片。目前,Scenic 组件也负责这方面的工作,但未来可能会有所变化。

将窗口系统和组合区分开来的选择为图形呈现提供了一种快速路径,并可实现高效的实现。虽然 View 系统和合成器目前主要在 Views 中实现,但在 API 和代码方面,它们是独立的。这种分离使 View 系统能够支持多种合成策略(Flatland 和 GFX)。

通过将窗口管理设为产品级关注点,我们将政策逻辑保留在平台之外,从而确保平台和产品完全区分开来。

输入

视图系统是 Fuchsia 平台确定如何路由用户输入(例如指针事件或键盘事件)的主要机制。Fuchsia 的用户输入 API 旨在将每个通道的作用域限定为特定视图。输入将根据当前的视图焦点(如果是键盘事件)传送到视图,以及/或者传送到与输入事件位置对应的一个或多个视图(例如轻触或鼠标事件)。视图只能在连接到视图树时接收用户输入。

多个视图可以参与同一事件的输入处理。特定产品的窗口管理器可以根据产品政策配置此路由,例如通过向系统界面授予对鼠标事件的全局访问权限。如需了解详情,请参阅用户输入架构。该系统可实现跨多个运行时的 View 无缝用户体验,包括能够消除触摸手势的歧义

这带来的一个重要影响是,Fuchsia 平台之外的组件无法直接访问来自驱动程序的输入事件。它们必须接收由 View 系统中介的此信息。

查看焦点

在任何时候,视图树都有一个可辨别的视图,称为聚焦视图。聚焦的 View 通常是用户期望接收用户输入的 View。Fuchsia 的输入子系统依靠视图焦点来确定将输入路由到何处。如需了解详情,请参阅焦点链文档。父级 View 所有者可以控制其子树中的 View 焦点。

ViewRef

平台使用名为 ViewRefs 的令牌来识别 View 并就 View 进行通信。ViewRef 是对特定视图的唯一引用,在系统重新启动之前一直是唯一的。它以内核对象的形式实现,其句柄可以自由复制并通过任意协议发送给其他组件。

View System API 大量使用 ViewRef,为每个 View 提供稳定的跨组件引用。ViewRef 还用于发送有关关联 View 的生命周期事件。这样,平台内外的其他组件都可以就 View 及其生命周期进行通信,并将用户输入和无障碍功能协议路由到 View。

实现

景观是 View 系统的权威来源,因为 View Tree 和核心 View 管理 API 在 Views 中实现。每个客户端都使用其 ViewRef 注册来接收关联的 View 的用户输入和无障碍事件。Card 目前支持两种图形组合 API:fuchsia.ui.scenic(旧版)和 fuchsia.ui.composition(开发中)。View 系统彼此独立,但彼此协同工作。

API 实现详情不在本 RFC 的讨论范围内,但相关 API 可在下面找到。值得注意的是,这些 API 是多年来逐步发展的。未来可能会简化某些方面。

View 系统涉及的平台组件

  • 风景
  • 输入管道
  • 场景管理器(或旧版系统上的根 Presenter)
  • 无障碍管理器
  • 短信管理器

用于数据视图管理的 API

用于用户输入的 API

用于实现无障碍功能的 API

性能

视图系统的许多方面都会影响图形和输入性能。下面介绍一些重要方面。

  • 所有运行时均相同:Fucsia 的自带运行时原则意味着,Fuchsia 上的所有运行时都使用相同的事件路由,并且不会优先对待运行时。
  • 渲染一次:Sour 页中可以合并不同 View 的图形内容,而无需重新渲染,因为它知道视图位置,可以正确地将图形内容转发到显示驱动程序。
  • 高效调度:Sensing 可提供焦点信息,允许非图形用户输入(例如键盘事件)直接从处理该输入的组件中调度。

安全和隐私权注意事项

View 系统为在 Fuchsia 上安全地编写图形内容提供了多项保证,这些保证为实现安全用户体验奠定了基础。但是,单独的 View 系统无法保证所有用户体验都是安全的,只不过 View 系统尊重自己的安全保证。

视图系统尝试通过以下方式实现安全的用户体验:

  • 将拥有和操控 View 树的全部责任委托给 Scenic。
  • 将在屏幕上显示图形内容的唯一责任委托给景观。
  • 禁止界面客户端操控没有匹配的视口或 ViewRef 的其他 View。
  • 禁止界面客户端使用 View 系统检查任何其他界面客户端 View 的内容。
  • 仅允许界面客户端将输入注入其 View 子树。
  • 仅允许 View 在连接到视图树时获得焦点并接收输入。

界面安全依赖于组件框架在功能路由方面提供的保证。未来的 RFC 中会详细介绍 View 安全性。

测试

视图系统是在多个抽象层实现的,因此使用分层方法进行测试。

在 fuchsia.git 中:

  • View 组件的代码库中对 View 树和 View 生命周期的单元测试。
  • 界面集成测试(位于 /src/ui/tests 中),用于执行与 View System API 相关的合同。
    • 这些 API 由 S View、Scene Manager、Input Pipeline、Accessibility Manager 和 Text Manager 等平台组件提供和使用。
  • fuchsia.ui.observation.test API 在树内集成测试中使用,以检查 View 系统的行为。

树外:

  • Chromium 和 Flutter 等运行时会编写集成测试来运行 View System API
  • 产品会编写间接执行 View 系统的端到端测试。

文档

此 RFC 简要介绍了 View 系统的角色和责任。我们会撰写相关文档和可能的其他 RFC,以提供详细地址信息。

鉴于此 RFC 以及 Flatland 即将发生的变更,您还需要更新部分 Scenic 文档

缺点、替代方案和未知情况

已知限制

View 系统目前缺少在多个 View 之间同步更新的机制。

View 系统部分负责将 capability 路由到公开 View 的运行时(使用 ViewRef)。这与通过 Fuchsia 的组件框架进行的功能路由在概念上存在一些重叠,但目前是完全独立的。将来,在组件框架中支持 View 功能可能很有用。

当前的 API 只允许视图所有者创建子视图。对于希望创建多个顶级窗口的应用这类应用,这不太理想。

由于 View System API 多年来在许多不同的贡献者的推动下自然发展,因此运行时开发者的认知负担目前非常高。未来,您应该通过更好的文档和示例以及可能的 API 简化来缓解这一问题。

替代选项

视图系统架构进行了许多架构选择。

  • 任何带图形的商品都必须使用 View 系统。
    • 或者,Sensing 可能是可选的,产品也可以包含自己的合成器。这需要从树中公开许多低级别 API。
    • 当前方法的优点:
    • 跨运行时的同构行为(包括无障碍功能和输入)
    • 一致的安全保证
    • Display API 可以在不影响客户端的情况下不断发展完善
    • 当前方法的缺点:
    • 减少商品定制
    • 运行时集成的复杂性
    • 如果未来在紫红色上构建的产品需要,此要求可能会发生变化。
  • View 系统分布在多个组件中,包括 Scape 和输入管道。
    • 或者,我们也可以将整个 View 系统构建到景观中。
    • 当前方法的优点:
    • 分离关注点:图形组合、窗口管理和产品政策都是独立的。
    • 允许通过委托组合功能实现高性能图形路径
    • 与界面相关的组件可以独立改进
    • 允许图形继续工作,即使子系统(例如文本输入)崩溃也是如此
    • 当前方法的缺点:
    • 使用 IPC 时,多个进程可能会增加延迟时间
    • 增加了组件之间的协调/同步复杂性

早期技术和参考资料