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