gvalkov / python-evdev

Python bindings for the Linux input subsystem
https://python-evdev.rtfd.org/
BSD 3-Clause "New" or "Revised" License
336 stars 112 forks source link

evdev not working for Wayland #200

Open rkmax opened 1 year ago

rkmax commented 1 year ago

We are using evdev in a project, and while we tested Ubuntu 23, we notice that. UInput is not working at all when is running Wayland. using X11 works correctly

SO: Ubuntu 23.04 kernel: Linux ubuntu2304 6.2.0-35-generic

This is the image we are using https://www.linuxvmimages.com/images/ubuntu-2304/

Here's a sample script that we tried

from evdev import UInput, ecodes as e
import time

ui = UInput(name='uinput-sample', vendor=0x1, product=0x1, version=1)
# we tried this also
# ui = UInput()

time.sleep(2)

print("Simulating key press and release...")

ui.write(e.EV_KEY, e.KEY_A, 1)
ui.syn()

ui.write(e.EV_KEY, e.KEY_A, 0)
ui.syn()

time.sleep(2)

ui.close()

image

We also tested the following C script

#define _GNU_SOURCE
#include <fcntl.h>
#include <linux/uinput.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// Initialize uinput device
int init_uinput_device() {
    int fd = open("/dev/uinput", O_RDWR | O_NONBLOCK);
    if (fd < 0) {
        perror("open /dev/uinput");
        return -1;
    }

    ioctl(fd, UI_SET_EVBIT, EV_KEY);
    ioctl(fd, UI_SET_KEYBIT, KEY_A);

    struct uinput_setup usetup;
    memset(&usetup, 0, sizeof(usetup));
    snprintf(usetup.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
    usetup.id.bustype = BUS_USB;
    usetup.id.vendor = 0x1;
    usetup.id.product = 0x1;
    usetup.id.version = 1;

    if (ioctl(fd, UI_DEV_SETUP, &usetup)) {
        perror("UI_DEV_SETUP");
        return -1;
    }

    if (ioctl(fd, UI_DEV_CREATE)) {
        perror("UI_DEV_CREATE");
        return -1;
    }

    return fd;
}

// Emit events
void emit(int fd, int type, int code, int val) {
    struct input_event ie;
    ie.type = type;
    ie.code = code;
    ie.value = val;
    ie.time.tv_sec = 0;
    ie.time.tv_usec = 0;

    write(fd, &ie, sizeof(ie));
}

int main() {
    int fd = init_uinput_device();
    if (fd < 0) {
        fprintf(stderr, "Could not initialize uinput device.\n");
        exit(EXIT_FAILURE);
    }

    sleep(2);

    printf("Simulating key press and release...\n");

    emit(fd, EV_KEY, KEY_A, 1);
    emit(fd, EV_SYN, SYN_REPORT, 0);

    emit(fd, EV_KEY, KEY_A, 0);
    emit(fd, EV_SYN, SYN_REPORT, 0);

    sleep(2);

    ioctl(fd, UI_DEV_DESTROY);
    close(fd);

    return 0;
}

image