Reintroduce dedicated virtual pointer

Reverse the consolidation of keyd events into a single virtual
device since this still causes problems with xinput. Instead
we now lazily initialize the pointer on an as-needed basis
to minimize interference with things which behave differently
in the presence of an external pointer (e.g libinput touchpad
disabling).
master
Raheman Vaiya 4 years ago
parent 40012a44a6
commit 88c8475741
  1. 8
      src/vkbd.h
  2. 75
      src/vkbd/uinput.c

@ -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

@ -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)

Loading…
Cancel
Save