入门
在 Firefox OS 中,通过硬件按键输入事件的行为在不同的应用程序之间存在很大差异。早期的智能手机只配备了少量按键——电源、主页、音量加、音量减——因此软件很容易为每个按键事件确定适当的响应。但是,现在的智能电视遥控器配备了多种硬件按键,在按下按键时定义适当的行为已成为 Firefox OS TV 平台上的一个重要问题。如果智能遥控器上的硬件按键可以同时由应用程序和系统使用,那么确定按下按键时触发哪个响应就非常重要。
本文将介绍在 Firefox OS 智能电视平台上,对电视遥控器进行编程以管理键盘事件所面临的挑战。我们将把键盘事件划分为四种场景,并描述这些派发场景以及它们的交互方式。这是关于 Firefox OS 智能电视键盘事件的两篇文章中的第一篇。在后续的 第二篇文章 中,我们将深入研究实现细节,并查看在电视遥控器上进行事件处理的示例代码。
我们从电视遥控器上的“信息”按键开始。通常,硬件使用它来显示系统信息,虽然应用程序可以使用同一个按键来显示应用程序信息。当用户按下此按键时,屏幕上将显示哪个操作——系统信息还是应用程序信息?四种键盘事件场景
为了确定按下硬件按键时的适当行为,我们首先描述键盘事件的四种场景。
场景 | 描述 | 事件顺序 |
---|---|---|
SYSTEM-ONLY | 仅供 mozbrowser-iframe-host-page 处理的按键。 | system |
SYSTEM-FIRST | 可以先由 mozbrowser-iframe-host-page 处理,然后也可以由 mozbrowser-iframe-embedded-page 处理的按键。 | system->app |
APP-CANCELLED | 仅供 mozbrowser-iframe-embedded-page 处理的按键。 | app |
APP-FIRST | 可以先由 mozbrowser-iframe-embedded-page 处理,然后也可以由 mozbrowser-iframe-host-page 处理的按键。 | app->system |
[表 1]
表 1 中提到的 mozbrowser-iframe-host-page 和 mozbrowser-iframe-embedded-page 在上面的图 2 中进行了说明。如果 A.html 代表一个源代码为 B.html 的主机页面,那么 A.html 就是 mozbrowser-iframe-host-page,B.html 就是 mozbrowser-iframe-embedded-page。mozbrowser
使用非标准的 Firefox 浏览器 API,它专为在 Firefox OS 应用程序中实现关键功能和内容体验而构建。了解更多关于 MDN 上的 mozbrowser 的信息。
任何给定键盘事件的适当响应取决于场景。在上面说明的例子中,假设“信息”键盘事件被归类为 APP-FIRST,并且系统设置的默认操作是显示系统信息。因此,当我们在应用程序 Z 处于前台的情况下按下“信息”键时,会有两种可能的结果
- 如果应用程序 Z 有一个事件处理程序,指示“信息”键显示应用程序信息,那么当用户按下遥控器上的“信息”键时,将显示应用程序信息。
- 如果应用程序 Z 没有为“信息”键设置事件处理程序,则将触发默认操作。也就是说,屏幕将显示系统信息。
如何实现四种场景
为了实现上面描述的四种键盘事件场景,我们引入了四个新的键盘事件
mozbrowserbeforekeydown
– 在 keydown 事件 之前 触发mozbrowserafterkeydown
– 在 keydown 事件 之后 触发mozbrowserbeforekeyup
– 在 keyup 事件 之前 触发mozbrowserafterkeyup
– 在 keyup 事件 之后 触发
这四个键盘事件只会被嵌入 mozbrowser-iframe 的 window 接收。
键盘事件按照特定的时间顺序发生:mozbrowserbeforekeydown
、mozbrowserafterkeydown
、mozbrowserbeforekeyup
、keyup
、mozbrowserafterkeyup
。
这为开发者提供了一种方法来实现上面提到的四种场景。从概念上讲,可以分别通过为 mozbrowserbeforekey*
和 mozbrowserafterkey*
事件设置适当的处理程序来实现 SYSTEM-ONLY、SYSTEM-FIRST 和 APP-CANCELLED、APP-FIRST 场景。SYSTEM-ONLY 和 SYSTEM-FIRST 场景可以通过为 mozbrowserbeforekey*
事件设置适当的处理程序来实现,而 APP-CANCELLED 和 APP-FIRST 场景则可以通过 mozbrowserafterkey*
事件来实现。
Firefox OS 中的 iframe 结构
为了理解如何实现这四种场景,让我们首先看一下 Firefox OS 中的 iframe 结构。Firefox OS 中最外层的 iframe 是 shell.html。它嵌入了一个来自 system/index.html 的 进程内 iframe。系统应用程序 (system/index.html) 包含多个 Web 应用程序(本质上是 iframe),它们可以是 进程内 (remote=”false”) 或 进程外 (remote=”true”)。因此,这三层之间的关系可以用下表表示mozbrowser iframe 主机页面 | mozbrowser iframe 嵌入页面 |
---|---|
shell.html | system/index.html |
system/index.html | Web 应用程序(本质上是 iframe) |
[表 2]
键盘事件的派发顺序
当一个 keydown 事件被发送到 mozbrowser-iframe-embedded-page 中的某个元素时,嵌入 iframe 的所有者,即 mozbrowser-iframe-host-page,将在 keydown 事件发送之前收到mozbrowserbeforekeydown
事件,并在事件发送到 mozbrowser-iframe-embedded-page 之后收到 mozbrowserafterkeydown
事件。
在 Gecko 中,一旦有一个目标在 HTML 文档中嵌入的进程外 iframe 中的 keydown 事件,keydown 事件就会复制到 HTML 文档中。此复制事件的目标被设置为嵌入的 iframe 元素。
这导致了图 4 中所示的键盘事件序列。它说明了当需要派发目标在 mozbrowser-iframe-embedded-page 中的 keydown 事件时,所有相关的 keydown 事件及其关系。简而言之,事件按照以下顺序执行
- 在派发任何 keydown 事件之前,
mozbrowserbeforekeydown
事件首先派发到 mozbrowser-iframe-host-page 的窗口。 - 然后,原始的 keydown 事件(目标在 mozbrowser-iframe-embedded-page 中)将被复制到 mozbrowser-iframe-host-page HTML 文档中。它的目标将被设置为包含 mozbrowser-iframe-embedded-page 的 iframe。
- 接下来,原始的 keydown 事件将被派发到它的目标。
- 在原始的 keydown 事件派发完成后,
mozbrowserafterkeydown
事件将被派发到 mozbrowser-iframe-host-page 的窗口。
请注意,上面描述的事件派发过程遵循 DOM 树事件流。事件序列和事件目标可以整理到下表中
顺序 | 事件 | 目标 |
---|---|---|
1 | mozbrowserbeforekeydown | mozbrowser-iframe-host-page 中的窗口 |
2 | keydown | mozbrowser-iframe-host-page 中包含 mozbrowser-iframe-embedded-page 的 iframe |
3 | keydown | mozbrowser-iframe-embedded-page 中的原始事件 |
4 | mozbrowserafterkeydown | mozbrowser-iframe-host-page 中的窗口 |
[表 3]
键盘事件mozbrowserbeforekeydown
、keydown
和 mozbrowserafterkeydown
可以扩展到嵌套的 mozbrowser iframe,例如表 2 中描述的 Firefox OS 中的 iframe 结构。在这种情况下,mozbrowserbeforekeydown
和 mozbrowserafterkeydown
事件将被派发到最里面的 mozbrowser-iframe-host-page 以及最外面的那个。因此,在 Firefox OS 中,mozbrowserkeydown
和 mozbrowserafterkeydown
将被派发到 system/index.html 的窗口和 shell.html 的窗口。图 5 说明了当一个 keydown 事件被派发到一个 Web 应用程序时,所有相关事件的整个派发顺序。事件顺序在表 4 中进行了演示。
顺序 | 事件 | 目标 |
---|---|---|
1 | mozbrowserbeforekeydown | shell.html 中的窗口 |
2 | mozbrowserbeforekeydown | system/index.html 中的窗口 |
3 | keydown | system/index.html 中包含 Web 应用程序的 iframe |
4 | keydown | Web 应用程序中的原始事件 |
5 | mozbrowserafterkeydown | system/index.html 中的窗口 |
6 | mozbrowserafterkeydown | shell.html 中的窗口 |
[表 4]
虽然 keyup 事件必须在 keydown 事件之后触发,但 keydown 事件和 keyup 事件是相互独立的。此外,路径mozbrowserbeforekeyup
、keyup
、mozbrowserafterkeyup
与路径 mozbrowserbeforekeydown
、keydown
、mozbrowserafterkeydown
是相互独立的。因此,这两个路径可能交叉。mozbrowserbeforekeyup
可能会在 keydown 事件之前到达。
在 Firefox OS 中,大多数应用程序都是 进程外 运行的。这意味着应用程序在自己的进程中运行,而不是在主进程中运行。在将给定的 key* 事件(副本)派发到系统应用程序之后,需要时间才能将原始的 key* 事件发送到 mozbrowser-iframe-embedded-page 所在的进程。同样,在将给定的 key* 事件派发到 mozbrowser-iframe-embedded-page 的进程之后,还需要时间才能将 mozbrowserafterkey*
发送回 mozbrowser-iframe-host-page 所在的进程。
因此,mozbrowserbeforekeyup
事件可能会在 keydown 事件被派发到应用程序自己的进程之前到达 Firefox OS 主进程(系统应用程序所在的进程)。上面图 6 中演示了 key* 事件顺序的常见结果。黄色系列表示 keydown 路径,蓝色系列表示 keyup 路径。没错,这两个路径可能会交叉。
下一步
如果您正在寻找我们描述的四种场景的实现细节,以及事件处理程序示例代码,以帮助您实现智能电视遥控器的键盘事件,请密切关注 后续文章,并随时关注即将在 MDN 上发布的更完整的文档。
一条评论