From 2c1bb55db744f80d1cdce172ced413bbf5e9eee5 Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Fri, 20 Jun 2008 15:13:58 -0400 Subject: [PATCH] initial import of xvmouse --- Makefile | 2 + xvmouse.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 Makefile create mode 100644 xvmouse.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..965ee6a --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +xvmouse: xvmouse.c + gcc -o xvmouse xvmouse.c -lm -lX11 /usr/lib/libXtst.so.6 diff --git a/xvmouse.c b/xvmouse.c new file mode 100644 index 0000000..44e94d9 --- /dev/null +++ b/xvmouse.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include +#include +#include + +#define STATUS_LEFT 0x01 +#define STATUS_RIGHT 0x02 +#define STATUS_UP 0x04 +#define STATUS_DOWN 0x08 +#define STATUS_MOVING 0xF +#define STATUS_TAPJUMP 0x100 +#define STATUS_RUNNING 0x80000000 + +#define MIN(a,b) ({int __a = (a), __b = (b); (__a < __b) ? __a : __b; }) +#define MAX(a,b) ({int __a = (a), __b = (b); (__a > __b) ? __a : __b; }) + +unsigned long long now() +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec*1000000 + tv.tv_usec; +} + +void main() +{ + int e; + XEvent ev; + Display *dpy; + int status = 0, dmy; + char key = 0, lastkey = 0; + unsigned long long lasttime = 0; + int repeats = 1; + int starttime = 0; + + dpy = XOpenDisplay(NULL); + if (!dpy) + { + printf("Display open failed; bailing out\n"); + exit(1); + } + + if (!XTestQueryExtension(dpy, &dmy, &dmy, &dmy, &dmy)) + { + printf("XTest NOT supported\n"); + exit(1); + } + + printf("Grabbing keyboard...\n"); + XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), Mod1Mask, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync); + + while (1) + { + while (XCheckMaskEvent(dpy, 0xFFFFFFFF, &ev)) + { + switch (ev.type) + { + case KeyPress: + case KeyRelease: + { + XKeyEvent *ke = (XKeyEvent*)&ev; + char *keystr = XKeysymToString(XKeycodeToKeysym(dpy, ke->keycode, 0)); + //printf("Key %s: %s\n", ev.type == KeyPress ? "PRESS " : "RELEASE", keystr); + + if (!strcmp(keystr, "grave")) { + if (ev.type == KeyPress) + { + XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), AnyModifier, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync); + XAutoRepeatOff(dpy); + status |= STATUS_RUNNING; + } else { + XUngrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), AnyModifier, RootWindow(dpy, DefaultScreen(dpy))); + XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), Mod1Mask, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync); + XAutoRepeatOn(dpy); + status &= ~STATUS_RUNNING; + } + } else if (!strcmp(keystr, "u")) + XTestFakeButtonEvent(dpy, 1, ev.type == KeyPress, 0); + else if (!strcmp(keystr, "o")) + XTestFakeButtonEvent(dpy, 3, ev.type == KeyPress, 0); + else if (!strcmp(keystr, "apostrophe") || !strcmp(keystr, "semicolon")) { + if (ev.type == KeyPress) + status |= STATUS_TAPJUMP; + else + status &= ~STATUS_TAPJUMP; + repeats = 1; + } else if (!strcmp(keystr, "j")) { + if (ev.type == KeyPress) + { + status |= STATUS_LEFT; + if ((lastkey == 'j') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP)) + XTestFakeRelativeMotionEvent(dpy, -100.0 * pow(repeats++, 0.8), 0, 0); + } else + status &= ~STATUS_LEFT; + } else if (!strcmp(keystr, "l")) { + if (ev.type == KeyPress) + { + status |= STATUS_RIGHT; + if ((lastkey == 'l') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP)) + XTestFakeRelativeMotionEvent(dpy, 100.0 * pow(repeats++, 0.8), 0, 0); + } else + status &= ~STATUS_RIGHT; + } else if (!strcmp(keystr, "i")) { + if (ev.type == KeyPress) + { + status |= STATUS_UP; + if ((lastkey == 'i') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP)) + XTestFakeRelativeMotionEvent(dpy, 0, -100.0 * pow(repeats++, 0.8), 0); + } else + status &= ~STATUS_UP; + } else if (!strcmp(keystr, "k")) { + if (ev.type == KeyPress) + { + status |= STATUS_DOWN; + if (lastkey == 'k' && (now() - lasttime) < 250000 && (status & STATUS_TAPJUMP)) + XTestFakeRelativeMotionEvent(dpy, 0, 100.0 * pow(repeats++, 0.8), 0); + } else + status &= ~STATUS_DOWN; + } + if (strlen(keystr) == 1 && ev.type == KeyPress) + { + lastkey = keystr[0]; + lasttime = now(); + } else if (ev.type == KeyPress) { + lastkey = 0; + repeats = 0; + } + break; + } + default: + printf("NFI what %d is\n", ev.type); + } + } + if (!(status & STATUS_RUNNING)) + status = 0; + if (!(status & STATUS_MOVING)) // if we haven't anything to do, don't sit and suck up cycles + { + XPeekEvent(dpy, &ev); + starttime = now(); + } + usleep(20000 - MIN(MAX(pow(13 * (now() - starttime), 0.6), 0), 18000)); + if (now() - lasttime > 250000) + repeats = 1; + if (status & STATUS_LEFT) + XTestFakeRelativeMotionEvent(dpy, -2, 0, 0); + if (status & STATUS_RIGHT) + XTestFakeRelativeMotionEvent(dpy, 2, 0, 0); + if (status & STATUS_UP) + XTestFakeRelativeMotionEvent(dpy, 0, -2, 0); + if (status & STATUS_DOWN) + XTestFakeRelativeMotionEvent(dpy, 0, 2, 0); + } + + + exit(0); +} \ No newline at end of file -- 2.39.2