4.7. 键盘

编写:Ove K鍁en

(提取自 wine/documentation/keyboard)

现在 Wine 需要知道你的键盘布局(layout)。这个要求来自一些应用程序的需求,它们需要获得正确的键盘扫描码,原因是它们直接读取这些扫描码,而不是接受从 X 服务器返回的字符。这意味着 Wine 现在需要有一个从 X 键到这些程序所需要的扫描码的映射。

在启动的时候,Wine 尝试着识别活跃的 X 布局,方法是查看它是否匹配任何定义的表。如果是,所有的事情都正常。如果不是,你需要定义它。

要想定义它,打开文件 windows/x11drv/keyboard.c 并查看现存的表。复制它做为一个备份,特别是在你不是使用 CVS 的时候。

你实际上需要做的是找出每个键需要生成的那个扫描码。在 main_key_scan 表中查看,它看起来如下:

static const int main_key_scan[MAIN_LEN] =
{
/* 这是我的 (102-键) 键盘布局,如果不匹配你的键盘是很遗憾的 */
   0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
   0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
   0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
   0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
   0x56 /* 第 102 个键(实际上在 l-shift 的右边) */
};
static const char main_key_US_phantom[MAIN_LEN][4] =
{
 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
 "<>" /* 幽灵键 */
};      

接着,把印在按键上的字符赋予每个扫描码。这为 US 101 键键盘(的次序)做的。它可以在 keyboard.c 的顶部找到。它还显示了如果没有第 102 键,你可以跳过它。

但是,对于多数国际化的 102 键键盘,我们使它易于你的使用。这些键盘的扫描码布局已经非常匹配在 main_key_scan 中的物理键盘布局了,所以你要做的所有事情就是完成在你主键盘上生成字符的所有的键(除了空格键之外),并把它们组织到一个适当的表中。只有第 102 个键是个例外,它通常在最后一行的第一个字符的左边(通常是 Z),它必须放到在最后一行之后的单独一行中。

例如,我的挪威(Norwegian)键盘看起来如下

? !  "  #  ? %  &  /  (  )  =  ?  `  Back-
|  1  2@ 3?4$ 5  6  7{ 8[ 9] 0} +  \?space

Tab Q  W  E  R  T  Y  U  I  O  P  ? ^
                                     ▇
                                        Enter
Caps A  S  D  F  G  H  J  K  L  ? ? *
Lock                                  '

Sh- > Z  X  C  V  B  N  M  ;  :  _  Shift
ift <                      ,  .  -

Ctrl  Alt       Spacebar       AltGr  Ctrl
      

注意第 102 个键,它是 <> 键,在 Z 的左边。在主字符右侧的那个字符是由 AltGr 键生成的字符。

定义这个键盘如下:

static const char main_key_NO[MAIN_LEN][4] =
{
 "|?,"1!","2\"@","3#?,"4?","5%","6&","7/{","8([","9)]","0=}","+?","\\?,
 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","迮","╚~",
 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","","嫫","'*",
 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
 "<>"
};   
      

除了 " 和 \ 需要用反斜杠引用起来,和第 102 个键在单独的一行之外,它是非常直接的。

你写完了一个这样的表之后,你需要把它添加到 main_key_tab[] 布局索引表中。这看起来如下:

static struct {
 WORD lang, ansi_codepage, oem_codepage;
 const char (*key)[MAIN_LEN][4];
} main_key_tab[]={
...
...
 {MAKELANGID(LANG_NORWEGIAN,SUBLANG_DEFAULT),  1252, 865, &main_key_NO},  
...
      

在你增加了这个表之后,重新编译 Wine 并测试它的工作。如果检测你的表失败,尝试运行

wine --debugmsg +key,+keyboard >& key.log
      

并查看结果的 key.log 文件来找到关于你的布局的错误消息。

注意 LANG_*SUBLANG_* 定义在 include/winnls.h 中,你可能需要用它找出给你的语言分配的编号,并在调试消息输出中找到它。这个编号是(SUBLANG * 0x400 + LANG),所以,例如 LANG_NORWEGIAN (0x14)SUBLANG_DEFAULT (0x1) 的组合将是 (十六进制的) 14 + 1*400 = 414,因为我是挪威人,我将在调试消息输出中查找 0414 以便找出为什么不能检测到我的键盘。

一旦它工作了,请提交到 Wine 计划。如果你使用 CVS,你需要在你的主 Wine 目录中做

cvs -z3 diff -u windows/x11drv/keyboard.c > layout.diff
      

,接着把 layout.diff 提交到 并加上关于它是什么的一个简要的说明。

如果你不使用 CVS,你需要做

diff -u the_backup_file_you_made windows/x11drv/keyboard.c > layout.diff
      

并按上面解说的那样提交。

如果你做的正确,它将被包括到下一次 Wine 发行中,而所有使用扫描码的有问题的应用程序(尤其是远程控制应用程序)和游戏将荣幸的使用你键盘布局,并且你将不再得到这些闹心的 fixme 消息了。

祝你好运。