【问题标题】:Linux: Canceling input from /dev/input/event*Linux:取消来自 /dev/input/event* 的输入
【发布时间】:2021-10-13 05:25:07
【问题描述】:

在我一直在开发的程序中,我想独立于我关注的任何窗口读取键盘击键(因此,无论我关注的是 Firefox 还是玩 Minecraft,相同的程序都可以工作,无需改变焦点)。到目前为止,使用 linux/input.h 库并从 /dev/input/event5 读取似乎工作得很好。

fd = open(argv[1], O_RDONLY);
struct input_event ev;
int len = read(fd, &ev, sizeof(struct input_event));

但是,我想添加的一项功能是在程序运行时取消此输入,以防止我的击键到达 Firefox 或 Minecraft 或通用操作系统。有什么好办法吗?

【问题讨论】:

  • 这是XY problem? 破坏操作系统是一个非常激进的解决方案。
  • 可能是。我已经四处寻找一种解决方案,它可以让我捕获键盘输入而不依赖于专用窗口成为焦点,并且仅捕获原始输入事件似乎是最简单的。我确实尝试了 pynput 模块,但这往往会导致我的桌面环境在安装时随机崩溃,所以我自己滚动。
  • 理想情况下,不会取消所有键盘输入,只需输入我认为对我的程序有用的输入(几乎只是字母/数字键、空格和回车/esc 键,我用来关闭程序)。此外,程序只会在触发时运行(此时,通过自动键热键),因此操作系统会在最短的时间内瘫痪。
  • 在 Windows API 中,我使用SetWindowsHookEx() 来查看键盘事件,但没有试图干扰它们。好吧,不在那里,我已经生成了事件,就好像它们来自带有SendInput() 的键盘,但它们转到具有焦点的进程(也可以被操纵)。
  • 不过,根据rediculousanddirtyprogramming,如果您真的想要,SetWindowsHookEx 可以 用于此目的。不幸的是,我使用的是 Linux(尽管如果我想将我的应用程序移植到 Windows,这可能很有用)。

标签: c linux input keyboard


【解决方案1】:

警告:未经测试

  • 以 O_RDWR(读/写)模式打开字符设备
  • 抓取设备:ioctl(fd, EVIOCGRAB, 1)
  • 读取事件
  • 如果你想调度事件:
    • 取消抓取设备 ioctl(fd, EVIOCGRAB, 0)
    • 写事件

在取消抓取和写入之间,可能会发生其他事件,这些事件不会过滤并分派到所有连接的文件句柄。不知道能不能先写后不抓(或者干脆不写,查看write的返回值)。

提示:您也可以修改libevdev

【讨论】:

  • 这实际上工作得很好。不过要记住两件事:1. 在抓取之前暂停程序一秒钟是必不可少的 (sleep(1);)。否则,用于触发程序的任何击键(即终端环境中的回车键)都不会将其“键向上”调用发送到操作系统,从而导致无休止的重复击键流。 2.我们可以使用ioctl调用的返回码来保证一次只运行一个程序实例,低于0就退出。结合以上,应该可以防止产生无限多的进程。
猜你喜欢
  • 2014-09-20
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2012-05-02
相关资源
最近更新 更多