Linux键盘输入记录-键盘映射翻译

Linux键盘输入记录-键盘映射翻译

我正在编写一个监视 Linux 上输入事件的类。它将用在一个守护进程中,该守护进程根据用户在 GUI 程序中的按键操作,在 USB LED 设备上提供视觉反馈。

我使用从 /dev/input/event* 读取的输入事件。我正在使用<linux/input.h>并获得了密钥代码。

我使用的是比利时键盘。我按下并释放键盘上的“A”键,我的日志当前显示:

29/09/2019 - 14:14:48.751 [Info] Event: time 1569759288.751445, type 4 (Misc), code 4 (ScanCode), value 0x10
29/09/2019 - 14:14:48.751 [Info] Event: time 1569759288.751445, type 1 (Key), code 16 (Q), value 1
29/09/2019 - 14:14:48.751 [Info] Event: time 1569759288.751445, -------------- Report Sync ------------
29/09/2019 - 14:14:48.792 [Info] Event: time 1569759288.792115, type 4 (Misc), code 4 (ScanCode), value 0x10
29/09/2019 - 14:14:48.792 [Info] Event: time 1569759288.792115, type 1 (Key), code 16 (Q), value 0
29/09/2019 - 14:14:48.792 [Info] Event: time 1569759288.792115, -------------- Report Sync ------------

在没有任何修饰键的情况下,实际在屏幕上打印的是一个小“a”

请注意“代码 16 (Q)” - 数字 16 是基于 10 的键码。

我现在需要将“Q”映射到我的键盘布局,在本例中它应该记录“a”。为此,我使用 dumpkeys 程序来获取内核的当前转换表。

就这个具体示例而言,它输出的缩短数据(仅显示 4 列)为:

keycode  16 = +a               +A               at               VoidSymbol

或者更合适的格式:

keycode  16 = +0x0b61          +0x0b41          0x0040           0x0200 

+ 表示默认情况下可移动。在这个阶段,我不确定这是否是我需要考虑的事情,所以我删除了它。

据我了解,dumpkeys 程序将 0xb00 添加到正确的数字,因此,我删除 +,从 0x0b61 中减去 0x0b00 以获得 0x0061。

0x0061 是“a”的 unicode 编号 U+0061,我将该 QString 存储在位置 0 的向量中,因此,就转储键而言,第一列。

现在针对问题:

有些按键是可以的。如果我解释具有字符“1”“&”“|”的物理密钥的数据在我的键盘上,这一切都通过修饰键进行检查。

但对于这个例子(物理钥匙只带有大写“A”),这是不行的。

根据 keymaps(5) - Linux 手册页中解释的修饰符规则,应该发生以下情况:

我在没有任何修饰键的情况下按下键码 16,然后得到 U+0061 或“a”-> ok - 操作编号零(来自第一列)

我用 Shift 修饰键按下键码 16,得到 U+0041 或“A” -> 确定,因为 Shift 修饰键的权重为 1,所以第一个操作(来自第二列)

我用 AltGr 修饰键按下键码 16,得到 U+0040 或“@” -> 好的,AltGr 权重 2 - 所以第二个操作(来自第三列)

现在,如果我同时按下键码 16 和 Shift 和 AltGr,则重量加起来为 3,因此第三个操作(从第 4 列开始)又名 VoidSymbol,因此不会发生任何情况。我得到的是一个大写的欧米茄“Ω”。为什么?

至于那个 VoidSymbol,U+0200 实际上是 ş(带有双坟墓的拉丁文大写字母 a)。如果将 unicode 值用作 VoidSymbol,如何打印该字符?

还有其他问题。

另一个例子是上面有“§”、“6”、“^”的物理钥匙。键盘映射转储键给我没有“§”字符(U+00A7)的痕迹。不过,我还能打字……

默认情况下可移动是怎么回事?

编辑:附加问题

#define modifierShift 1;    //why the difference between ShiftL and ShiftR -> there is no 'shift' key
#define modifierControl 4;  //why the difference between ControlL and ControlR -> there is no 'control' key
#define modifierShiftL 16;  //code 42
#define modifierShiftR 32;  //code 54
#define modifierCtrlL 64;   //code 29
#define modifierCtrlR 128;  //code 97

有人可以帮我澄清一下吗?

答案1

Linux 使用两组键盘映射。一个在内核输入层级别工作,并将键码分配给扫描码。您可以用来loadkeys更改此映射。这就是您在 中看到的evtest

另一种工作在 X 服务器级别。 X 有(除其他外)一个通用evdev驱动程序,它从内核输入层收集输入事件,然后将这些事件映射到所谓的键符号。这就是您在 中看到的xev。您可以xmodmap使用 xkbd 扩展以更通用的方式修改它。

因此,如果您的用户不使用 X,您有两种选择:对按键的扫描码进行操作(即按键在键盘上的位置,因此您可以实现自己的按键映射),或者对翻译后的按键进行操作在内核中,并指导您的用户使用loadkeys等来加载他们选择的键盘映射。

两种方法都是“可靠的”,但语义却截然不同。

相关内容