RFC-0189:窗口管理 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 描述用于窗口管理的平台架构和标准 API。 |
问题 | |
Gerrit 更改 | |
作者 | |
审核人 | |
提交日期(年-月-日) | 2022-08-12 |
审核日期(年-月-日) | 2022-09-20 |
总结
此 RFC 提出了一个模型,用以说明 fuchsia 平台、产品会话和会话 shell 如何协同工作,以支持具有多个窗口的复杂图形应用。具体而言:
- 虽然平台负责负责将图形放置到屏幕上和路由输入的机制,但产品组件必须指定针对何时以及如何显示图形的特定于产品的政策。
- 该平台将定义一个用于窗口管理的标准化 API Surface1,以实现应用和产品之间的最大兼容性。
这样做的一个重要结果是应用会与 Fuchsia 平台集成,而不是与特定的 Fuchsia 产品集成,因此与一款 Fuchsia 产品配合使用的应用应该与支持同一组数据选取功能的任何其他 Fuchsia 产品配合使用。特别是,针对一款 Fuchsia 桌面产品运行的应用应针对任何此类产品运行,无论特定产品会话或系统 shell 实现如何。
此 RFC 在 RFC-0092: Sessions 的基础上进行了扩展。描述的是计划状态,而不是当前的运作方式。此 RFC 中介绍的方法取代了之前的所有尝试(模块化、会话框架),是未来记录计划。
设计初衷
当前的 Fuchsia API 导致产品和应用难以实现丰富的窗口管理和多窗口应用。平台责任和产品责任之间的区别令人感到困惑,并且该平台提供的 API 始于早期 Fuchsia 愿景时代,并且缺少当前工作所需的一些重要功能(例如工作站)。此前,我们已尝试过解决此问题和相关问题(模块化、会话框架),但并未在所有 Fuchsia 平台上完全实现。
系统的当前状态缺乏明确的责任划分,并且可以通过多种方式执行相同的操作。这导致了不同产品间的不一致现在,通过批准架构,我们可以就该平台将来支持的 API 做出未来决策(例如,有可能采用 Wayland 在 Fuchsia 中使用),并解锁 shell 和应用开发的障碍。
此 RFC 可能是介绍窗口管理不同方面的系列文章中的第一篇。其目标是阐明产品和平台之间的划分,使以后更容易决定要使用哪些 API(例如 Wayland)。
利益相关方
教员:abarth@google.com
审核者:
- 显卡:dworsham@google.com
- 工作站:sanjayc@google.com
- 架构:abarth@google.com
- 组件框架:theguy@google.com
- Chrome:wez@google.com
- 用户体验:asz@google.com
咨询人员:quiche@google.com、jasoncampbell@google.com、geb@google.com、masonben@google.com、jsankey@google.com、tjdetwiler@google.com
社交:在通过 Gerrit 发布之前,我们与利益相关方分享并广泛讨论了此 RFC 的草稿。
定义
在本文档中:
- 显示服务器(也称为合成器):一种组件,负责允许应用组件创建和显示视图,允许控制这些视图的位置和大小,并确保将图形输入事件基于应用组件的视图传递给应用组件。在 Fuchsia 上,这是场景。
- 窗口管理器:用于控制应用所提供窗口的放置位置和外观的组件(一个或多个组件)。在某些系统上,此系统还负责呈现界面(例如标题栏)。由于 Fuchsia 平台可用于实现具有截然不同的图形和输入功能的各种产品,因此在 Fuchsia 上,窗口管理器职责的分配可能与其他操作系统截然不同,在这些操作系统中,该平台更贴近单一用户体验。
- 系统 Shell:负责绘制产品界面的组件。该组件在显示视觉内容的视图层次结构的产品子树中拥有顶层视图视图。此视图有时称为 shell 视图。系统 shell 负责安装视图树中由应用组件提供的视图,并就如何显示这些视图制定政策决策。
- 产品会话:负责实现紫红色产品体验的组件。此组件作为会话管理器的子级运行。此组件负责启动具有适当功能的应用组件,以响应用户操作。截至撰写此 RFC 时,Fuchsia 一次仅支持一个会话。
- 元素:包含图形的组件的会话框架概念。此 RFC 弃用了元素角色。
- 应用组件:一种用于实现图形用户体验并在系统 shell 中运行的组件。
- View Tree:景观场景图中的视图层次结构。
设计
概览
Fuchsia 上的窗口管理主要分为两个方面:机制和政策。
- “政策”是指针对具体产品的详细信息,其中说明了允许哪些组件在屏幕上展示图形、这些图形的显示位置、它们如何接收输入和焦点,以及它们在视图树中之间的关系。政策旨在决定允许对窗口执行的操作。
- “机制”是指使像素在屏幕上呈现并将输入路由到其底层组件的机制,主要通过 Fuchsia 界面堆栈处理。所有提供图形的组件都必须与这些 API 进行通信。政策决策的影响可能需要多次调用机制 API,才能对界面进行相关更改。
Fuchsia SDK 为窗口管理政策定义了两个 API 接口:
- 一个 API,供系统 Shell 实施特定于产品的窗口管理政策,并提供有关此产品上提供的窗口管理器功能的信息。目前,这是通过要求系统 shell 实现图形演示者角色来实现的。
- 一个 API 或一组 API,供应用组件用于请求更改该组件拥有的视图的存在性和外观。这种机制采用所有应用客户端都应使用的核心 API 的形式,以及可用于实现其他行为的扩展(可在运行时检测)。此 API Surface 应在所有 Fuchsia 应用之间共享,这有助于促进基于 Fuchsia 构建的不同产品之间的兼容性。
目前,客户端应用的实现细节差异很大。一些应用会实现元素角色,而其他应用则直接与组件框架和场景交互,或在应用中实现元素管理器 API。此 RFC 要求对所有应用组件改用单个 API,以简化这一过程。
此 RFC 目前并未就系统 shell 和应用组件是否相互直接通信,或者平台组件是否应调解这些交互这一观点发表看法。
架构示意图
上图展示了在 Fuchsia 上运行的图形产品的可能架构。产品会话负责启动系统 shell 和所有应用。应用和系统 shell 必须就任何政策决策进行通信,可能通过平台提供的窗口管理器或“桥接”组件进行沟通(请参阅下文中的可能的平台桥组件)。系统 shell 和应用还必须与 Fuchsia 平台的界面堆栈(包括处理图形和输入处理的组件)通信,以针对窗口管理的“机制”执行。这种通信也可能通过桥接组件进行。
产品会议职责
产品会话是产品启动时要启动的第一个产品专用组件。对于带图形的产品,它具有以下额外责任:
- 产品会话负责启动应用组件并为其提供适当的功能,包括在屏幕上显示界面所需的功能。
- 产品会话必须提供根视图来提供用户体验,方法是直接实现根视图,或将其委托给子组件。提供此视图的组件也称为系统 shell(有时也称为系统界面)。系统 shell 具有一项功能 (fuchsia.session.scene.Manager),可以让其在视图树中安装其根视图。(请注意,一个产品可以包含多个 shell,如登录和用户 shell,并可以根据需要在它们之间进行切换。)
- 产品会话负责窗口管理的产品政策方面。特别是,会话必须实现 Fuchsia SDK 提供的窗口管理政策 API。该责任包括提供有关此产品上可用的窗口操作类型的信息。
组件层次结构示例
此图显示了用户体验可能的组件层次结构。请注意,这会排除元素管理器。如上所示,应用组件是产品会话的子级。某些产品可能会选择以不同的方式进行设置,例如,在产品会话领域中创建一个负责启动应用的组件,或者将应用组件实例化委托给某个具有不同功能的平台组件。
设置视图层次结构
启动后,应用可与界面联系以创建应用视图,然后通过窗口管理 API 联系系统 shell,以在系统 shell 的用户体验中显示该视图。系统 shell 联系场景以将应用视图安装到视图树中(通常作为根视图的子级)。
应用可能会按照上述初始窗口创建流程,打开第二个顶级窗口。进一步的窗口管理操作(例如调整应用视图大小、启动弹出式窗口等)需要应用组件通过调用窗口管理 API 从系统 shell 请求这些更改。一般来说,负责直接与其拥有的 View 内容的场景通信的每个组件。不过,如果视图所有者/应用想要更改其视图的显示方式(例如调整大小、最小化或打开另一个顶层视图),则系统 shell 必须以某种方式指示允许执行此操作。系统 shell 可以通过以下两种方式实现此目的:响应客户端 API 调用;或者在视图树中存储信息来指示允许该视图执行的操作,并允许 Views 执行相关政策。
注意:
- 生成的组件层次结构和视图树看起来并不相同!虽然应用视图必须是系统 shell 所拥有的视图的子视图,但应用组件不需要是系统 shell 组件领域的一部分。
- 该说明省却了关于视图创建的大量详细信息,包括用户输入等如何通过视图树路由到视图。
示例视图层次结构
上图显示了运行多个图形应用的系统界面的示例视图树。系统 shell 视图是用户体验的根视图。请注意,视图树的父子关系可能与上面显示的组件层次结构不同。
协商窗口管理功能
并非所有系统 shell 实现都会提供相同的功能,因为系统 shell 在一定程度上实现了产品专用政策。因此,这些实现因产品而异。例如,智能手表可能具有非常简单的界面,一次在屏幕上显示一个视图,而桌面设备则支持具有多个重叠窗口的多个应用。一些产品支持用户通过触摸屏输入,而另一些产品则仅支持鼠标和键盘。
对于在“核心集”之外公开的产品特定功能,客户端必须能够发现当前产品支持其中哪些功能。这样,客户端就可以定制其在不同产品中的行为,并能够实现可在不同产品上运行的 fuchsia 图形应用。
同样,系统界面必须告知平台当前可用的功能。
可能的平台桥组件
平台可能会引入一个“桥接”组件,用于协调客户端应用与系统界面之间的通信。该组件类似于其他平台上的窗口管理器,然后可以自动执行某些窗口管理“机制”操作,并减少开发者编写将低级别命令发送到 Fuchsia 界面堆栈的代码的需求。这样做的好处是客户端可以针对机制和政策,与单个 API Surface 进行通信,这是其他系统(例如 Wayland)中的常见模式。通过将网桥组件放置在平台中,还可以让产品共享窗口管理代码,并避免在实现类似功能时造成重复。
关于是否使用平台桥组件/平台窗口管理器的决定留给未来的 RFC。
实现
此 RFC 说明了窗口管理的高级架构。我们预计未来 RFC 会对涉及的 API 做出重大变更,因此许多实现细节都应在这些 RFC 中解决。
实施 API 后,此 RFC 要求移除一些旧版解决方案,以解决系统当前的缺陷。具体而言:
- 此 RFC 弃用了 Element Manager(当前元素管理器功能将成为产品会话的工作)。
- 此 RFC 批准了将应用行为标准化的意图(没有更多特定于 Chrome 的解决方法)。现有 API 的替换将在未来的 RFC 中得到解决。
性能
虽然图形和用户输入处理对性能非常敏感,但窗口管理政策决策(例如,打开新应用或窗口)通常以“人类速度”进行,因此不需要与渲染或输入处理相同的性能。因此,在执行“控制”操作(如打开新窗口)时,使用额外的 RPC 通常没有问题。不过,在设计 API 时应格外小心,以确保任何对性能要求较高的流(通常是涉及数据流的流,例如将帧放在屏幕上、路由用户输入)会避免不必要的 IPC,也不会对客户端响应进行不必要的阻塞。当窗口管理器和 shell 不是同一个组件时,尤其要注意这一点。应在即将发布的 RFC 中详细解决特定 API 对性能的影响。
动画和同步
为了向用户提供顺畅的体验,请务必确保界面操作(例如调整大小的动画)可以在多个组件之间同步。虽然这主要取决于特定 API 及其对原子性保证的功能,但架构可能会影响在实现此类同步的情况下构建用户体验的难易程度。
此 RFC 未正式采用某个特定的 API,而是根据 Wayland API 评估了该 API 中包含的决策,该 API 的既定目标是让“每一帧都完美”。在最终确定此 RFC 中描述的 API 时,同步问题将是一个重要的考虑因素。
安全性和隐私权注意事项
组件安全性
此 RFC 说明组件层次结构和视图层次结构不必相同,并允许应用作为产品会话的子项而不是系统 shell(在某些系统上稳定性可能较低或安全性较低)启动。这样,产品可以更轻松地确保产品内的组件层次结构满足产品的特定安全和隐私需求。
查看安全性
视图系统 RFC 中详细介绍了视图系统的安全保证。需要注意的是,此 RFC 可以保证视图只能在其或其子项当前获得焦点时操控视图焦点,并且与视图树断开连接的视图无法接收用户输入。这意味着,产品会话安装系统界面视图和系统 shell 做出的窗口管理政策决策(例如,为已启动的应用安装子视图)也是决定哪些组件在任何给定时间有资格接收用户输入的决定。虽然平台无法保证所有产品都会实现安全行为,但视图系统提供了产品的基础组件,以打造安全的体验。
测试
该平台应提供所有窗口管理 API 的一致性测试,以便产品和应用都可以确保与 Fuchsia 平台兼容。这些测试可能会因给定应用或产品会话支持的窗口管理 API 扩展而异。
系统 shell 和应用开发者可以使用测试界面堆栈编写集成测试,以测试其代码与 Fuchsia 平台界面堆栈的交互。
文档
本 RFC 以及处理 API 细节的后续 RFC 需要对 fuchsia.dev 上的会话框架文档进行重大更新,以反映关于产品和平台之间拆分以及消除元素管理器的最新预期。
缺点、替代方案和未知情况
替代方案:Sens 视图执行窗口管理
- 如果没有新的 API,系统 shell 将不会应用产品级政策/概念。
- 不清楚如何扩展此 API 以处理产品差异。否则,会将大量特定于产品的逻辑(例如“最小化”的含义)推送到平台中。
早期技术和参考资料
-
这些 API 将在后续 RFC 中定义。 ↩