C 中的按键按下和按键释放中断

Key pressed and key released interrupts in C

有没有办法在简单的 C 程序中的 while (1) 循环中捕获 KEY PRESSEDKEY RELEASED 事件Linux 运行 来自终端机 window.

如果按下一个键,

kbhit() 将 return truegetch() return 是按下的字符。

如何捕获 RELEASE 事件?

您不能以可移植的方式执行此操作。终端(以及 xterm 等终端的模拟器)只为您提供按下的键,而不是释放事件。图形用户界面通常提供接收单独的按下和释放事件的能力。

终端仿真器 运行 在图形环境中将这些事件组合成单独的字符。在图形环境中读取时,这些是 关键符号 ,其中可能包含 个字符 。除了按键事件本身的按下和释放事件外,您还可以使用 修饰符 ,例如 shift 修饰符、控制修饰符和元修饰符,它们是单独的事件。如果你 运行 xev,你可以看到这些单独的事件。

将这些事件组合成一个字符后,终端仿真器可能会将其作为一系列数据字节发送到您的应用程序,例如,以 UTF-8 编码。当您使用 getch() 时,ncurses 库读取这些字节,并将它们再次组合成一个字符。在这两者(终端仿真器和应用程序)之间是伪终端和 its 转换,终端仿真器和应用程序都必须操作它们。

如果您 运行宁愿使用图形环境,除了图形应用程序(例如xev)之外,还有(并非总是)其他方式可以直接读取关键 press/release 事件。 Linux 控制台支持。例如,参见 Receiving key press and key release events in Linux terminal applications?

中引用的链接

这适用于我 xtermopenbox window 经理:

xinput test-xi2 --root |
  awk -v id="$(
     xwininfo -children -id "$WINDOWID" |
       awk ' == "Parent" {print }'
     )" '
   == "EVENT"{e = $NF}
   == "detail:" {k = }
   == "child" &&  == id && e ~ /Key/ {print e, k}'

输出类似:

(KeyRelease) 36
(KeyPress) 38
a(KeyRelease) 38
s(KeyPress) 39
d(KeyPress) 40
(KeyRelease) 39
(KeyRelease) 40

asdxterm 在处理这些字符时写入伪终端主端的字符的本地回显KeyPress 事件并且不是输出的一部分)。

xinput test-xi2 --root 将报告当前 $DISPLAY 的每个 X Window 事件,包括但不限于类似于以下格式的按键和按键释放事件:

EVENT type 2 (KeyPress)
    device: 14 (14)
    detail: 54
    flags:
    root: 795.06/645.66
    event: 795.06/645.66
    buttons:
    modifiers: locked 0 latched 0 base 0x4 effective: 0x4
    group: locked 0 latched 0 base 0 effective: 0
    valuators:
    windows: root 0x252 event 0x252 child 0x1c0015b

从我的有限测试中,我发现其中的 child 字段似乎与终端仿真器主 window 的父级 ID 匹配(大多数终端仿真器在 $WINDOWID 环境变量)接收这些事件。我怀疑 window id 有点属于 window 经理。

因此,在这里,我们从 xwininfo -children 命令输出中检索该 ID,并使用它来过滤 xinput.

报告的事件

要将这些键代码转换为键标签,请选中 this other answer

现在,您需要检查 xinput 的源代码或使用 ltrace(如果在 Linux 上)直接在 C 中做同样的事情而无需帮助这些公用事业。