#include #include #include #include #include #include #include #include #include #include #include #define SCALE 1 struct abs_range { int x_min; int x_max; int x_range; int y_min; int y_max; int y_range; }; int click_mouse(Display *dpy, struct input_event *ev) { int btn; if (ev->code == BTN_LEFT) { btn = 1; } else if (ev->code == BTN_RIGHT) { btn = 2; } else { return 1; } if (ev->value < 2) { XTestFakeButtonEvent(dpy, btn, ev->value, CurrentTime); } } int move_mouse(Display *dpy, float posx, float posy, int screenw, int screenh) { float x, y; x = (screenw * posx) * SCALE; y = (screenh * posy) * SCALE; //x = ((screenw * posx) - (screenw*0.3)) * SCALE; //y = ((screenh * posy) - (screenh*0.1)) * SCALE; Window root = DefaultRootWindow(dpy); XWarpPointer(dpy, None, root, 0, 0, 0, 0, x, y); XFlush(dpy); } int handle_event(struct input_event *ev, Display *dpy, struct abs_range abs_range, float *posx, float *posy, int sw, int sh) { if (ev->type == EV_ABS) { if (ev->code == ABS_X) { *posx = (float) (ev->value - abs_range.x_min) / abs_range.x_range; } else if (ev->code == ABS_Y) { *posy = (float) (ev->value - abs_range.y_min) / abs_range.y_range; } } else if (ev->type == EV_KEY) { click_mouse(dpy, ev); } move_mouse(dpy, *posx, *posy, sw, sh); return 0; } Display *get_resolution(int *width, int *height) { Display *dpy; int snum; if(!(dpy = XOpenDisplay(0))) fprintf(stderr, "cannot open display '%s'", XDisplayName(0)); snum = DefaultScreen(dpy); *width = DisplayWidth(dpy, snum); *height = DisplayHeight(dpy, snum); printf("screen is %dx%d\n", *width, *height); return dpy; } XDevice *get_trackpad(Display *dpy) { XDevice *device; XDeviceInfo *devices; Atom touchpad_type = 0; touchpad_type = XInternAtom(dpy, XI_TOUCHPAD, True); int ndevices = 50; devices = XListInputDevices(dpy, &ndevices); while (ndevices--) { if (devices[ndevices].type == touchpad_type) { device = XOpenDevice(dpy, devices[ndevices].id); if (!device) { fprintf(stderr, "Failed to open device '%s'.\n", devices[ndevices].name); break; } printf("Opened device '%s'.\n", devices[ndevices].name); } } XFreeDeviceList(devices); return device; } char *get_event_device(Display *dpy, XDevice *device) { int rc, i; Atom prop; Atom realtype; int realformat; unsigned long nitems, bytes_after; unsigned char *data; prop = XInternAtom (dpy, "Device Node", 0); rc = XGetDeviceProperty(dpy, device, prop, 0, // offset 5, // number of items 0, // false AnyPropertyType, &realtype, &realformat, &nitems, &bytes_after, &data); if (rc != Success) { fprintf(stderr, "Failed to read property '%s'\n", "Device Node"); } return data; } int main() { Display *dpy; XDevice *device; unsigned char *node; struct libevdev *dev; struct input_event ev; struct abs_range abs_range; float posx, posy; int sw, sh; int fd, rc; dpy = get_resolution(&sw, &sh); device = get_trackpad(dpy); node = get_event_device(dpy, device); printf("Reading device from %s\n", node); fd = open(node, O_RDONLY|O_NONBLOCK); if (fd < 0) fprintf(stderr, "error: %d %s\n", errno, strerror(errno)); rc = libevdev_new_from_fd(fd, &dev); if (rc < 0) fprintf(stderr, "error: %d %s\n", -rc, strerror(-rc)); abs_range.x_min = libevdev_get_abs_minimum(dev, ABS_X); abs_range.x_max = libevdev_get_abs_maximum(dev, ABS_X); abs_range.y_min = libevdev_get_abs_minimum(dev, ABS_Y); abs_range.y_max = libevdev_get_abs_maximum(dev, ABS_Y); abs_range.x_range = abs_range.x_max - abs_range.x_min; abs_range.y_range = abs_range.y_max - abs_range.y_min; do { struct input_event ev; rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL|LIBEVDEV_READ_FLAG_BLOCKING, &ev); if (rc == LIBEVDEV_READ_STATUS_SYNC) { // this is not needed since we dont really care about catching up with missed events //while (rc == LIBEVDEV_READ_STATUS_SYNC) { //handle_event(&ev, dpy, abs_range, &posx, &posy, sw, sh); //rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_SYNC, &ev); //} } else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) { handle_event(&ev, dpy, abs_range, &posx, &posy, sw, sh); } } while (rc == LIBEVDEV_READ_STATUS_SYNC || rc == LIBEVDEV_READ_STATUS_SUCCESS || rc == -EAGAIN); ; return 0; }