Add middle-click with 'p'
[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
38f747ac 27int main()
2c1bb55d
JW
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);
38f747ac
JW
83 else if (!strcmp(keystr, "p"))
84 XTestFakeButtonEvent(dpy, 2, ev.type == KeyPress, 0);
2c1bb55d
JW
85 else if (!strcmp(keystr, "apostrophe") || !strcmp(keystr, "semicolon")) {
86 if (ev.type == KeyPress)
87 status |= STATUS_TAPJUMP;
88 else
89 status &= ~STATUS_TAPJUMP;
90 repeats = 1;
91 } else if (!strcmp(keystr, "j")) {
92 if (ev.type == KeyPress)
93 {
94 status |= STATUS_LEFT;
95 if ((lastkey == 'j') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP))
96 XTestFakeRelativeMotionEvent(dpy, -100.0 * pow(repeats++, 0.8), 0, 0);
97 } else
98 status &= ~STATUS_LEFT;
99 } else if (!strcmp(keystr, "l")) {
100 if (ev.type == KeyPress)
101 {
102 status |= STATUS_RIGHT;
103 if ((lastkey == 'l') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP))
104 XTestFakeRelativeMotionEvent(dpy, 100.0 * pow(repeats++, 0.8), 0, 0);
105 } else
106 status &= ~STATUS_RIGHT;
107 } else if (!strcmp(keystr, "i")) {
108 if (ev.type == KeyPress)
109 {
110 status |= STATUS_UP;
111 if ((lastkey == 'i') && ((now() - lasttime) < 250000) && (status & STATUS_TAPJUMP))
112 XTestFakeRelativeMotionEvent(dpy, 0, -100.0 * pow(repeats++, 0.8), 0);
113 } else
114 status &= ~STATUS_UP;
115 } else if (!strcmp(keystr, "k")) {
116 if (ev.type == KeyPress)
117 {
118 status |= STATUS_DOWN;
119 if (lastkey == 'k' && (now() - lasttime) < 250000 && (status & STATUS_TAPJUMP))
120 XTestFakeRelativeMotionEvent(dpy, 0, 100.0 * pow(repeats++, 0.8), 0);
121 } else
122 status &= ~STATUS_DOWN;
123 }
124 if (strlen(keystr) == 1 && ev.type == KeyPress)
125 {
126 lastkey = keystr[0];
127 lasttime = now();
128 } else if (ev.type == KeyPress) {
129 lastkey = 0;
130 repeats = 0;
131 }
132 break;
133 }
134 default:
135 printf("NFI what %d is\n", ev.type);
136 }
137 }
138 if (!(status & STATUS_RUNNING))
139 status = 0;
140 if (!(status & STATUS_MOVING)) // if we haven't anything to do, don't sit and suck up cycles
141 {
142 XPeekEvent(dpy, &ev);
143 starttime = now();
144 }
145 usleep(20000 - MIN(MAX(pow(13 * (now() - starttime), 0.6), 0), 18000));
146 if (now() - lasttime > 250000)
147 repeats = 1;
148 if (status & STATUS_LEFT)
149 XTestFakeRelativeMotionEvent(dpy, -2, 0, 0);
150 if (status & STATUS_RIGHT)
151 XTestFakeRelativeMotionEvent(dpy, 2, 0, 0);
152 if (status & STATUS_UP)
153 XTestFakeRelativeMotionEvent(dpy, 0, -2, 0);
154 if (status & STATUS_DOWN)
155 XTestFakeRelativeMotionEvent(dpy, 0, 2, 0);
156 }
157
2c1bb55d 158 exit(0);
38f747ac 159}
This page took 0.032568 seconds and 4 git commands to generate.