rev |
line source |
paulo@0
|
1 /*
|
paulo@0
|
2 * Visual user-directed binary search for something to point your mouse at.
|
paulo@0
|
3 */
|
paulo@0
|
4
|
paulo@0
|
5 #include "config.h"
|
paulo@0
|
6
|
paulo@0
|
7 #include <stdio.h>
|
paulo@0
|
8 #include <stdlib.h>
|
paulo@0
|
9 #include <string.h>
|
paulo@0
|
10
|
paulo@0
|
11 #include <X11/Xlib.h>
|
paulo@0
|
12 #include <X11/Xresource.h>
|
paulo@0
|
13 #include <X11/Xutil.h>
|
paulo@0
|
14 #include <X11/extensions/shape.h>
|
paulo@0
|
15 #include <X11/extensions/XTest.h>
|
paulo@0
|
16
|
paulo@0
|
17 Display *dpy;
|
paulo@0
|
18 Window root;
|
paulo@0
|
19 XWindowAttributes attr;
|
paulo@0
|
20 int drag = 0;
|
paulo@0
|
21 int allmoves = 0;
|
paulo@0
|
22 int allhits = 0;
|
paulo@0
|
23 int allclicks = 0;
|
paulo@0
|
24 int ninegrid_default = 0;
|
paulo@0
|
25 int ninegrid_n_switch = 0;
|
paulo@0
|
26 int ninegrid = 0;
|
paulo@0
|
27
|
paulo@0
|
28 struct /* undo stack */
|
paulo@0
|
29 {
|
paulo@1
|
30 int x[N_UNDO];
|
paulo@1
|
31 int y[N_UNDO];
|
paulo@1
|
32 int w[N_UNDO];
|
paulo@1
|
33 int h[N_UNDO];
|
paulo@1
|
34 int ninegrid[N_UNDO];
|
paulo@0
|
35 } u;
|
paulo@0
|
36
|
paulo@0
|
37 void toggleninegrid() {
|
paulo@1
|
38 if (ninegrid)
|
paulo@1
|
39 ninegrid = 0;
|
paulo@1
|
40 else
|
paulo@1
|
41 ninegrid = 1;
|
paulo@0
|
42 }
|
paulo@0
|
43
|
paulo@0
|
44 void stats(int hits, int moves) {
|
paulo@1
|
45 allhits += hits;
|
paulo@1
|
46 allmoves += moves;
|
paulo@1
|
47 allclicks++;
|
paulo@1
|
48 printf("hits=%d, moves=%d \n", hits, moves);
|
paulo@1
|
49 printf("total hits=%d, total moves=%d, total clicks=%d, avg. hit/click=%.2f, avg. moves/click=%.2f \n", allhits, allmoves, allclicks, (float)allhits/(float)allclicks, (float)allmoves/(float)allclicks);
|
paulo@1
|
50 fflush(stdout); fflush(stderr); // force buffers to write out
|
paulo@0
|
51 }
|
paulo@0
|
52
|
paulo@0
|
53 void grab(char *keyname, int mods) {
|
paulo@1
|
54 int key;
|
paulo@1
|
55
|
paulo@1
|
56 key = XKeysymToKeycode(dpy, XStringToKeysym(keyname));
|
paulo@1
|
57 XGrabKey(dpy, key, mods, root, False,
|
paulo@1
|
58 GrabModeAsync, GrabModeAsync);
|
paulo@1
|
59 XGrabKey(dpy, key, mods | CAPSLOCKMASK, root, False,
|
paulo@1
|
60 GrabModeAsync, GrabModeAsync);
|
paulo@1
|
61 XGrabKey(dpy, key, mods | NUMLOCKMASK, root, False,
|
paulo@1
|
62 GrabModeAsync, GrabModeAsync);
|
paulo@1
|
63 XGrabKey(dpy, key, mods | CAPSLOCKMASK | NUMLOCKMASK, root, False,
|
paulo@1
|
64 GrabModeAsync, GrabModeAsync);
|
paulo@0
|
65 }
|
paulo@0
|
66
|
paulo@0
|
67 void ungrab(char *keyname, int mod) {
|
paulo@1
|
68 int key;
|
paulo@1
|
69
|
paulo@1
|
70 key = XKeysymToKeycode(dpy, XStringToKeysym(keyname));
|
paulo@1
|
71 XUngrabKey(dpy, key, mod, root);
|
paulo@1
|
72 XUngrabKey(dpy, key, mod | CAPSLOCKMASK, root);
|
paulo@1
|
73 XUngrabKey(dpy, key, mod | NUMLOCKMASK, root);
|
paulo@1
|
74 XUngrabKey(dpy, key, mod | CAPSLOCKMASK | NUMLOCKMASK, root);
|
paulo@0
|
75 }
|
paulo@0
|
76
|
paulo@0
|
77 void buttondown(int i) {
|
paulo@1
|
78 XTestFakeButtonEvent(dpy, i, True, 50);
|
paulo@0
|
79 }
|
paulo@0
|
80
|
paulo@0
|
81 void buttonup(int i) {
|
paulo@1
|
82 XTestFakeButtonEvent(dpy, i, False, 50);
|
paulo@0
|
83 }
|
paulo@0
|
84
|
paulo@0
|
85 void warppointer(int x, int y, int w, int h) {
|
paulo@1
|
86 XWarpPointer(dpy, None, root, 0, 0, 0, 0, x + w/2, y + h/2);
|
paulo@0
|
87 }
|
paulo@0
|
88
|
paulo@0
|
89 /* operations for undo */
|
paulo@0
|
90 void undo_stack_push(int x, int y, int w, int h) {
|
paulo@1
|
91 int i;
|
paulo@0
|
92
|
paulo@1
|
93 if (x >= 0 && y >= 0 && w > 0 && h > 0) {
|
paulo@1
|
94 fprintf(stderr,"undo_stack_push success: @(%d,%d) #(%d,%d)\n", x, y, w, h);
|
paulo@1
|
95 for (i=N_UNDO-1; i>0; i--) {
|
paulo@1
|
96 u.x[i] = u.x[i-1];
|
paulo@1
|
97 u.y[i] = u.y[i-1];
|
paulo@1
|
98 u.w[i] = u.w[i-1];
|
paulo@1
|
99 u.h[i] = u.h[i-1];
|
paulo@1
|
100 u.ninegrid[i] = u.ninegrid[i-1];
|
paulo@1
|
101 }
|
paulo@1
|
102 u.x[0] = x;
|
paulo@1
|
103 u.y[0] = y;
|
paulo@1
|
104 u.w[0] = w;
|
paulo@1
|
105 u.h[0] = h;
|
paulo@1
|
106 u.ninegrid[0] = ninegrid;
|
paulo@0
|
107 }
|
paulo@0
|
108 }
|
paulo@0
|
109
|
paulo@0
|
110 int undo_stack_pop(int *x, int *y, int *w, int *h, int *ninegrid) {
|
paulo@1
|
111 int i;
|
paulo@1
|
112 int ret = 0;
|
paulo@1
|
113
|
paulo@1
|
114 int rx = u.x[0];
|
paulo@1
|
115 int ry = u.y[0];
|
paulo@1
|
116 int rw = u.w[0];
|
paulo@1
|
117 int rh = u.h[0];
|
paulo@1
|
118 int rninegrid = u.ninegrid[0];
|
paulo@0
|
119
|
paulo@1
|
120 if (rx >= 0 && ry >= 0 && rw > 0 && rh > 0) {
|
paulo@1
|
121 fprintf(stderr,"undo_stack_pop success: @(%d,%d) #(%d,%d)\n", *x, *y, *w, *h);
|
paulo@1
|
122 ret = 1; // return success
|
paulo@1
|
123 for (i=0; i<N_UNDO-1; i++) {
|
paulo@1
|
124 u.x[i] = u.x[i+1];
|
paulo@1
|
125 u.y[i] = u.y[i+1];
|
paulo@1
|
126 u.w[i] = u.w[i+1];
|
paulo@1
|
127 u.h[i] = u.h[i+1];
|
paulo@1
|
128 u.ninegrid[i] = u.ninegrid[i+1];
|
paulo@1
|
129 }
|
paulo@1
|
130 u.x[N_UNDO-1] = -1;
|
paulo@1
|
131 u.y[N_UNDO-1] = -1;
|
paulo@1
|
132 u.w[N_UNDO-1] = -1;
|
paulo@1
|
133 u.h[N_UNDO-1] = -1;
|
paulo@1
|
134 u.ninegrid[N_UNDO-1] = -1;
|
paulo@1
|
135 *x = rx;
|
paulo@1
|
136 *y = ry;
|
paulo@1
|
137 *w = rw;
|
paulo@1
|
138 *h = rh;
|
paulo@1
|
139 *ninegrid = rninegrid;
|
paulo@0
|
140 }
|
paulo@1
|
141 return ret;
|
paulo@0
|
142 }
|
paulo@0
|
143
|
paulo@0
|
144 void undo_stack_reset() {
|
paulo@1
|
145 int i;
|
paulo@0
|
146
|
paulo@1
|
147 for (i=0; i<N_UNDO; i++) {
|
paulo@1
|
148 u.x[i] = -1;
|
paulo@1
|
149 u.y[i] = -1;
|
paulo@1
|
150 u.w[i] = -1;
|
paulo@1
|
151 u.h[i] = -1;
|
paulo@1
|
152 }
|
paulo@0
|
153 }
|
paulo@0
|
154 /* =-=-=-=-=-= */
|
paulo@0
|
155
|
paulo@0
|
156 int chk_keysym(int keysym, char *str) {
|
paulo@1
|
157 int ret = 0;
|
paulo@0
|
158
|
paulo@1
|
159 if (XStringToKeysym(str) == keysym)
|
paulo@1
|
160 ret = 1;
|
paulo@0
|
161
|
paulo@1
|
162 return ret;
|
paulo@0
|
163 }
|
paulo@0
|
164
|
paulo@0
|
165 GC creategc(Window win) {
|
paulo@1
|
166 GC gc;
|
paulo@1
|
167 XGCValues values;
|
paulo@1
|
168
|
paulo@1
|
169 gc = XCreateGC(dpy, win, 0, &values);
|
paulo@1
|
170 XSetForeground(dpy, gc, BlackPixel(dpy, 0));
|
paulo@1
|
171 XSetBackground(dpy, gc, WhitePixel(dpy, 0));
|
paulo@1
|
172 XSetLineAttributes(dpy, gc, LINEWIDTH, LineSolid, CapButt, JoinBevel);
|
paulo@1
|
173 XSetFillStyle(dpy, gc, FillSolid);
|
paulo@1
|
174
|
paulo@1
|
175 return gc;
|
paulo@0
|
176 }
|
paulo@0
|
177
|
paulo@0
|
178 void drawquadrants(Window win, int w, int h) {
|
paulo@1
|
179 GC gc;
|
paulo@1
|
180 XRectangle clip[20];
|
paulo@1
|
181 int idx = 0;
|
paulo@1
|
182 Colormap colormap;
|
paulo@1
|
183 XColor color;
|
paulo@1
|
184
|
paulo@1
|
185 gc = creategc(win);
|
paulo@1
|
186 colormap = DefaultColormap(dpy, 0);
|
paulo@1
|
187
|
paulo@1
|
188 if (drag)
|
paulo@1
|
189 XAllocNamedColor(dpy, colormap, DRAG_COLOR, &color, &color);
|
paulo@1
|
190 else
|
paulo@1
|
191 XAllocNamedColor(dpy, colormap, NORM_COLOR, &color, &color);
|
paulo@1
|
192
|
paulo@1
|
193 /*left*/ clip[idx].x = 0; clip[idx].y = 0; clip[idx].width = BORDER; clip[idx].height = h;
|
paulo@1
|
194 idx++;
|
paulo@1
|
195 /*right*/ clip[idx].x = w-BORDER; clip[idx].y = 0; clip[idx].width = BORDER; clip[idx].height = h;
|
paulo@1
|
196 idx++;
|
paulo@1
|
197 /*top*/ clip[idx].x = 0; clip[idx].y = 0; clip[idx].width = w; clip[idx].height = BORDER;
|
paulo@1
|
198 idx++;
|
paulo@1
|
199 /*bottom*/ clip[idx].x = 0; clip[idx].y = h-BORDER; clip[idx].width = w; clip[idx].height = BORDER;
|
paulo@1
|
200 idx++;
|
paulo@1
|
201
|
paulo@1
|
202 if (ninegrid) {
|
paulo@1
|
203 /*1st horiz*/
|
paulo@1
|
204 clip[idx].x = 0; clip[idx].y = h/3 - BORDER/2;
|
paulo@1
|
205 clip[idx].width = w; clip[idx].height = BORDER;
|
paulo@1
|
206 idx++;
|
paulo@1
|
207 /*2nd horiz*/
|
paulo@1
|
208 clip[idx].x = 0; clip[idx].y = h*2/3 - BORDER/2;
|
paulo@1
|
209 clip[idx].width = w; clip[idx].height = BORDER;
|
paulo@1
|
210 idx++;
|
paulo@1
|
211 /*1st vert*/
|
paulo@1
|
212 clip[idx].x = w/3 - BORDER/2; clip[idx].y = 0;
|
paulo@1
|
213 clip[idx].width = BORDER; clip[idx].height = h;
|
paulo@1
|
214 idx++;
|
paulo@1
|
215 /*2nd vert*/
|
paulo@1
|
216 clip[idx].x = w*2/3 - BORDER/2; clip[idx].y = 0;
|
paulo@1
|
217 clip[idx].width = BORDER; clip[idx].height = h;
|
paulo@1
|
218 idx++;
|
paulo@1
|
219 } else {
|
paulo@1
|
220 /*horiz*/
|
paulo@1
|
221 clip[idx].x = 0; clip[idx].y = h/2 - BORDER/2;
|
paulo@1
|
222 clip[idx].width = w; clip[idx].height = BORDER;
|
paulo@1
|
223 idx++;
|
paulo@1
|
224 /*vert*/
|
paulo@1
|
225 clip[idx].x = w/2 - BORDER/2; clip[idx].y = 0;
|
paulo@1
|
226 clip[idx].width = BORDER; clip[idx].height = h;
|
paulo@1
|
227 idx++;
|
paulo@1
|
228 }
|
paulo@0
|
229
|
paulo@1
|
230 XShapeCombineRectangles(dpy, win, ShapeBounding, 0, 0, clip, idx, ShapeSet, 0);
|
paulo@1
|
231
|
paulo@1
|
232 XFillRectangle(dpy, win, gc, 0, 0, w, h);
|
paulo@1
|
233
|
paulo@1
|
234 XSetForeground(dpy, gc, color.pixel);
|
paulo@1
|
235 XDrawLine(dpy, win, gc, BORDER - PEN, BORDER - PEN, w - PEN, BORDER - PEN); //top line
|
paulo@1
|
236 XDrawLine(dpy, win, gc, BORDER - PEN, h - PEN, w - PEN, h - PEN); //bottom line
|
paulo@1
|
237 XDrawLine(dpy, win, gc, BORDER - PEN, BORDER - PEN, BORDER - PEN, h - PEN); //left line
|
paulo@1
|
238 XDrawLine(dpy, win, gc, w - PEN, BORDER - PEN, w - PEN, h - PEN); //left line
|
paulo@0
|
239
|
paulo@1
|
240 if (ninegrid) {
|
paulo@1
|
241 XDrawLine(dpy, win, gc, w/3, 0, w/3, h); // 1st vert line
|
paulo@1
|
242 XDrawLine(dpy, win, gc, w*2/3, 0, w*2/3, h); // 2nd vert line
|
paulo@1
|
243 XDrawLine(dpy, win, gc, 0, h/3, w, h/3); // 1st horiz line
|
paulo@1
|
244 XDrawLine(dpy, win, gc, 0, h*2/3, w, h*2/3); // 2nd horiz line
|
paulo@1
|
245 } else {
|
paulo@1
|
246 XDrawLine(dpy, win, gc, w/2, 0, w/2, h); // vert line
|
paulo@1
|
247 XDrawLine(dpy, win, gc, 0, h/2, w, h/2); // horiz line
|
paulo@1
|
248 }
|
paulo@0
|
249
|
paulo@1
|
250 XFlush(dpy);
|
paulo@0
|
251 }
|
paulo@0
|
252
|
paulo@0
|
253 int handlekey(int keysym, int mod, int *moves, int *x, int *y, int *w, int *h) {
|
paulo@1
|
254 int ret = 1;
|
paulo@1
|
255 int ox = *x;
|
paulo@1
|
256 int oy = *y;
|
paulo@1
|
257 int ow = *w;
|
paulo@1
|
258 int oh = *h;;
|
paulo@0
|
259
|
paulo@1
|
260 if (mod & SHIFTMASK || mod & SHIFTMASK & NUMLOCKMASK || mod & SHIFTMASK & CAPSLOCKMASK || mod & SHIFTMASK & CAPSLOCKMASK & NUMLOCKMASK) {
|
paulo@1
|
261 if (chk_keysym(keysym, KEY_CENTER))
|
paulo@1
|
262 toggleninegrid();
|
paulo@1
|
263 if (chk_keysym(keysym, KEY_LEFT) || chk_keysym(keysym, KEY_UPLEFT) || chk_keysym(keysym, KEY_DOWNLEFT)) {
|
paulo@1
|
264 if (*x > 0) *x -= *w; // shift left
|
paulo@1
|
265 }
|
paulo@1
|
266 if (chk_keysym(keysym, KEY_DOWN) || chk_keysym(keysym, KEY_DOWNLEFT) || chk_keysym(keysym, KEY_DOWNRIGHT)) {
|
paulo@1
|
267 if ((*y + *h) < attr.height) *y += *h; // shift down
|
paulo@1
|
268 }
|
paulo@1
|
269 if (chk_keysym(keysym, KEY_UP) || chk_keysym(keysym, KEY_UPLEFT) || chk_keysym(keysym, KEY_UPRIGHT)) {
|
paulo@1
|
270 if (*y > 0) *y -= *h; // shift up
|
paulo@1
|
271 }
|
paulo@1
|
272 if (chk_keysym(keysym, KEY_RIGHT) || chk_keysym(keysym, KEY_UPRIGHT) || chk_keysym(keysym, KEY_DOWNRIGHT)) {
|
paulo@1
|
273 if ((*x + *w) < attr.width) *x += *w; // shift right
|
paulo@1
|
274 }
|
paulo@1
|
275 } else {
|
paulo@1
|
276 if (ninegrid) {
|
paulo@1
|
277 if (chk_keysym(keysym, KEY_UPLEFT)) {
|
paulo@1
|
278 *w /= 3; *h /= 3; // split upper left
|
paulo@1
|
279 } else if (chk_keysym(keysym, KEY_UP)) {
|
paulo@1
|
280 *w /= 3; *h /= 3; // split up
|
paulo@1
|
281 *x += *w;
|
paulo@1
|
282 } else if (chk_keysym(keysym, KEY_UPRIGHT)) {
|
paulo@1
|
283 *w /= 3; *h /= 3; // split upper right
|
paulo@1
|
284 *x += *w * 2;
|
paulo@1
|
285 } else if (chk_keysym(keysym, KEY_LEFT)) {
|
paulo@1
|
286 *w /= 3; *h /= 3; // split left
|
paulo@1
|
287 *y += *h;
|
paulo@1
|
288 } else if (chk_keysym(keysym, KEY_CENTER)) {
|
paulo@1
|
289 *w /= 3; *h /= 3; // split center
|
paulo@1
|
290 *x += *w; *y += *h;
|
paulo@1
|
291 } else if (chk_keysym(keysym, KEY_RIGHT)) {
|
paulo@1
|
292 *w /= 3; *h /= 3; // split right
|
paulo@1
|
293 *x += *w * 2; *y += *h;
|
paulo@1
|
294 } else if (chk_keysym(keysym, KEY_DOWNLEFT)) {
|
paulo@1
|
295 *w /= 3; *h /= 3; // split bottom left
|
paulo@1
|
296 *y += *h * 2;
|
paulo@1
|
297 } else if (chk_keysym(keysym, KEY_DOWN)) {
|
paulo@1
|
298 *w /= 3; *h /= 3; // split down
|
paulo@1
|
299 *x += *w; *y += *h * 2;
|
paulo@1
|
300 } else if (chk_keysym(keysym, KEY_DOWNRIGHT)) {
|
paulo@1
|
301 *w /= 3; *h /= 3; // split bottom right
|
paulo@1
|
302 *x += *w * 2; *y += *h * 2;
|
paulo@1
|
303 }
|
paulo@1
|
304 } else {
|
paulo@1
|
305 if (chk_keysym(keysym, KEY_LEFT) || chk_keysym(keysym, KEY_UPLEFT) || chk_keysym(keysym, KEY_DOWNLEFT)) {
|
paulo@1
|
306 *w /= 2; // split left
|
paulo@1
|
307 }
|
paulo@1
|
308 if (chk_keysym(keysym, KEY_DOWN) || chk_keysym(keysym, KEY_DOWNLEFT) || chk_keysym(keysym, KEY_DOWNRIGHT)) {
|
paulo@1
|
309 *h /= 2; // split down
|
paulo@1
|
310 *y += *h;
|
paulo@1
|
311 }
|
paulo@1
|
312 if (chk_keysym(keysym, KEY_UP) || chk_keysym(keysym, KEY_UPLEFT) || chk_keysym(keysym, KEY_UPRIGHT)) {
|
paulo@1
|
313 *h /= 2; // split up
|
paulo@1
|
314 }
|
paulo@1
|
315 if (chk_keysym(keysym, KEY_RIGHT) || chk_keysym(keysym, KEY_UPRIGHT) || chk_keysym(keysym, KEY_DOWNRIGHT)) {
|
paulo@1
|
316 *w /= 2; // split right
|
paulo@1
|
317 *x += *w;
|
paulo@1
|
318 }
|
paulo@1
|
319 }
|
paulo@0
|
320 }
|
paulo@1
|
321
|
paulo@1
|
322 if (ox != *x || oy != *y || ow != *w || oh != *h) {
|
paulo@1
|
323 undo_stack_push(ox, oy, ow, oh);
|
paulo@1
|
324 *moves += 1;
|
paulo@0
|
325 }
|
paulo@1
|
326 else if (chk_keysym(keysym, KEY_UNDO)) {
|
paulo@1
|
327 int i, j;
|
paulo@0
|
328
|
paulo@1
|
329 if (mod & SHIFTMASK) j = 0;
|
paulo@1
|
330 else j = SHIFT_N_UNDO-1;
|
paulo@0
|
331
|
paulo@1
|
332 for (i=j; i<SHIFT_N_UNDO; i++) {
|
paulo@1
|
333 undo_stack_pop(x, y, w, h, &ninegrid);
|
paulo@1
|
334 *moves -= 1;
|
paulo@1
|
335 }
|
paulo@1
|
336 ret = 2;
|
paulo@1
|
337 }
|
paulo@0
|
338
|
paulo@1
|
339 if (*w < 1 || *h < 1) {
|
paulo@1
|
340 fprintf(stderr,"OOPS. Area too small. Giving up :(\n");
|
paulo@1
|
341 return 0;
|
paulo@0
|
342 }
|
paulo@0
|
343
|
paulo@1
|
344 if (drag && !(mod & WARPMASK) || !drag && (mod & WARPMASK))
|
paulo@1
|
345 warppointer(*x, *y, *w, *h);
|
paulo@1
|
346
|
paulo@1
|
347 fprintf(stderr,"Box: @(%d,%d) #(%d,%d)\n", *x, *y, *w, *h);
|
paulo@1
|
348
|
paulo@1
|
349 return ret;
|
paulo@0
|
350 }
|
paulo@0
|
351
|
paulo@0
|
352 void startmousekey(int from_undo) {
|
paulo@1
|
353 int keysym;
|
paulo@1
|
354 int done = 0;
|
paulo@1
|
355 int x,y,w,h;
|
paulo@1
|
356 int warp = 0;
|
paulo@1
|
357 int click = 0;
|
paulo@1
|
358 int k, hits, moves;
|
paulo@1
|
359 int mod;
|
paulo@1
|
360
|
paulo@1
|
361 Window zone;
|
paulo@1
|
362
|
paulo@1
|
363 // disable trigger keygrab
|
paulo@1
|
364 ungrab(KEY_TRIGGER, TRIGGERMASK);
|
paulo@1
|
365 ungrab(KEY_UNDO, TRIGGERMASK);
|
paulo@1
|
366
|
paulo@1
|
367 // grab keyboard
|
paulo@1
|
368 XGrabKeyboard(dpy, root, False, GrabModeAsync, GrabModeAsync, CurrentTime);
|
paulo@1
|
369
|
paulo@1
|
370 // init stuff
|
paulo@1
|
371 hits = moves = 0;
|
paulo@1
|
372 if (from_undo && undo_stack_pop(&x, &y, &w, &h, &ninegrid));
|
paulo@1
|
373 /* null -- only check for undo_stack_pop success */
|
paulo@1
|
374 else {
|
paulo@1
|
375 undo_stack_reset();
|
paulo@1
|
376 if (ninegrid_default)
|
paulo@1
|
377 ninegrid = 1;
|
paulo@1
|
378 x = y = 0;
|
paulo@1
|
379 w = attr.width;
|
paulo@1
|
380 h = attr.height;
|
paulo@1
|
381 }
|
paulo@0
|
382
|
paulo@1
|
383 zone = XCreateSimpleWindow(dpy, root, x, y, w, h, 1, BlackPixel(dpy, 0), WhitePixel(dpy, 0));
|
paulo@1
|
384
|
paulo@1
|
385 { /* Tell the window manager not to manage us */
|
paulo@1
|
386 unsigned long valuemask;
|
paulo@1
|
387 XSetWindowAttributes winattr;
|
paulo@1
|
388 winattr.override_redirect = 1;
|
paulo@1
|
389 XChangeWindowAttributes(dpy, zone, CWOverrideRedirect, &winattr);
|
paulo@1
|
390 }
|
paulo@0
|
391
|
paulo@1
|
392 drawquadrants(zone, w, h);
|
paulo@1
|
393 XMapWindow(dpy, zone);
|
paulo@1
|
394 drawquadrants(zone, w, h);
|
paulo@1
|
395
|
paulo@1
|
396 fprintf(stderr,"Starting quadrants...\n");
|
paulo@1
|
397 while (!done) {
|
paulo@1
|
398 XEvent e;
|
paulo@1
|
399 XNextEvent(dpy, &e);
|
paulo@1
|
400 if (e.type == KeyPress) {
|
paulo@1
|
401 keysym = XKeycodeToKeysym(dpy, e.xkey.keycode, 0);
|
paulo@1
|
402 mod = e.xkey.state;
|
paulo@1
|
403 if (chk_keysym(keysym, KEY_Q_CLICK)) {
|
paulo@1
|
404 done++;
|
paulo@1
|
405 click = 1;
|
paulo@1
|
406 } else if (chk_keysym(keysym, KEY_Q_RCLICK)) {
|
paulo@1
|
407 done++;
|
paulo@1
|
408 click = 3;
|
paulo@1
|
409 } else if (chk_keysym(keysym, KEY_QW_CLICK)) {
|
paulo@1
|
410 done++;
|
paulo@1
|
411 warp = 1;
|
paulo@1
|
412 click = 1;
|
paulo@1
|
413 } else if (chk_keysym(keysym, KEY_Q_MCLICK)) {
|
paulo@1
|
414 done++;
|
paulo@1
|
415 click = 2;
|
paulo@1
|
416 } else if (chk_keysym(keysym, KEY_QW_RCLICK)) {
|
paulo@1
|
417 done++;
|
paulo@1
|
418 warp = 1;
|
paulo@1
|
419 click = 3;
|
paulo@1
|
420 } else if (chk_keysym(keysym, KEY_HIDE)) {
|
paulo@1
|
421 done++;
|
paulo@1
|
422 warp = 1;
|
paulo@2
|
423 x = attr.width;
|
paulo@2
|
424 y = attr.height;
|
paulo@1
|
425 } else if (chk_keysym(keysym, KEY_ESCAPE)) {
|
paulo@1
|
426 warp = 0;
|
paulo@1
|
427 done++;
|
paulo@1
|
428 } else if (!drag && chk_keysym(keysym, KEY_ONE)) {
|
paulo@1
|
429 buttondown(1);
|
paulo@1
|
430 buttonup(1);
|
paulo@1
|
431 } else if (!drag && chk_keysym(keysym, KEY_TWO)) {
|
paulo@1
|
432 buttondown(2);
|
paulo@1
|
433 buttonup(2);
|
paulo@1
|
434 } else if (!drag && chk_keysym(keysym, KEY_THREE)) {
|
paulo@1
|
435 buttondown(3);
|
paulo@1
|
436 buttonup(3);
|
paulo@1
|
437 } else {
|
paulo@1
|
438 if (k = handlekey(keysym, mod, &moves, &x, &y, &w, &h)) {
|
paulo@1
|
439 if (ninegrid_default && ninegrid_n_switch && k < 2 && moves >= ninegrid_n_switch)
|
paulo@1
|
440 ninegrid = 0;
|
paulo@1
|
441 hits++;
|
paulo@1
|
442 XMoveResizeWindow(dpy, zone, x, y, w, h);
|
paulo@1
|
443 drawquadrants(zone, w, h);
|
paulo@1
|
444 } else
|
paulo@1
|
445 done++;
|
paulo@0
|
446 }
|
paulo@0
|
447 }
|
paulo@1
|
448 }
|
paulo@0
|
449
|
paulo@1
|
450 // end mouse key
|
paulo@1
|
451 XUngrabKeyboard(dpy, CurrentTime);
|
paulo@1
|
452 XDestroyWindow(dpy, zone);
|
paulo@1
|
453 undo_stack_push(x, y, w, h);
|
paulo@0
|
454
|
paulo@1
|
455 if (warp)
|
paulo@1
|
456 warppointer(x, y, w, h);
|
paulo@1
|
457 if (click == 1) {
|
paulo@1
|
458 if (!drag)
|
paulo@1
|
459 buttondown(1);
|
paulo@1
|
460 if (mod & DRAGMASK && !drag)
|
paulo@1
|
461 drag = 1;
|
paulo@1
|
462 else if (mod & DRAGMASK) {
|
paulo@1
|
463 buttonup(1);
|
paulo@1
|
464 buttondown(1);
|
paulo@1
|
465 } else {
|
paulo@1
|
466 buttonup(1);
|
paulo@1
|
467 drag = 0;
|
paulo@1
|
468 }
|
paulo@1
|
469 } else if (click) {
|
paulo@1
|
470 buttondown(click);
|
paulo@1
|
471 buttonup(click);
|
paulo@1
|
472 }
|
paulo@1
|
473
|
paulo@1
|
474 if (click) stats(hits, moves);
|
paulo@1
|
475
|
paulo@1
|
476 // loop back if in drag mode
|
paulo@1
|
477 if (drag) {
|
paulo@1
|
478 usleep(50);
|
paulo@1
|
479 startmousekey(0);
|
paulo@0
|
480 }
|
paulo@0
|
481
|
paulo@1
|
482 // re-enable trigger keygrabs
|
paulo@1
|
483 grab(KEY_TRIGGER, TRIGGERMASK);
|
paulo@1
|
484 grab(KEY_UNDO, TRIGGERMASK);
|
paulo@0
|
485 }
|
paulo@0
|
486
|
paulo@0
|
487 int main(int argc, char **argv) {
|
paulo@1
|
488 char *pcDisplay;
|
paulo@1
|
489
|
paulo@1
|
490 if ((dpy = XOpenDisplay(pcDisplay = getenv("DISPLAY"))) == NULL) {
|
paulo@0
|
491 fprintf(stderr,"Error: Can't open display: %s", pcDisplay);
|
paulo@0
|
492 exit(1);
|
paulo@1
|
493 }
|
paulo@1
|
494 fprintf(stderr,"Display: %s\n", pcDisplay);
|
paulo@0
|
495
|
paulo@1
|
496 // parse options
|
paulo@1
|
497 if (argc > 1)
|
paulo@1
|
498 if (argv[1][0] && argv[1][0] == '-')
|
paulo@1
|
499 if (argv[1][1] && argv[1][1] == 'n') {
|
paulo@1
|
500 ninegrid_default = 1;
|
paulo@1
|
501 fprintf(stderr,"nine-grid default mode \n");
|
paulo@1
|
502 if (argv[2]) {
|
paulo@1
|
503 ninegrid_n_switch = atoi(argv[2]);
|
paulo@1
|
504 fprintf(stderr,"nine-grid autoswitch num: %d \n", ninegrid_n_switch);
|
paulo@1
|
505 }
|
paulo@1
|
506 }
|
paulo@0
|
507
|
paulo@1
|
508 root = XDefaultRootWindow(dpy);
|
paulo@1
|
509 XGetWindowAttributes(dpy, root, &attr);
|
paulo@1
|
510
|
paulo@1
|
511 // these are the trigger keygrabs
|
paulo@1
|
512 grab(KEY_TRIGGER, TRIGGERMASK);
|
paulo@1
|
513 grab(KEY_UNDO, TRIGGERMASK);
|
paulo@1
|
514
|
paulo@1
|
515 while (1) {
|
paulo@0
|
516 XEvent e;
|
paulo@0
|
517 XNextEvent(dpy, &e);
|
paulo@0
|
518 if (e.type == KeyPress)
|
paulo@1
|
519 if (chk_keysym(XKeycodeToKeysym(dpy, e.xkey.keycode, 0), KEY_UNDO))
|
paulo@1
|
520 startmousekey(1);
|
paulo@1
|
521 else
|
paulo@1
|
522 startmousekey(0);
|
paulo@1
|
523 }
|
paulo@0
|
524 }
|