You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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语言示例)

  1. 安装依赖:Debian/Ubuntu执行sudo apt install libinput-dev,Fedora执行sudo dnf install libinput-devel。
  2. 初始化libinput上下文:通过libinput_udev_create_context创建上下文,绑定udev设备管理器。
  3. 添加目标设备:指定监听/dev/input/event1。
  4. 循环处理事件:调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:35:16