Skip to content

Commit

Permalink
Reintroduce dedicated virtual pointer
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
rvaiya committed Feb 11, 2022
1 parent 40012a4 commit 88c8475
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 16 deletions.
8 changes: 4 additions & 4 deletions src/vkbd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
75 changes: 63 additions & 12 deletions src/vkbd/uinput.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -56,13 +94,26 @@ 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;
}

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;
Expand All @@ -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) {
Expand All @@ -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)
Expand Down

0 comments on commit 88c8475

Please sign in to comment.