initial import of xvmouse
[xvmouse.git] / xvmouse.c
1 #include <X11/Xlib.h>
2 #include <math.h>
3 #include <X11/extensions/XTest.h>
4 #include <stdio.h>
5 #include <signal.h>
6 #include <sys/time.h>
7 #include <time.h>
8
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
16
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; })
19
20 unsigned long long now()
21 {
22         struct timeval tv;
23         gettimeofday(&tv, NULL);
24         return tv.tv_sec*1000000 + tv.tv_usec;
25 }
26
27 void main()
28 {
29         int e;
30         XEvent ev;
31         Display *dpy;
32         int status = 0, dmy;
33         char key = 0, lastkey = 0;
34         unsigned long long lasttime = 0;
35         int repeats = 1;
36         int starttime = 0;
37         
38         dpy = XOpenDisplay(NULL);
39         if (!dpy)
40         {
41                 printf("Display open failed; bailing out\n");
42                 exit(1);
43         }
44         
45         if (!XTestQueryExtension(dpy, &dmy, &dmy, &dmy, &dmy))
46         {
47                 printf("XTest NOT supported\n");
48                 exit(1);
49         }
50         
51         printf("Grabbing keyboard...\n");
52         XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), Mod1Mask, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync);
53         
54         while (1)
55         {
56                 while (XCheckMaskEvent(dpy, 0xFFFFFFFF, &ev))
57                 {
58                         switch (ev.type)
59                         {
60                         case KeyPress:
61                         case KeyRelease:
62                         {
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);
66                                 
67                                 if (!strcmp(keystr, "grave")) {
68                                         if (ev.type == KeyPress)
69                                         {
70                                                 XGrabKey(dpy, XKeysymToKeycode(dpy, XStringToKeysym("grave")), AnyModifier, RootWindow(dpy, DefaultScreen(dpy)), True, GrabModeAsync, GrabModeAsync);
71                                                 XAutoRepeatOff(dpy);
72                                                 status |= STATUS_RUNNING;
73                                         } else {
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);
76                                                 XAutoRepeatOn(dpy);
77                                                 status &= ~STATUS_RUNNING;
78                                         }
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;
86                                         else
87                                                 status &= ~STATUS_TAPJUMP;
88                                         repeats = 1;
89                                 } else if (!strcmp(keystr, "j")) {
90                                         if (ev.type == KeyPress)
91                                         {
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);
95                                         } else
96                                                 status &= ~STATUS_LEFT;
97                                 } else if (!strcmp(keystr, "l")) {
98                                         if (ev.type == KeyPress)
99                                         {
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);
103                                         } else
104                                                 status &= ~STATUS_RIGHT;
105                                 } else if (!strcmp(keystr, "i")) {
106                                         if (ev.type == KeyPress)
107                                         {
108                                                 status |= STATUS_UP;
109                                                 if ((lastkey == 'i') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP))
110                                                         XTestFakeRelativeMotionEvent(dpy, 0, -100.0 * pow(repeats++, 0.8), 0);
111                                         } else
112                                                 status &= ~STATUS_UP;
113                                 } else if (!strcmp(keystr, "k")) {
114                                         if (ev.type == KeyPress)
115                                         {
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);
119                                         } else
120                                                 status &= ~STATUS_DOWN;
121                                 }
122                                 if (strlen(keystr) == 1 && ev.type == KeyPress)
123                                 {
124                                         lastkey = keystr[0];
125                                         lasttime = now();
126                                 } else if (ev.type == KeyPress) {
127                                         lastkey = 0;
128                                         repeats = 0;
129                                 }
130                                 break;
131                         }
132                         default:
133                                 printf("NFI what %d is\n", ev.type);
134                         }
135                 }
136                 if (!(status & STATUS_RUNNING))
137                         status = 0;
138                 if (!(status & STATUS_MOVING))  // if we haven't anything to do, don't sit and suck up cycles
139                 {
140                         XPeekEvent(dpy, &ev);
141                         starttime = now();
142                 }
143                 usleep(20000 - MIN(MAX(pow(13 * (now() - starttime), 0.6), 0), 18000));
144                 if (now() - lasttime > 250000)
145                         repeats = 1;
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);
154         }
155         
156         
157         exit(0);
158 }
This page took 0.0258 seconds and 4 git commands to generate.