initial import of xvmouse
[xvmouse.git] / xvmouse.c
CommitLineData
2c1bb55d
JW
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
20unsigned long long now()
21{
22 struct timeval tv;
23 gettimeofday(&tv, NULL);
24 return tv.tv_sec*1000000 + tv.tv_usec;
25}
26
27void 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.030018 seconds and 4 git commands to generate.