GTK 4 中的无障碍功能

上周 GTK 3.99.3 版本发布的最大新闻是我们为新的无障碍功能实现提供了第一个重要的后端。因此,现在是深入了解 GTK 4 中无障碍功能的好时机。

概述

让我们先快速回顾一下无障碍功能在 Linux 上的工作原理。其中的参与者是应用程序和辅助技术 (AT),例如屏幕阅读器(例如,Orca)、放大镜等。

AT 的目的通常是为用户提供与应用程序交互的替代方式,这些方式是根据他们的需求量身定制的(例如,放大的视图、大声朗读的文本或语音命令)。为此,AT 需要有关应用程序 UI 的大量详细信息,而这正是无障碍功能堆栈发挥作用的地方——它是应用程序(或其工具包)和 AT 之间的连接层。

应用程序和 AT 通过无障碍总线相互通信,这是一个单独的 D-Bus 会话总线实例,使用 AT-SPI 项目描述的接口。应用程序的 UI 元素在总线上表示为实现了一些抽象接口的对象,例如 TextValue。应用程序发出信号来传达 UI 中的变化,并且 AT 可以调用对象上的方法来获取信息或进行更改(例如,更改 Value 接口的当前值以移动它表示的 GtkScale)。

发生了什么变化

在 GTK 2 和 3 中,这是以一种笨拙的间接方式完成的:GTK 小部件具有辅助的可访问对象,这些对象是 ATK 接口的实现(转换 1:GTK ➙ ATK)。然后,这些对象在 at-spi2-atk 中的适配器代码中转换为 AT-SPI 对象(转换 2:ATK ➙ AT-SPI),并在无障碍总线上表示。另一方面,AT 然后使用 pyatspi 将 AT-SPI 接口转换为 Python 对象(转换 3:AT-SPI ➙ Python)。

这个多步骤的过程效率低下、有损且难以维护;它需要至少在三个组件上实现相同的功能,并且导致记录的 AT-SPI 方法和属性与实际通过无障碍总线发送的方法和属性之间存在差异。

在 GTK 4 中,我们通过删除 ATK 和 at-spi2-atk 来简化应用程序端。小部件现在实现了一个 GtkAccessible 接口,该接口允许它们设置许多角色、状态、属性和关系,这些角色、状态、属性和关系或多或少直接取自 W3C 发布的 WAI-ARIA 规范。GTK 无障碍 API 的 AT-SPI 后端然后采用这些受 ARIA 启发的属性(以及小部件本身的知识),并将小部件表示为无障碍总线上的对象,为它们实现相关的 AT-SPI 接口。

这是一种更直接的方法,并且与 Qt 和 Web 浏览器已经做的事情相匹配。

应用程序 API

以下是您在应用程序中使用 GTK 4 时最有可能遇到的无障碍 API 的重点

设置可访问的角色。 角色是对小部件语义的描述,AT 将使用它来决定应向其用户呈现哪种行为。设置角色是一次性操作,这意味着它必须在小部件创建时完成,无论是在 class_init 中,还是在实例初始化期间

gtk_widget_class_set_accessible_role (widget_class,  
                                      GTK_ACCESSIBLE_ROLE_BUTTON);

更新小部件的可访问状态或属性。 只要小部件的可访问表示发生更改,就应该执行此操作

gtk_accessible_update_property (GTK_ACCESSIBLE (widget),
                       GTK_ACCESSIBLE_PROPERTY_VALUE_MIN, minimum,
                       GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, value,
                       GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, maximum,
                       -1);

GTK 参考文档对无障碍 API 进行了概述,其中包括针对应用程序开发人员和小部件编写者的指导。

下一步是什么?

对于 GTK 4.0,我们专注于完成 AT-SPI 后端。但是,借助新的 API 和后端分离,我们有了为其他平台制作无障碍后端的明确途径,这是我们希望在后续 GTK 4 版本中研究的。

在 Linux 上,我们希望与其他利益相关者合作,对 AT-SPI 接口进行现代化改造,以最终克服某些地方仍然可见的 CORBA 遗留问题。其中一部分是将从无障碍总线转向应用程序和 AT 之间的对等连接;这将增强无障碍功能堆栈的安全性,并填补 Flatpak 等技术使用的沙盒中的漏洞。

将来,我们希望引入工具来确保应用程序开发人员了解缺少无障碍注释的情况,例如为 UI 中的图标和图像提供标签属性或 labelled-by 关系;或确保每个 UI 元素都正确地表示在可访问树中。我们已经为 GtkAccessible 接口提供了一个测试后端,该后端可用于编写单元测试并验证在必要时是否更新了角色和属性。

GTK Hackfest 2020 — 路线图和无障碍功能

在 1 月 28 日至 1 月 31 日期间,GTK 团队在布鲁塞尔举办了第三届 hackfest

黑客马拉松的主要议题

  • GTK4 下一个开发快照的计划
  • 阻碍 GTK 4.0 发布的缺失功能
  • 工具包中无障碍功能支持的当前状态

