| @@ -38,7 +38,6 @@ |
| 38 | 38 | | /* timeouts in milliseconds: */ |
| 39 | 39 | | enum { |
| 40 | 40 | | TO_WIN_RESIZE = 75, |
| 41 | | − | TO_IMAGE_DRAG = 1, |
| 42 | 41 | | TO_CURSOR_HIDE = 1500, |
| 43 | 42 | | TO_THUMBS_LOAD = 200 |
| 44 | 43 | | }; |
| @@ -58,8 +57,6 @@ extern int filecnt, fileidx; |
| 58 | 57 | | |
| 59 | 58 | | int timo_cursor; |
| 60 | 59 | | int timo_redraw; |
| 61 | | − | unsigned char dragging; |
| 62 | | − | int mox, moy; |
| 63 | 60 | | |
| 64 | 61 | | int run_command(const char *cline, Bool reload) { |
| 65 | 62 | | int fncnt, fnlen; |
| @@ -122,7 +119,7 @@ void redraw() { |
| 122 | 119 | | img_render(&img, &win); |
| 123 | 120 | | if (timo_cursor) |
| 124 | 121 | | win_set_cursor(&win, CURSOR_ARROW); |
| 125 | | − | else if (!dragging) |
| 122 | + | else |
| 126 | 123 | | win_set_cursor(&win, CURSOR_NONE); |
| 127 | 124 | | } else { |
| 128 | 125 | | tns_render(&tns, &win); |
| @@ -131,16 +128,14 @@ void redraw() { |
| 131 | 128 | | timo_redraw = 0; |
| 132 | 129 | | } |
| 133 | 130 | | |
| 134 | | − | void on_keypress(XEvent *ev) { |
| 131 | + | void on_keypress(XKeyEvent *kev) { |
| 135 | 132 | | int i; |
| 136 | | − | XKeyEvent *kev; |
| 137 | 133 | | KeySym ksym; |
| 138 | 134 | | char key; |
| 139 | 135 | | |
| 140 | | − | if (!ev || ev->type != KeyPress) |
| 136 | + | if (!kev) |
| 141 | 137 | | return; |
| 142 | | − | |
| 143 | | − | kev = &ev->xkey; |
| 138 | + | |
| 144 | 139 | | XLookupString(kev, &key, 1, &ksym, NULL); |
| 145 | 140 | | |
| 146 | 141 | | if (EXT_COMMANDS && (CLEANMASK(kev->state) & ControlMask)) { |
| @@ -174,39 +169,34 @@ void on_keypress(XEvent *ev) { |
| 174 | 169 | | |
| 175 | 170 | | for (i = 0; i < LEN(keys); i++) { |
| 176 | 171 | | if (ksym == keys[i].ksym && keys[i].handler) { |
| 177 | | − | if (keys[i].handler(ev, keys[i].arg)) |
| 172 | + | if (keys[i].handler(keys[i].arg)) |
| 178 | 173 | | redraw(); |
| 179 | 174 | | return; |
| 180 | 175 | | } |
| 181 | 176 | | } |
| 182 | 177 | | } |
| 183 | 178 | | |
| 184 | | − | void on_buttonpress(XEvent *ev) { |
| 179 | + | void on_buttonpress(XButtonEvent *bev) { |
| 185 | 180 | | int i, sel; |
| 186 | | − | XButtonEvent *bev; |
| 187 | 181 | | |
| 188 | | − | if (!ev || ev->type != ButtonPress) |
| 182 | + | if (!bev) |
| 189 | 183 | | return; |
| 190 | 184 | | |
| 191 | | − | bev = &ev->xbutton; |
| 192 | | − | |
| 193 | 185 | | if (mode == MODE_NORMAL) { |
| 194 | | − | if (!dragging) { |
| 195 | | − | win_set_cursor(&win, CURSOR_ARROW); |
| 196 | | − | timo_cursor = TO_CURSOR_HIDE; |
| 197 | | − | } |
| 186 | + | win_set_cursor(&win, CURSOR_ARROW); |
| 187 | + | timo_cursor = TO_CURSOR_HIDE; |
| 198 | 188 | | |
| 199 | 189 | | for (i = 0; i < LEN(buttons); i++) { |
| 200 | 190 | | if (CLEANMASK(bev->state) == CLEANMASK(buttons[i].mod) && |
| 201 | 191 | | bev->button == buttons[i].button && buttons[i].handler) |
| 202 | 192 | | { |
| 203 | | − | if (buttons[i].handler(ev, buttons[i].arg)) |
| 193 | + | if (buttons[i].handler(buttons[i].arg)) |
| 204 | 194 | | redraw(); |
| 205 | 195 | | return; |
| 206 | 196 | | } |
| 207 | 197 | | } |
| 208 | 198 | | } else { |
| 209 | | − | /* thumbnail mode */ |
| 199 | + | /* thumbnail mode (hard-coded) */ |
| 210 | 200 | | switch (bev->button) { |
| 211 | 201 | | case Button1: |
| 212 | 202 | | if ((sel = tns_translate(&tns, bev->x, bev->y)) >= 0) { |
| @@ -232,29 +222,12 @@ void on_buttonpress(XEvent *ev) { |
| 232 | 222 | | } |
| 233 | 223 | | } |
| 234 | 224 | | |
| 235 | | − | void on_motionnotify(XEvent *ev) { |
| 236 | | − | XMotionEvent *mev; |
| 237 | | − | |
| 238 | | − | if (!ev || ev->type != MotionNotify) |
| 239 | | − | return; |
| 240 | | − | |
| 241 | | − | mev = &ev->xmotion; |
| 242 | | − | |
| 243 | | − | if (mev->x >= 0 && mev->x <= win.w && mev->y >= 0 && mev->y <= win.h) { |
| 244 | | − | if (img_move(&img, &win, mev->x - mox, mev->y - moy)) |
| 245 | | − | timo_redraw = TO_IMAGE_DRAG; |
| 246 | | − | mox = mev->x; |
| 247 | | − | moy = mev->y; |
| 248 | | − | } |
| 249 | | − | } |
| 250 | | − | |
| 251 | 225 | | void run() { |
| 252 | 226 | | int xfd, timeout; |
| 253 | 227 | | fd_set fds; |
| 254 | 228 | | struct timeval tt, t0, t1; |
| 255 | 229 | | XEvent ev; |
| 256 | 230 | | |
| 257 | | − | dragging = 0; |
| 258 | 231 | | timo_cursor = mode == MODE_NORMAL ? TO_CURSOR_HIDE : 0; |
| 259 | 232 | | |
| 260 | 233 | | redraw(); |
| @@ -312,18 +285,10 @@ void run() { |
| 312 | 285 | | } |
| 313 | 286 | | |
| 314 | 287 | | if (!XNextEvent(win.env.dpy, &ev)) { |
| 288 | + | /* handle events */ |
| 315 | 289 | | switch (ev.type) { |
| 316 | 290 | | case ButtonPress: |
| 317 | | − | on_buttonpress(&ev); |
| 318 | | − | break; |
| 319 | | − | case ButtonRelease: |
| 320 | | − | if (dragging) { |
| 321 | | − | dragging = 0; |
| 322 | | − | if (mode == MODE_NORMAL) { |
| 323 | | − | win_set_cursor(&win, CURSOR_ARROW); |
| 324 | | − | timo_cursor = TO_CURSOR_HIDE; |
| 325 | | − | } |
| 326 | | − | } |
| 291 | + | on_buttonpress(&ev.xbutton); |
| 327 | 292 | | break; |
| 328 | 293 | | case ClientMessage: |
| 329 | 294 | | if ((Atom) ev.xclient.data.l[0] == wm_delete_win) |
| @@ -339,16 +304,12 @@ void run() { |
| 339 | 304 | | } |
| 340 | 305 | | break; |
| 341 | 306 | | case KeyPress: |
| 342 | | − | on_keypress(&ev); |
| 307 | + | on_keypress(&ev.xkey); |
| 343 | 308 | | break; |
| 344 | 309 | | case MotionNotify: |
| 345 | | − | if (dragging) { |
| 346 | | − | on_motionnotify(&ev); |
| 347 | | − | } else if (mode == MODE_NORMAL) { |
| 348 | | − | if (!timo_cursor) |
| 349 | | − | win_set_cursor(&win, CURSOR_ARROW); |
| 350 | | − | timo_cursor = TO_CURSOR_HIDE; |
| 351 | | − | } |
| 310 | + | if (!timo_cursor) |
| 311 | + | win_set_cursor(&win, CURSOR_ARROW); |
| 312 | + | timo_cursor = TO_CURSOR_HIDE; |
| 352 | 313 | | break; |
| 353 | 314 | | } |
| 354 | 315 | | } |
| @@ -358,12 +319,12 @@ void run() { |
| 358 | 319 | | |
| 359 | 320 | | /* handler functions for key and button mappings: */ |
| 360 | 321 | | |
| 361 | | − | int quit(XEvent *e, arg_t a) { |
| 322 | + | int quit(arg_t a) { |
| 362 | 323 | | cleanup(); |
| 363 | 324 | | exit(0); |
| 364 | 325 | | } |
| 365 | 326 | | |
| 366 | | − | int reload(XEvent *e, arg_t a) { |
| 327 | + | int reload(arg_t a) { |
| 367 | 328 | | if (mode == MODE_NORMAL) { |
| 368 | 329 | | load_image(fileidx); |
| 369 | 330 | | return 1; |
| @@ -372,7 +333,7 @@ int reload(XEvent *e, arg_t a) { |
| 372 | 333 | | } |
| 373 | 334 | | } |
| 374 | 335 | | |
| 375 | | − | int toggle_fullscreen(XEvent *e, arg_t a) { |
| 336 | + | int toggle_fullscreen(arg_t a) { |
| 376 | 337 | | win_toggle_fullscreen(&win); |
| 377 | 338 | | if (mode == MODE_NORMAL) |
| 378 | 339 | | img.checkpan = 1; |
| @@ -382,7 +343,7 @@ int toggle_fullscreen(XEvent *e, arg_t a) { |
| 382 | 343 | | return 0; |
| 383 | 344 | | } |
| 384 | 345 | | |
| 385 | | − | int toggle_antialias(XEvent *e, arg_t a) { |
| 346 | + | int toggle_antialias(arg_t a) { |
| 386 | 347 | | if (mode == MODE_NORMAL) { |
| 387 | 348 | | img_toggle_antialias(&img); |
| 388 | 349 | | return 1; |
| @@ -391,7 +352,7 @@ int toggle_antialias(XEvent *e, arg_t a) { |
| 391 | 352 | | } |
| 392 | 353 | | } |
| 393 | 354 | | |
| 394 | | − | int toggle_alpha(XEvent *e, arg_t a) { |
| 355 | + | int toggle_alpha(arg_t a) { |
| 395 | 356 | | if (mode == MODE_NORMAL) { |
| 396 | 357 | | img.alpha ^= 1; |
| 397 | 358 | | return 1; |
| @@ -400,7 +361,7 @@ int toggle_alpha(XEvent *e, arg_t a) { |
| 400 | 361 | | } |
| 401 | 362 | | } |
| 402 | 363 | | |
| 403 | | − | int switch_mode(XEvent *e, arg_t a) { |
| 364 | + | int switch_mode(arg_t a) { |
| 404 | 365 | | if (mode == MODE_NORMAL) { |
| 405 | 366 | | if (!tns.thumbs) |
| 406 | 367 | | tns_init(&tns, filecnt); |
| @@ -418,7 +379,7 @@ int switch_mode(XEvent *e, arg_t a) { |
| 418 | 379 | | return 1; |
| 419 | 380 | | } |
| 420 | 381 | | |
| 421 | | − | int navigate(XEvent *e, arg_t n) { |
| 382 | + | int navigate(arg_t n) { |
| 422 | 383 | | if (mode == MODE_NORMAL) { |
| 423 | 384 | | n += fileidx; |
| 424 | 385 | | if (n < 0) |
| @@ -434,7 +395,7 @@ int navigate(XEvent *e, arg_t n) { |
| 434 | 395 | | return 0; |
| 435 | 396 | | } |
| 436 | 397 | | |
| 437 | | − | int first(XEvent *e, arg_t a) { |
| 398 | + | int first(arg_t a) { |
| 438 | 399 | | if (mode == MODE_NORMAL && fileidx != 0) { |
| 439 | 400 | | load_image(0); |
| 440 | 401 | | return 1; |
| @@ -447,7 +408,7 @@ int first(XEvent *e, arg_t a) { |
| 447 | 408 | | } |
| 448 | 409 | | } |
| 449 | 410 | | |
| 450 | | − | int last(XEvent *e, arg_t a) { |
| 411 | + | int last(arg_t a) { |
| 451 | 412 | | if (mode == MODE_NORMAL && fileidx != filecnt - 1) { |
| 452 | 413 | | load_image(filecnt - 1); |
| 453 | 414 | | return 1; |
| @@ -460,7 +421,7 @@ int last(XEvent *e, arg_t a) { |
| 460 | 421 | | } |
| 461 | 422 | | } |
| 462 | 423 | | |
| 463 | | − | int remove_image(XEvent *e, arg_t a) { |
| 424 | + | int remove_image(arg_t a) { |
| 464 | 425 | | if (mode == MODE_NORMAL) { |
| 465 | 426 | | remove_file(fileidx, 1); |
| 466 | 427 | | load_image(fileidx >= filecnt ? filecnt - 1 : fileidx); |
| @@ -476,39 +437,83 @@ int remove_image(XEvent *e, arg_t a) { |
| 476 | 437 | | } |
| 477 | 438 | | } |
| 478 | 439 | | |
| 479 | | − | int move(XEvent *e, arg_t dir) { |
| 440 | + | int move(arg_t dir) { |
| 480 | 441 | | if (mode == MODE_NORMAL) |
| 481 | 442 | | return img_pan(&img, &win, dir, 0); |
| 482 | 443 | | else |
| 483 | 444 | | return tns_move_selection(&tns, &win, dir); |
| 484 | 445 | | } |
| 485 | 446 | | |
| 486 | | − | int pan_screen(XEvent *e, arg_t dir) { |
| 447 | + | int pan_screen(arg_t dir) { |
| 487 | 448 | | if (mode == MODE_NORMAL) |
| 488 | 449 | | return img_pan(&img, &win, dir, 1); |
| 489 | 450 | | else |
| 490 | 451 | | return 0; |
| 491 | 452 | | } |
| 492 | 453 | | |
| 493 | | − | int pan_edge(XEvent *e, arg_t dir) { |
| 454 | + | int pan_edge(arg_t dir) { |
| 494 | 455 | | if (mode == MODE_NORMAL) |
| 495 | 456 | | return img_pan_edge(&img, &win, dir); |
| 496 | 457 | | else |
| 497 | 458 | | return 0; |
| 498 | 459 | | } |
| 499 | 460 | | |
| 500 | | − | int drag(XEvent *e, arg_t a) { |
| 501 | | − | if (mode == MODE_NORMAL) { |
| 502 | | − | mox = e->xbutton.x; |
| 503 | | − | moy = e->xbutton.y; |
| 504 | | − | win_set_cursor(&win, CURSOR_HAND); |
| 505 | | − | timo_cursor = 0; |
| 506 | | − | dragging = 1; |
| 461 | + | /* Xlib helper function for drag() */ |
| 462 | + | Bool ismnotify(Display *d, XEvent *e, XPointer a) { |
| 463 | + | return e != NULL && e->type == MotionNotify; |
| 464 | + | } |
| 465 | + | |
| 466 | + | int drag(arg_t a) { |
| 467 | + | int dx = 0, dy = 0, i, ox, oy, x, y; |
| 468 | + | unsigned int ui; |
| 469 | + | Bool dragging = True, next = False; |
| 470 | + | XEvent e; |
| 471 | + | Window w; |
| 472 | + | |
| 473 | + | if (mode != MODE_NORMAL) |
| 474 | + | return 0; |
| 475 | + | if (!XQueryPointer(win.env.dpy, win.xwin, &w, &w, &i, &i, &ox, &oy, &ui)) |
| 476 | + | return 0; |
| 477 | + | |
| 478 | + | win_set_cursor(&win, CURSOR_HAND); |
| 479 | + | |
| 480 | + | while (dragging) { |
| 481 | + | if (!next) |
| 482 | + | XMaskEvent(win.env.dpy, |
| 483 | + | ButtonPressMask | ButtonReleaseMask | PointerMotionMask, &e); |
| 484 | + | switch (e.type) { |
| 485 | + | case ButtonPress: |
| 486 | + | case ButtonRelease: |
| 487 | + | dragging = False; |
| 488 | + | break; |
| 489 | + | case MotionNotify: |
| 490 | + | x = e.xmotion.x; |
| 491 | + | y = e.xmotion.y; |
| 492 | + | if (x >= 0 && x <= win.w && y >= 0 && y <= win.h) { |
| 493 | + | dx += x - ox; |
| 494 | + | dy += y - oy; |
| 495 | + | } |
| 496 | + | ox = x; |
| 497 | + | oy = y; |
| 498 | + | break; |
| 499 | + | } |
| 500 | + | if (dragging) |
| 501 | + | next = XCheckIfEvent(win.env.dpy, &e, ismnotify, None); |
| 502 | + | if ((!dragging || !next) && (dx != 0 || dy != 0)) { |
| 503 | + | if (img_move(&img, &win, dx, dy)) |
| 504 | + | img_render(&img, &win); |
| 505 | + | dx = dy = 0; |
| 506 | + | } |
| 507 | 507 | | } |
| 508 | + | |
| 509 | + | win_set_cursor(&win, CURSOR_ARROW); |
| 510 | + | timo_cursor = TO_CURSOR_HIDE; |
| 511 | + | timo_redraw = 0; |
| 512 | + | |
| 508 | 513 | | return 0; |
| 509 | 514 | | } |
| 510 | 515 | | |
| 511 | | − | int rotate(XEvent *e, arg_t dir) { |
| 516 | + | int rotate(arg_t dir) { |
| 512 | 517 | | if (mode == MODE_NORMAL) { |
| 513 | 518 | | if (dir == DIR_LEFT) { |
| 514 | 519 | | img_rotate_left(&img, &win); |
| @@ -521,7 +526,7 @@ int rotate(XEvent *e, arg_t dir) { |
| 521 | 526 | | return 0; |
| 522 | 527 | | } |
| 523 | 528 | | |
| 524 | | − | int zoom(XEvent *e, arg_t scale) { |
| 529 | + | int zoom(arg_t scale) { |
| 525 | 530 | | if (mode != MODE_NORMAL) |
| 526 | 531 | | return 0; |
| 527 | 532 | | if (scale > 0) |
| @@ -532,7 +537,7 @@ int zoom(XEvent *e, arg_t scale) { |
| 532 | 537 | | return img_zoom(&img, &win, 1.0); |
| 533 | 538 | | } |
| 534 | 539 | | |
| 535 | | − | int fit_to_win(XEvent *e, arg_t ret) { |
| 540 | + | int fit_to_win(arg_t ret) { |
| 536 | 541 | | if (mode == MODE_NORMAL) { |
| 537 | 542 | | if ((ret = img_fit_win(&img, &win))) |
| 538 | 543 | | img_center(&img, &win); |
| @@ -542,7 +547,7 @@ int fit_to_win(XEvent *e, arg_t ret) { |
| 542 | 547 | | } |
| 543 | 548 | | } |
| 544 | 549 | | |
| 545 | | − | int fit_to_img(XEvent *e, arg_t ret) { |
| 550 | + | int fit_to_img(arg_t ret) { |
| 546 | 551 | | int x, y; |
| 547 | 552 | | unsigned int w, h; |
| 548 | 553 | | |