首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

在基于 Web 的 VNC 应用程序中支持多种键盘布局-1

在基于 Web 的 VNC 应用程序中支持多种键盘布局-1

基于 Web 的  管理工具(比如  和 )可帮助用户轻松创建和管理虚拟机                (VM),甚至是从移动设备创建和管理虚拟机。这些工具依靠远程桌面共享技术,比如  (VNC),而使用 VNC 的技术需要一个基于 Web 的 VNC 客户端,比如 。
VNC 最初的目的是使物理 PC 能够从远程进行访问。因为虚拟化不是 VNC 关注的问题,所以在将 VNC 用于 VM                时,需要经过特殊处理才能解释和操作击键。Web 技术也带来了额外的挑战:Web                应用程序必须解决浏览器支持上的差异,否则仅能用于某些选定的浏览器。Web 应用程序只能通过浏览器 API 访问 PC                硬件,而桌面应用程序能够更直接地进行访问。
本文旨在帮助 JavaScript 开发人员理解和解决相关挑战,让基于 Web 的 VNC 客户端(或其他任何面临同样问题的基于 Web                的硬件模拟器)能够准确地响应从多种键盘布局生成的击键信息。我首先将解释桌面操作系统如何处理键盘信号。然后,您将学习 RFB(VNC                使用的协议)如何将击键信息从 VNC 客户端发送到 VNC 服务器,还将了解此过程在虚拟化场景中涉及到哪些问题,以及 QEMU 社区如何为桌面                VNC 客户端解决这些问题。然后,我将介绍如何使用一个相对较新的浏览器 API 为基于 Web 的 VNC 客户端实现 QEMU 解决方案。
操作系统如何处理击键键盘是一种硬件设备,对于每个按下或释放的键,它都会发送一个信号。这些信号称为扫描码,由一个或多个字节组成,用于唯一地标识按下或释放实体键的操作。
IBM 在 IBM XT 中设立了第一个扫描码标准。大部分制造商都遵循 XT 标准来确保设备与 IBM                硬件兼容。但是,扫描码不是一种容易供应用程序使用的好的键盘表示,因为不同的键盘类型可能使用不同的扫描码。举例而言,USB 键盘遵循与 XT                标准不同的扫描码标准。
键码为了使应用程序能够处理任何类型的键盘,操作系统将扫描码转换为与不依赖于键盘的键码。例如,在 PS2 键盘中按 Q,会得到与在 USB                键盘中按 Q 相同的键码。得益于从扫描码到键码的转换(键盘驱动程序 的第一个任务),应用程序不需要处理所有已知的键盘类型。
扫描码与键码之间的转换是可逆的。任何键码都可以转换回生成它的准确的硬件扫描码。例如,在标准美国 102 键键盘上按下标为 Q 的键,不会解释为                    Q 键被按下,而是解释为位于第三行第二列的键被按下
键符 (keysyms)对应用程序而言,使用键码仍不是很理想,因为根据不同的键盘布局,同一个实体键可能表示不同的符号。例如,在法国键盘中,位于第三行第二列的键是                A,不是 Q。大部分应用程序(例如文本编辑器)都希望获知用户按下了 Q,而不是按下的键在布局中的位置。
键符 (keysym) 是在考虑键盘布局图 (keymap)                后从一次或多次按键/释放键的操作生成的符号。从键码到键符的转换是操作系统执行的最后一次转换,该操作会向应用程序提供准确的键符。
图 1 演示了一个兼容 XT 的键盘将一个从美国或法国键盘布局将按键信号发送到基于 Linux 的系统的转换顺序。
图 1. 按键信号如何从键盘发送到应用程序不同于扫描码到键码的转换,从键码到键符的转换是不可逆的,原因有两个。首先,这种转换需要知道用于生成键符的键盘布局图,而且不是所有场景都可以获得此信息。其次,无法知道使用了哪种键组合来创建键符。例如,A                的键符可通过按 Shift + a 或在锁定大写时按 a 来生成。这种模糊性是 QEMU 在使用 RFB 时遇到的问题的来源。
RFB 协议、QEMU/KVM 虚拟化和 VNCRFB(远程帧缓冲区)是 VNC                用于远程访问 GUI                的协议。在该协议及其扩展协议中定义的多种                RFB 客户端到服务器消息类型中,本文关注的是 KeyEvent,也就是在按下或释放一个键时从 RFB                客户端发送到服务器的消息。图 2 显示了该消息格式。
图 2. RFB KeyEvent 客户端消息的格式
  • message-type 指定消息类型。KeyEvent 消息为类型 4。
  • down-flag 指定键的状态。如果按下该键,该值为 1;如果释放,该值为 0。
  • padding 是一个填充了 0 的 2 字节字段。
  • keysym 是按下或释放的键的键符。
当收到 KeyEvent 消息时,依据 down-flag 的值,RFB                服务器将按下或释放键时的键符复制到远程桌面中。在此消息中使用键符,是早期 QEMU 版本在用于虚拟化的 VNC                客户端/服务器上遇到设计问题的根源。
首次尝试QEMU 项目首次尝试引入 keymap 选项,以告诉 QEMU 生成键符的 VNC                    客户端中使用了哪个键盘布局图。有了此信息,QEMU                    就可以尝试从键符转换回键码;如果未指定键盘布局图,它会使用默认的美国布局。此方法不足以解决非美国键盘的 QEMU 问题。QEMU                    需要能够支持 VNC 客户端使用的任何键盘布局(针对 100 多种语言的布局),而且从上一节中我们已经知道,不同的组合键可能生成相同的键符。               

QEMU 是一个硬件模拟器。当您连接到在 QEMU 虚拟机中运行的 VNC                服务器时,服务器不会单纯地接收和显示击键;它会模拟它们,就像有人在虚拟机中的一个真实键盘上按键一样。结果,在收到 RFB                KeyEvent 消息时,QEMU 会尝试着将已发送的键转换为生成该键的 XT                扫描码。但是,KeyEvent 消息发送的是键符。QEMU 曾经面临着如何根据键符利用已按下或已释放的键来获取实际 XT                扫描码的挑战。
在 QEMU 最初尝试解决此问题失败后(参见 “首次尝试” 边栏), 和 QEMU                社区合作创建了 RFB 协议的一个官方扩展,该扩展添加了一条新的 KeyEvent 消息,其中不仅包含键符,还包含在                VNC 客户端中按下的键码。图 3 显示了该消息格式。
图 3. QEMU 扩展 KeyEvent RFB                    消息的格式
  • message-type 指定消息类型。扩展的 QEMU KeyEvent 消息为类型                    255。
  • submessage-type 有一个一字节的默认值 0。
  • down-flag 指定键的状态。如果按下该键,该值为 1;如果释放,该值为 0。
  • keysym 是已按下或释放的键的键符。
  • keycode 是生成该键符的键码。
借助额外的 keycode 信息,QEMU 可将键码转换回扫描码并进行模拟。此能力还使 VNC 服务器不知道 VNC                客户端使用了哪个键盘布局图。只要客户端的键盘布局图与来宾操作系统(在虚拟机中运行的操作系统)中配置的键盘布局图相同,键盘就会按预期工作。
返回列表