前两个项目占据了黑客马拉松前两天的大部分时间;您可以阅读 GTK 3.98 发布公告,了解自 3.96 发布以来的过去 300 天里我们一直在做的事情。缺失的功能是

  • 键盘快捷键的事件控制器
  • Wayland 上的可移动弹出窗口
  • 行回收列表和网格视图
  • 动画 API

所有这些都在主题分支中进行。键盘快捷键分支最近已重新基于,并且正在进行文档编制和清理;可移动弹出窗口在几次迭代后也正在审查中。最后剩下的两个分支相当大,需要进行更多的迭代才能使其正确——动画 API 目前主要是一个原型。

黑客马拉松的最后一个主题是最大的,并且是早就应该进行的讨论。

GTK 的无障碍功能支持是作为 Sun 无障碍功能团队的 GTK 2.0 版本的一部分添加的;它依赖于 ATK(无障碍工具包)提供的抽象数据类型,这些数据类型在 GTK 类(如 GtkWidgetAccessibleGtkEntryAccessible)中具体实现。每个小部件都有一个与之关联的“可访问”对象,该对象要么由 GTK 自动创建,要么在子类化 GTK 小部件时由应用程序代码提供。非小部件类型也可以具有与之关联的可访问对象——最值得注意的情况是树视图和组合框的单元格渲染器集。最底层是 AT-SPI,这是一种 AT(可访问技术,如屏幕阅读器)用来使用应用程序提供的数据的协议。通常,AT 将使用像 libatspi 这样的库来处理协议本身。

现有堆栈的主要问题是

  • ATK 的存在导致了很多间接性;任何新功能或错误修复都需要在 ATK 内部定义,然后实现到 GTK 和 libatspi 中
  • ATK 是在非常不同的环境中编写的,虽然它已经过几次弃用,但它在其所做的假设(如全局坐标空间)和设计中显示出其时代性
  • AT 要求和 GUI 测试要求之间存在一定的重叠,最终会在 API 设计中产生摩擦
  • 自从 Sun 无障碍功能团队解散以来,该堆栈已经失修;大部分正在进行的工作仍然主要发生在 AT 领域(如 Orca)和 Web 浏览器中
  • 整个堆栈是在 CORBA 盛行时编写的,然后及时移植到 GNOME3 中的 DBus;但是,该协议并不是很有效,并且需要大量的往返才能移动少量数据,而不是进行批量操作和通知

最后一点也是我们需要单独的无障碍总线的原因,以避免垃圾邮件发送会话总线,并在启用无障碍功能支持后使一切变慢。单独的总线意味着我们需要在任何沙盒中打开一个额外的漏洞,并且仍然让连接到无障碍总线的任何东西都有可能窥探每个应用程序中发生的事情。

最后,GTK 仅支持 Linux 上的无障碍功能;不支持 macOS 或 Windows,这意味着用 GTK 编写并移植到其他平台的应用程序在那里无法被 AT 访问。当我们在 API 中公开 ATK 时,在其他平台上添加对无障碍功能的支持将需要桥接 ATK,从而创建进一步的复杂性。

由于我们希望重新设计和更新 GTK4 中的无障碍功能,我们需要了解无障碍功能堆栈现有消费者的要求是什么,以及我们需要针对哪种用例。为此,我们邀请了 Hypra,这是一家致力于开发基于自由和开源软件的无障碍解决方案的公司,来帮助我们。

Hypra 开发人员熟悉 GNOME,并且一直在研究 Linux 无障碍功能堆栈。他们的客户涵盖了广泛的无障碍功能用户,因此他们最适合描述日常实际使用的 AT 类型。

从工具包到合成器,堆栈的不同层必须提供各种各样的工具和功能;应用程序开发人员还必须能够访问必要的工具,以便为 AT 提供适当的支持,因为他们比工具包更了解他们的应用程序应该是什么样子以及如何运行。

在两天的时间里,我们确定了一个前进的计划

  • 从堆栈中删除 ATK,并让 GTK 直接与 AT-SPI 协议对话;这类似于 Qt 从工具包端所做的事情,并且可以更容易地扩展和验证最终的协议更改
  • 清理 AT-SPI 协议本身,在需要时更新它,以便更有效地使用 DBus
  • 放弃全局辅助功能总线,让辅助技术 (AT) 与每个应用程序协商建立点对点连接
  • 让辅助技术 (AT) 向合成器请求收集全局状态,例如快捷键,而不是与应用程序对话,因为应用程序随后必须向窗口系统请求(如果可能),否则在无法获取时返回无效数据
  • 将 GUI 测试与辅助功能解耦
  • 为应用程序开发人员编写小部件和应用程序创作指南,并提供可作为构建和 CI 流程一部分的验证工具,以检查 UI 元素是否具有正确的辅助功能描述和链接

有关笔记和路线图的更多信息,请访问维基,我们已经安排了今年夏季的额外检查点会议。

有很多工作要做,但现在我们对这种重新设计的工作范围和交付成果有了更清晰的认识。如果您想帮助加速事情的发生,请随时加入这项工作;您也可以向 GNOME 基金会捐款。

GTK 团队感谢 GNOME 基金会赞助场地和与会者,以及 Hypra 的优秀员工参加黑客马拉松,解释用例和当前辅助功能堆栈的状态,并在开发方面提供帮助。