如何使用libevdev在C中生成键盘输入

6
我想编写一个应用程序来生成键盘输入(即对于系统来说,它看起来就像按下了键盘上的按钮)用于Linux系统。我想使用C语言,但xdotools不是一个选择。Libevdev看起来很有前途,但到目前为止我还没有能够让它工作。
首先,libevdev可以做到我想要的吗?大部分文档都集中在读取输入和输出上,但API确实有一个“通过uinput设备发布事件”的功能。
还有一个创建设备的示例。我修改了示例如下:
#include <stdio.h>
#include <libevdev.h>
#include <libevdev-uinput.h>

int main(int argc, char **argv)
{
    int err;
    struct libevdev *dev;
    struct libevdev_uinput *uidev;

    dev = libevdev_new();
    libevdev_set_name(dev, "fake keyboard device");

    libevdev_enable_event_type(dev, EV_KEY);
    libevdev_enable_event_code(dev, EV_KEY, KEY_A, NULL);

    err = libevdev_uinput_create_from_device(dev,
        LIBEVDEV_UINPUT_OPEN_MANAGED,
        &uidev);

    if (err != 0)
        return err;

    libevdev_uinput_write_event(uidev, EV_KEY, KEY_A, 1);
    libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);
    libevdev_uinput_write_event(uidev, EV_KEY, KEY_A, 0);
    libevdev_uinput_write_event(uidev, EV_SYN, SYN_REPORT, 0);

    libevdev_uinput_destroy(uidev);
    printf("Complete\n");
}

当我运行这个应用程序时,我没有看到任何错误(出于简洁起见,上面的代码中删除了错误处理),但我也没有看到“A”键被按下。我是做错了什么还是对这个库有错误的期望?

大多数(如果不是全部)操作系统(和桌面环境)都不允许任何程序假装成用户键盘。这将是您的程序实现特权升级的相对简单的方法。 - Steve Cox
了解。在我的环境中,程序具有必要的特权。 - GrandAdmiral
1
你可以直接使用/dev/input/dev/input/uinput设备。 (只需记住,如果一个路径不起作用,请尝试另一条路径;设备路径因发行版而异。也许可以使其可配置?)该接口已经存在很久并且非常稳定,无需担心兼容性问题。这里有一个示例程序;它是用于鼠标事件的,但是应该不难根据您的需要进行调整。 - Nominal Animal
有趣的名义动物,你的例子可行了,然后我能够通过用“i=getchar()”括起来的libevdev_uinput_write_event函数调用使我的例子工作。 我不明白为什么这样会奏效,也不知道虚拟键盘输入之前去了哪里。为什么调用getchar显然需要在命令行上看到虚假输入? - GrandAdmiral
1
啊...这只是为了延迟一段时间。睡眠100毫秒也可以。谢谢,我想我会直接使用/dev/uinput - GrandAdmiral
1个回答

4
您的代码本身没有问题,这似乎是一个时间问题。例如,如果您是在 X 中运行此代码,那么等到 X 服务器接收到 udev 事件并告知 evdev 驱动程序打开设备时,设备可能已经消失了。您应该会在 Xorg.log 中看到相关的消息。
如果您查看 libevdev 的源代码,就会发现它实际上只是一个围绕着对 /dev/uinput 写入数据的小包装器。它提供了更好的类型安全性和稍微更简单的代码。
最简单的解决方案是添加一些延迟。更复杂的解决方法是检查 X 是否正确初始化了该设备,或者至少通过 udev 检查该设备是否存在。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接