mouse: Add support for mice which use absolute positioning (e.g trackpads)

master
Raheman Vaiya 4 years ago
parent e749310df4
commit bf63568d72
  1. 71
      src/device.c
  2. 19
      src/device.h
  3. 10
      src/keyd.c
  4. 31
      src/vkbd/uinput.c

@ -45,7 +45,7 @@
* corresponding device should be considered invalid by the caller.
*/
static uint8_t resolve_device_type(int fd)
static uint8_t resolve_device_capabilities(int fd)
{
const uint32_t keyboard_mask = 1<<KEY_1 | 1<<KEY_2 | 1<<KEY_3 |
1<<KEY_4 | 1<<KEY_5 | 1<<KEY_6 |
@ -56,7 +56,8 @@ static uint8_t resolve_device_type(int fd)
uint32_t mask[BTN_LEFT/32+1] = {0};
uint8_t has_rel;
uint8_t type = 0;
uint8_t has_abs;
uint8_t capabilities = 0;
if (ioctl(fd, EVIOCGBIT(EV_KEY, (BTN_LEFT/32+1)*4), mask) < 0) {
perror("ioctl");
@ -68,36 +69,62 @@ static uint8_t resolve_device_type(int fd)
return 0;
}
if (has_rel)
type |= DEVT_MOUSE;
if (ioctl(fd, EVIOCGBIT(EV_ABS, 1), &has_abs) < 0) {
perror("ioctl");
return 0;
}
if (has_rel || has_abs)
capabilities |= CAP_MOUSE;
if (has_abs)
capabilities |= CAP_MOUSE_ABS;
if ((mask[0] & keyboard_mask) == keyboard_mask)
type |= DEVT_KEYBOARD;
capabilities |= CAP_KEYBOARD;
return type;
return capabilities;
}
static int device_init(const char *path, struct device *dev)
{
int fd;
int type;
int capabilities;
struct input_absinfo absinfo;
if ((fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC, 0600)) < 0) {
fprintf(stderr, "failed to open %s\n", path);
return -1;
}
type = resolve_device_type(fd);
capabilities = resolve_device_capabilities(fd);
if (ioctl(fd, EVIOCGNAME(sizeof(dev->name)), dev->name) == -1) {
perror("ioctl EVIOCGNAME");
return -1;
}
dbg2("device type of %s (%s): %x", path, dev->name, type);
if (capabilities & CAP_MOUSE_ABS) {
if (ioctl(fd, EVIOCGABS(ABS_X), &absinfo) < 0) {
perror("ioctl");
return 0;
}
dev->_minx = absinfo.minimum;
dev->_maxx = absinfo.maximum;
if (ioctl(fd, EVIOCGABS(ABS_Y), &absinfo) < 0) {
perror("ioctl");
return 0;
}
dev->_miny = absinfo.minimum;
dev->_maxy = absinfo.maximum;
}
dbg2("capabilities of %s (%s): %x", path, dev->name, capabilities);
if (type) {
if (capabilities) {
struct input_id info;
if (ioctl(fd, EVIOCGID, &info) == -1) {
@ -109,7 +136,7 @@ static int device_init(const char *path, struct device *dev)
dev->path[sizeof(dev->path)-1] = 0;
dev->fd = fd;
dev->type = type;
dev->capabilities = capabilities;
dev->vendor_id = info.vendor;
dev->product_id = info.product;
@ -347,6 +374,26 @@ struct device_event *device_read_event(struct device *dev)
return NULL;
}
break;
case EV_ABS:
switch (ev.code) {
case ABS_X:
devev.type = DEV_MOUSE_MOVE_ABS;
devev.x = (ev.value * 1024) / (dev->_maxx - dev->_minx);
devev.y = 0;
break;
case ABS_Y:
devev.type = DEV_MOUSE_MOVE_ABS;
devev.y = (ev.value * 1024) / (dev->_maxy - dev->_miny);
devev.x = 0;
break;
default:
fprintf(stderr, "Unrecognized EV_ABS code: %d\n", ev.code);
break;
}
break;
case EV_KEY:
/* Ignore repeat events */
@ -386,6 +433,8 @@ struct device_event *device_read_event(struct device *dev)
break;
default:
if (ev.type)
dbg2("unrecognized evdev event type: %d %d %d", ev.type, ev.code, ev.value);
return NULL;
}

@ -13,8 +13,15 @@
#define DEV_KEY 2
#define DEV_REMOVED 3
#define DEVT_MOUSE 0x1
#define DEVT_KEYBOARD 0x2
/*
* All absolute values are relative to a resolution
* of 1024x1024
*/
#define DEV_MOUSE_MOVE_ABS 4
#define CAP_MOUSE 0x1
#define CAP_MOUSE_ABS 0x2
#define CAP_KEYBOARD 0x4
#define MAX_DEVICES 64
@ -25,12 +32,18 @@ struct device {
*/
int fd;
uint8_t type;
uint8_t capabilities;
uint16_t product_id;
uint16_t vendor_id;
char name[64];
char path[256];
/* Internal. */
uint32_t _maxx;
uint32_t _maxy;
uint32_t _minx;
uint32_t _miny;
/* Reserved for the user. */
void *data;
};

@ -118,7 +118,7 @@ static void daemon_add_cb(struct device *dev)
* between these two, so we take a permissive approach and leave it up to
* the user to blacklist mice which emit key events.
*/
if (!exact_match && !(dev->type & DEVT_KEYBOARD)) {
if (!exact_match && !(dev->capabilities & CAP_KEYBOARD)) {
dbg("Ignoring %s (not a keyboard)", dev->name);
return;
}
@ -188,7 +188,7 @@ static int daemon_event_cb(struct device *dev, struct device_event *ev)
panic_check(code, pressed);
if (dev->type & DEVT_KEYBOARD)
if (dev->capabilities & CAP_KEYBOARD)
active_kbd = kbd;
dbg2("Processing %04x:%04x (%s): %s %s",
@ -215,6 +215,9 @@ static int daemon_event_cb(struct device *dev, struct device_event *ev)
case DEV_MOUSE_MOVE:
vkbd_mouse_move(vkbd, ev->x, ev->y);
break;
case DEV_MOUSE_MOVE_ABS:
vkbd_mouse_move_abs(vkbd, ev->x, ev->y);
break;
}
return 0;
@ -277,6 +280,9 @@ static int monitor_event_cb(struct device *dev, struct device_event *ev)
case DEV_MOUSE_MOVE:
dbg("%s: move %d %d", dev->name, ev->x, ev->y);
break;
case DEV_MOUSE_MOVE_ABS:
dbg("%s: move abs %d %d", dev->name, ev->x, ev->y);
break;
case DEV_MOUSE_SCROLL:
dbg("%s: scroll %d %d", dev->name, ev->x, ev->y);
break;

@ -197,8 +197,9 @@ void write_key_event(const struct vkbd *vkbd, uint8_t code, int state)
* to prevent X from identifying the virtual
* keyboard as a mouse.
*/
if (is_btn)
if (is_btn) {
fd = vkbd->pfd;
}
ev.value = state;
@ -319,23 +320,27 @@ void vkbd_mouse_move_abs(const struct vkbd *vkbd, int x, int y)
{
struct input_event ev;
ev.type = EV_ABS;
ev.code = ABS_X;
ev.value = x;
if (x) {
ev.type = EV_ABS;
ev.code = ABS_X;
ev.value = x;
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
write(vkbd->pfd, &ev, sizeof(ev));
write(vkbd->pfd, &ev, sizeof(ev));
}
ev.type = EV_ABS;
ev.code = ABS_Y;
ev.value = y;
if (y) {
ev.type = EV_ABS;
ev.code = ABS_Y;
ev.value = y;
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
write(vkbd->pfd, &ev, sizeof(ev));
write(vkbd->pfd, &ev, sizeof(ev));
}
ev.type = EV_SYN;
ev.code = 0;

Loading…
Cancel
Save