C

时间:2015-11-06 10:07:55

标签: keyboard c interrupt events

有没有办法在从终端窗口运行的Linux上的简单C程序中捕获while (1)循环中的 KEY PRESSED KEY RELEASED 事件。 / p> 如果按下某个键,

kbhit()将返回truegetch()将返回按下的字符。

如何捕获RELEASE事件?

2 个答案:

答案 0 :(得分:3)

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

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

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

如果你在图形环境中运行,除了xev之类的图形应用程序之外,还有(并非总是)其他方式可以直接读取按键/释放事件。 Linux控制台支持这一点。例如,请参阅 Receiving key press and key release events in Linux terminal applications?

中引用的链接

答案 1 :(得分:1)

这适用于我xtermopenbox窗口管理器:

xinput test-xi2 --root |
  awk -v id="$(
     xwininfo -children -id "$WINDOWID" |
       awk '$1 == "Parent" {print $4}'
     )" '
  $1 == "EVENT"{e = $NF}
  $1 == "detail:" {k = $2}
  $6 == "child" && $7 == 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字段似乎与终端仿真器主窗口的父级的id匹配(大多数终端仿真器在$WINDOWID环境变量中可用)接收这些事件。我怀疑窗口ID有点属于窗口管理器。

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

要将这些键码转换为键标签,请检查this other answer

现在,您需要检查xinput的源代码或使用ltrace(如果在Linux上)使用,直接在C中执行相同的操作,而无需这些实用程序的帮助。