Прямой ввод в Linux

Для достижения максимально быстрого ввода событий от клавиатуры и мыши следует исключить промежуточные абстракции в виде XOrg или Wayland сервера. В Linux есть библиотека - обертка для работы с ядром libevdev (посредством файлов /dev/input/event*).

Приведенный ниже пример открывает файл устройства ввода (на моей машине мышью оказался event7), проверяет наличие относительных осей и наличие левой кнопки мыши. Затем выводит на экран события с устройства.

Пример пришлось адаптировать под машину, и скорректировать имена функций libevdev_get_event_type_name и libevdev_get_event_code_name. Концепт работает, устройство ввода считывается напрямую и очень быстро. Лучший вариант для Linux в качестве способа ввода.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
 
#include <libevdev-1.0/libevdev/libevdev.h>
 
int main() {
    struct libevdev *dev = NULL;
    int fd;
    int rc = 1;
    fd = open("/dev/input/event7", O_RDONLY|O_NONBLOCK);
    rc = libevdev_new_from_fd(fd, &dev);
    if (rc < 0) {
            fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
            exit(1);
    }
    printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
    printf("Input device ID: bus %#x vendor %#x product %#x\n",
           libevdev_get_id_bustype(dev),
           libevdev_get_id_vendor(dev),
           libevdev_get_id_product(dev));
    if (!libevdev_has_event_type(dev, EV_REL) ||
        !libevdev_has_event_code(dev, EV_KEY, BTN_LEFT)) {
            printf("This device does not look like a mouse\n");
            exit(1);
    }
    do {
            struct input_event ev;
            rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
            if (rc == 0)
                    printf("Event: %s %s %d\n",
                           libevdev_event_type_get_name(ev.type),
                           libevdev_event_code_get_name(ev.type, ev.code),
                           ev.value);
    } while (rc == 1 || rc == 0 || rc == -EAGAIN);
    return 0;
}
 

2018-10-29