3 #include <X11/extensions/XTest.h>
 
   9 #define STATUS_LEFT 0x01
 
  10 #define STATUS_RIGHT 0x02
 
  11 #define STATUS_UP 0x04
 
  12 #define STATUS_DOWN 0x08
 
  13 #define STATUS_MOVING 0xF
 
  14 #define STATUS_TAPJUMP 0x100
 
  15 #define STATUS_RUNNING 0x80000000
 
  17 #define MIN(a,b) ({int __a = (a), __b = (b); (__a < __b) ? __a : __b; })
 
  18 #define MAX(a,b) ({int __a = (a), __b = (b); (__a > __b) ? __a : __b; })
 
  20 unsigned long long now()
 
  23         gettimeofday(&tv, NULL);
 
  24         return tv.tv_sec*1000000 + tv.tv_usec;
 
  33         char key = 0, lastkey = 0;
 
  34         unsigned long long lasttime = 0;
 
  38         dpy = XOpenDisplay(NULL);
 
  41                 printf("Display open failed; bailing out\n");
 
  45         if (!XTestQueryExtension(dpy, &dmy, &dmy, &dmy, &dmy))
 
  47                 printf("XTest NOT supported\n");
 
  51         printf("Grabbing keyboard...\n");
 
  52         XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), Mod1Mask, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync);
 
  56                 while (XCheckMaskEvent(dpy, 0xFFFFFFFF, &ev))
 
  63                                 XKeyEvent *ke = (XKeyEvent*)&ev;
 
  64                                 char *keystr = XKeysymToString(XKeycodeToKeysym(dpy, ke->keycode, 0));
 
  65                                 //printf("Key %s: %s\n", ev.type == KeyPress ? "PRESS  " : "RELEASE", keystr);
 
  67                                 if (!strcmp(keystr, "grave")) {
 
  68                                         if (ev.type == KeyPress)
 
  70                                                 XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), AnyModifier, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync);
 
  72                                                 status |= STATUS_RUNNING;
 
  74                                                 XUngrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), AnyModifier, RootWindow(dpy, DefaultScreen(dpy)));
 
  75                                                 XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), Mod1Mask, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync);
 
  77                                                 status &= ~STATUS_RUNNING;
 
  79                                 } else if (!strcmp(keystr, "u")) 
 
  80                                         XTestFakeButtonEvent(dpy, 1, ev.type == KeyPress, 0);
 
  81                                 else if (!strcmp(keystr, "o"))
 
  82                                         XTestFakeButtonEvent(dpy, 3, ev.type == KeyPress, 0);
 
  83                                 else if (!strcmp(keystr, "apostrophe") || !strcmp(keystr, "semicolon")) {
 
  84                                         if (ev.type == KeyPress)
 
  85                                                 status |= STATUS_TAPJUMP;
 
  87                                                 status &= ~STATUS_TAPJUMP;
 
  89                                 } else if (!strcmp(keystr, "j")) {
 
  90                                         if (ev.type == KeyPress)
 
  92                                                 status |= STATUS_LEFT;
 
  93                                                 if ((lastkey == 'j') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP))
 
  94                                                         XTestFakeRelativeMotionEvent(dpy, -100.0 * pow(repeats++, 0.8), 0, 0);
 
  96                                                 status &= ~STATUS_LEFT;
 
  97                                 } else if (!strcmp(keystr, "l")) {
 
  98                                         if (ev.type == KeyPress)
 
 100                                                 status |= STATUS_RIGHT;
 
 101                                                 if ((lastkey == 'l') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP))
 
 102                                                         XTestFakeRelativeMotionEvent(dpy, 100.0 * pow(repeats++, 0.8), 0, 0);
 
 104                                                 status &= ~STATUS_RIGHT;
 
 105                                 } else if (!strcmp(keystr, "i")) {
 
 106                                         if (ev.type == KeyPress)
 
 109                                                 if ((lastkey == 'i') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP))
 
 110                                                         XTestFakeRelativeMotionEvent(dpy, 0, -100.0 * pow(repeats++, 0.8), 0);
 
 112                                                 status &= ~STATUS_UP;
 
 113                                 } else if (!strcmp(keystr, "k")) {
 
 114                                         if (ev.type == KeyPress)
 
 116                                                 status |= STATUS_DOWN;
 
 117                                                 if (lastkey == 'k' && (now() - lasttime) < 250000 && (status & STATUS_TAPJUMP))
 
 118                                                         XTestFakeRelativeMotionEvent(dpy, 0, 100.0 * pow(repeats++, 0.8), 0);
 
 120                                                 status &= ~STATUS_DOWN;
 
 122                                 if (strlen(keystr) == 1 && ev.type == KeyPress)
 
 126                                 } else if (ev.type == KeyPress) {
 
 133                                 printf("NFI what %d is\n", ev.type);
 
 136                 if (!(status & STATUS_RUNNING))
 
 138                 if (!(status & STATUS_MOVING))  // if we haven't anything to do, don't sit and suck up cycles
 
 140                         XPeekEvent(dpy, &ev);
 
 143                 usleep(20000 - MIN(MAX(pow(13 * (now() - starttime), 0.6), 0), 18000));
 
 144                 if (now() - lasttime > 250000)
 
 146                 if (status & STATUS_LEFT)
 
 147                         XTestFakeRelativeMotionEvent(dpy, -2, 0, 0);
 
 148                 if (status & STATUS_RIGHT)
 
 149                         XTestFakeRelativeMotionEvent(dpy, 2, 0, 0);
 
 150                 if (status & STATUS_UP)
 
 151                         XTestFakeRelativeMotionEvent(dpy, 0, -2, 0);
 
 152                 if (status & STATUS_DOWN)
 
 153                         XTestFakeRelativeMotionEvent(dpy, 0, 2, 0);