diff --git a/src/vkbd.h b/src/vkbd.h index cdecb45..f1d38cc 100644 --- a/src/vkbd.h +++ b/src/vkbd.h @@ -5,10 +5,10 @@ struct vkbd; -struct vkbd *vkbd_init(const char *name); -void vkbd_send(const struct vkbd *vkbd, uint16_t code, int state); -void vkbd_move_mouse(const struct vkbd *vkbd, int x, int y); +struct vkbd *vkbd_init(const char *name); +void vkbd_send(const struct vkbd *vkbd, uint16_t code, int state); +void vkbd_move_mouse(const struct vkbd *vkbd, int x, int y); -void free_vkbd(struct vkbd *vkbd); +void free_vkbd(struct vkbd *vkbd); #endif diff --git a/src/vkbd/uinput.c b/src/vkbd/uinput.c index b510f49..55fbab2 100644 --- a/src/vkbd/uinput.c +++ b/src/vkbd/uinput.c @@ -10,34 +10,72 @@ struct vkbd { int fd; + int pfd; }; -static int create_virtual_keyboard(const char *name) +static int create_virtual_pointer(const char *name) { - size_t i; + uint16_t code; struct uinput_setup usetup; int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); if (fd < 0) { - perror("open uinput"); + perror("open"); exit(-1); } - ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_EVBIT, EV_REL); + ioctl(fd, UI_SET_EVBIT, EV_KEY); ioctl(fd, UI_SET_EVBIT, EV_SYN); - for (i = 0; i < KEY_MAX; i++) { - if (keycode_table[i].name) - ioctl(fd, UI_SET_KEYBIT, i); - } - ioctl(fd, UI_SET_RELBIT, REL_X); ioctl(fd, UI_SET_RELBIT, REL_WHEEL); ioctl(fd, UI_SET_RELBIT, REL_HWHEEL); ioctl(fd, UI_SET_RELBIT, REL_Y); ioctl(fd, UI_SET_RELBIT, REL_Z); + for (code = BTN_LEFT; code <= BTN_TASK; code++) + ioctl(fd, UI_SET_KEYBIT, code); + + for (code = BTN_0; code <= BTN_9; code++) + ioctl(fd, UI_SET_KEYBIT, code); + + memset(&usetup, 0, sizeof(usetup)); + usetup.id.bustype = BUS_USB; + usetup.id.product = 0x1FAC; + usetup.id.vendor = 0x0ADE; + strcpy(usetup.name, name); + + ioctl(fd, UI_DEV_SETUP, &usetup); + ioctl(fd, UI_DEV_CREATE); + + return fd; +} + +static int create_virtual_keyboard(const char *name) +{ + size_t code; + struct uinput_setup usetup; + + int fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (fd < 0) { + perror("open uinput"); + exit(-1); + } + + ioctl(fd, UI_SET_EVBIT, EV_KEY); + ioctl(fd, UI_SET_EVBIT, EV_REL); + ioctl(fd, UI_SET_EVBIT, EV_SYN); + + for (code = 0; code < KEY_MAX; code++) { + /* skip mouse buttons to prevent X from identifying the virtual device as a mouse */ + if (((code) >= BTN_LEFT && (code) <= BTN_TASK) || + ((code) >= BTN_0 && (code) <= BTN_9)) + continue; + + if (keycode_table[code].name) + ioctl(fd, UI_SET_KEYBIT, code); + } memset(&usetup, 0, sizeof(usetup)); usetup.id.bustype = BUS_USB; @@ -56,6 +94,15 @@ struct vkbd *vkbd_init(const char *name) struct vkbd *vkbd = calloc(1, sizeof vkbd); vkbd->fd = create_virtual_keyboard(name); + /* + * lazily initialize the virtual pointer to avoid presenting an + * external mouse if it is unnecessary. This can cause issues higher + * up the input stack (e.g libinput touchpad disabling in the presence + * of an external mouse) + */ + + vkbd->pfd = 0; + return vkbd; } @@ -63,6 +110,10 @@ void vkbd_move_mouse(const struct vkbd *vkbd, int x, int y) { struct input_event ev; + if (!vkbd->pfd) { + ((struct vkbd *)vkbd)->pfd = create_virtual_pointer("keyd virtual pointer"); + } + if (x) { ev.type = EV_REL; ev.code = REL_X; @@ -71,7 +122,7 @@ void vkbd_move_mouse(const struct vkbd *vkbd, int x, int y) ev.time.tv_sec = 0; ev.time.tv_usec = 0; - write(vkbd->fd, &ev, sizeof(ev)); + write(vkbd->pfd, &ev, sizeof(ev)); } if (y) { @@ -82,14 +133,14 @@ void vkbd_move_mouse(const struct vkbd *vkbd, int x, int y) ev.time.tv_sec = 0; ev.time.tv_usec = 0; - write(vkbd->fd, &ev, sizeof(ev)); + write(vkbd->pfd, &ev, sizeof(ev)); } ev.type = EV_SYN; ev.code = 0; ev.value = 0; - write(vkbd->fd, &ev, sizeof(ev)); + write(vkbd->pfd, &ev, sizeof(ev)); } void vkbd_send(const struct vkbd *vkbd, uint16_t code, int state)