annotate keynav.c @ 2:640c5e9ea6ad

use root window width and height when hiding mouse cursor, so that it really hides away on the bottom right corner in all cases
author paulo@thepaulopc
date Thu, 17 Jun 2010 00:56:16 -0700
parents 0d5dc7c29c78
children
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 }