Linux下如何用Wayland及C/C++读取/dev/input/event1?无需创建surfaces
可行方法及实现步骤
方法一:直接读取/dev/input/event1(无需Wayland)
这是最直接的实现方式,无需依赖Wayland相关库,直接通过Linux输入子系统API读取设备文件。
实现步骤(C语言示例)
- 打开设备文件:调用
open("/dev/input/event1", O_RDONLY),注意需要足够权限(比如将用户加入input组,或使用sudo)。 - 循环读取事件结构体:读取
struct input_event(定义在<linux/input.h>),该结构体包含事件类型(如EV_KEY、EV_REL)、按键/轴代码(如KEY_A)和事件值(按下/释放/重复等状态)。 - 解析并处理事件:根据事件类型和代码做对应逻辑处理。
代码片段
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <linux/input.h> int main() { int fd = open("/dev/input/event1", O_RDONLY); if (fd == -1) { perror("Failed to open device"); return 1; } struct input_event ev; while (read(fd, &ev, sizeof(ev)) == sizeof(ev)) { if (ev.type == EV_KEY) { printf("Key event: code=%d, value=%d\n", ev.code, ev.value); // 0=释放, 1=按下, 2=重复 } } close(fd); return 0; }
注意事项
- 权限问题:普通用户默认无访问权限,可执行
sudo usermod -aG input $USER将用户加入input组,重启后生效。 - 设备匹配:可用
ls /dev/input/查看所有event设备,或通过cat /proc/bus/input/devices确认目标设备对应的event节点。
方法二:使用Wayland生态的libinput库(无需创建Wayland Surface)
libinput是Wayland合成器标配的输入处理库,可独立于Wayland客户端环境直接访问输入设备,无需创建Surface,同时提供手势识别、触摸点跟踪等高级功能。
实现步骤(C语言示例)
- 安装依赖:Debian/Ubuntu执行
sudo apt install libinput-dev,Fedora执行sudo dnf install libinput-devel。 - 初始化libinput上下文:通过
libinput_udev_create_context创建上下文,绑定udev设备管理器。 - 添加目标设备:指定监听
/dev/input/event1。 - 循环处理事件:调用
libinput_dispatch获取事件,解析后处理。
代码片段
#include <libinput.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> static int open_restricted(const char *path, int flags, void *user_data) { int fd = open(path, flags); return fd < 0 ? -errno : fd; } static void close_restricted(int fd, void *user_data) { close(fd); } const struct libinput_interface interface = { .open_restricted = open_restricted, .close_restricted = close_restricted, }; int main() { struct libinput *li = libinput_udev_create_context(&interface, NULL, NULL); if (!li) { fprintf(stderr, "Failed to create libinput context\n"); return 1; } if (libinput_udev_add_device(li, "/dev/input/event1") != 0) { fprintf(stderr, "Failed to add device\n"); libinput_unref(li); return 1; } while (1) { libinput_dispatch(li); struct libinput_event *ev; while ((ev = libinput_get_event(li))) { struct libinput_event_keyboard *key_ev = libinput_event_get_keyboard_event(ev); if (key_ev) { printf("Key: code=%d, state=%d\n", libinput_event_keyboard_get_key(key_ev), libinput_event_keyboard_get_key_state(key_ev)); } libinput_event_destroy(ev); } usleep(10000); // 避免忙等 } libinput_unref(li); return 0; }
编译命令
gcc -o read_input read_input.c -linput
注意事项
- 同样需要input组权限,否则libinput无法访问设备。
- libinput会自动处理设备热插拔、事件过滤等逻辑,比直接读设备文件更健壮。
关于Wayland客户端直接读取输入的说明
Wayland协议采用客户端-合成器架构,客户端的输入事件由合成器转发,无法通过Wayland API直接读取/dev/input设备——因为Wayland设计上由合成器独占输入设备,客户端仅能接收合成器转发的事件,且必须绑定Surface才能获取这些事件,不符合你无需创建Surface的需求。因此优先推荐上述两种方法。
内容的提问来源于stack exchange,提问作者Moltenpowa
相关产品推荐
相关产品推荐

