diff options
| author | robert <robertrussell.72001@gmail.com> | 2022-01-08 11:40:34 -0800 |
|---|---|---|
| committer | Hiltjo Posthuma <hiltjo@codemadness.org> | 2022-01-10 17:04:01 +0100 |
| commit | ea7cd7b62fdfa6a1fbd882d1565d557577f2cf32 (patch) | |
| tree | 5eafff9b5a615369874408a9820471982ac727b3 /x.c | |
| parent | bump version to 0.8.5 (diff) | |
| download | st-ea7cd7b62fdfa6a1fbd882d1565d557577f2cf32.tar.gz st-ea7cd7b62fdfa6a1fbd882d1565d557577f2cf32.zip | |
Fix mousereport
This patch replaces the previous one I sent.
The following changes are made in this patch:
- Fix tracking of pressed buttons. Previously, pressing two buttons and
then releasing one would make st think no buttons are pressed, which
in particular broke MODE_MOUSEMOTION.
- Always send the lowest-numbered pressed button on motion events; when
no button is pressed for a motion event in MODE_MOUSEMANY, then send
a release. This matches the behaviour of xterm. (Previously, st sent
the most recently pressed button in the motion report.)
- Remove UB (?) access to potentially inactive struct member
e->xbutton.button of XEvent union.
- Fix (unlikely) possibility of overflow for large button numbers.
The one discrepancy I found between st and xterm is that xterm sometimes
encodes buttons with large numbers (>5) strangely. E.g., xterm reports
presses of buttons 8 and 9 as releases, whereas st properly (?) encodes
them as presses.
Diffstat (limited to 'x.c')
| -rw-r--r-- | x.c | 86 |
1 files changed, 51 insertions, 35 deletions
| @@ -252,7 +252,7 @@ static char *opt_line = NULL; | |||
| 252 | static char *opt_name = NULL; | 252 | static char *opt_name = NULL; |
| 253 | static char *opt_title = NULL; | 253 | static char *opt_title = NULL; |
| 254 | 254 | ||
| 255 | static int oldbutton = 3; /* button event on startup: 3 = release */ | 255 | static uint buttons; /* bit field of pressed buttons */ |
| 256 | 256 | ||
| 257 | void | 257 | void |
| 258 | clipcopy(const Arg *dummy) | 258 | clipcopy(const Arg *dummy) |
| @@ -364,61 +364,68 @@ mousesel(XEvent *e, int done) | |||
| 364 | void | 364 | void |
| 365 | mousereport(XEvent *e) | 365 | mousereport(XEvent *e) |
| 366 | { | 366 | { |
| 367 | int len, x = evcol(e), y = evrow(e), | 367 | int len, btn, code; |
| 368 | button = e->xbutton.button, state = e->xbutton.state; | 368 | int x = evcol(e), y = evrow(e); |
| 369 | int state = e->xbutton.state; | ||
| 369 | char buf[40]; | 370 | char buf[40]; |
| 370 | static int ox, oy; | 371 | static int ox, oy; |
| 371 | 372 | ||
| 372 | /* from urxvt */ | 373 | if (e->type == MotionNotify) { |
| 373 | if (e->xbutton.type == MotionNotify) { | ||
| 374 | if (x == ox && y == oy) | 374 | if (x == ox && y == oy) |
| 375 | return; | 375 | return; |
| 376 | if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) | 376 | if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY)) |
| 377 | return; | 377 | return; |
| 378 | /* MOUSE_MOTION: no reporting if no button is pressed */ | 378 | /* MODE_MOUSEMOTION: no reporting if no button is pressed */ |
| 379 | if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3) | 379 | if (IS_SET(MODE_MOUSEMOTION) && buttons == 0) |
| 380 | return; | 380 | return; |
| 381 | 381 | /* Set btn to lowest-numbered pressed button, or 12 if no | |
| 382 | button = oldbutton + 32; | 382 | * buttons are pressed. */ |
| 383 | ox = x; | 383 | for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++) |
| 384 | oy = y; | 384 | ; |
| 385 | code = 32; | ||
| 385 | } else { | 386 | } else { |
| 386 | if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) { | 387 | btn = e->xbutton.button; |
| 387 | button = 3; | 388 | /* Only buttons 1 through 11 can be encoded */ |
| 388 | } else { | 389 | if (btn < 1 || btn > 11) |
| 389 | button -= Button1; | 390 | return; |
| 390 | if (button >= 7) | 391 | if (e->type == ButtonRelease) { |
| 391 | button += 128 - 7; | ||
| 392 | else if (button >= 3) | ||
| 393 | button += 64 - 3; | ||
| 394 | } | ||
| 395 | if (e->xbutton.type == ButtonPress) { | ||
| 396 | oldbutton = button; | ||
| 397 | ox = x; | ||
| 398 | oy = y; | ||
| 399 | } else if (e->xbutton.type == ButtonRelease) { | ||
| 400 | oldbutton = 3; | ||
| 401 | /* MODE_MOUSEX10: no button release reporting */ | 392 | /* MODE_MOUSEX10: no button release reporting */ |
| 402 | if (IS_SET(MODE_MOUSEX10)) | 393 | if (IS_SET(MODE_MOUSEX10)) |
| 403 | return; | 394 | return; |
| 404 | if (button == 64 || button == 65) | 395 | /* Don't send release events for the scroll wheel */ |
| 396 | if (btn == 4 || btn == 5) | ||
| 405 | return; | 397 | return; |
| 406 | } | 398 | } |
| 399 | code = 0; | ||
| 407 | } | 400 | } |
| 408 | 401 | ||
| 402 | ox = x; | ||
| 403 | oy = y; | ||
| 404 | |||
| 405 | /* Encode btn into code. If no button is pressed for a motion event in | ||
| 406 | * MODE_MOUSEMANY, then encode it as a release. */ | ||
| 407 | if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12) | ||
| 408 | code += 3; | ||
| 409 | else if (btn >= 8) | ||
| 410 | code += 128 + btn - 8; | ||
| 411 | else if (btn >= 4) | ||
| 412 | code += 64 + btn - 4; | ||
| 413 | else | ||
| 414 | code += btn - 1; | ||
| 415 | |||
| 409 | if (!IS_SET(MODE_MOUSEX10)) { | 416 | if (!IS_SET(MODE_MOUSEX10)) { |
| 410 | button += ((state & ShiftMask ) ? 4 : 0) | 417 | code += ((state & ShiftMask ) ? 4 : 0) |
| 411 | + ((state & Mod4Mask ) ? 8 : 0) | 418 | + ((state & Mod4Mask ) ? 8 : 0) |
| 412 | + ((state & ControlMask) ? 16 : 0); | 419 | + ((state & ControlMask) ? 16 : 0); |
| 413 | } | 420 | } |
| 414 | 421 | ||
| 415 | if (IS_SET(MODE_MOUSESGR)) { | 422 | if (IS_SET(MODE_MOUSESGR)) { |
| 416 | len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", | 423 | len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c", |
| 417 | button, x+1, y+1, | 424 | code, x+1, y+1, |
| 418 | e->xbutton.type == ButtonRelease ? 'm' : 'M'); | 425 | e->type == ButtonRelease ? 'm' : 'M'); |
| 419 | } else if (x < 223 && y < 223) { | 426 | } else if (x < 223 && y < 223) { |
| 420 | len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", | 427 | len = snprintf(buf, sizeof(buf), "\033[M%c%c%c", |
| 421 | 32+button, 32+x+1, 32+y+1); | 428 | 32+code, 32+x+1, 32+y+1); |
| 422 | } else { | 429 | } else { |
| 423 | return; | 430 | return; |
| 424 | } | 431 | } |
| @@ -461,9 +468,13 @@ mouseaction(XEvent *e, uint release) | |||
| 461 | void | 468 | void |
| 462 | bpress(XEvent *e) | 469 | bpress(XEvent *e) |
| 463 | { | 470 | { |
| 471 | int btn = e->xbutton.button; | ||
| 464 | struct timespec now; | 472 | struct timespec now; |
| 465 | int snap; | 473 | int snap; |
| 466 | 474 | ||
| 475 | if (1 <= btn && btn <= 11) | ||
| 476 | buttons |= 1 << (btn-1); | ||
| 477 | |||
| 467 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { | 478 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { |
| 468 | mousereport(e); | 479 | mousereport(e); |
| 469 | return; | 480 | return; |
| @@ -472,7 +483,7 @@ bpress(XEvent *e) | |||
| 472 | if (mouseaction(e, 0)) | 483 | if (mouseaction(e, 0)) |
| 473 | return; | 484 | return; |
| 474 | 485 | ||
| 475 | if (e->xbutton.button == Button1) { | 486 | if (btn == Button1) { |
| 476 | /* | 487 | /* |
| 477 | * If the user clicks below predefined timeouts specific | 488 | * If the user clicks below predefined timeouts specific |
| 478 | * snapping behaviour is exposed. | 489 | * snapping behaviour is exposed. |
| @@ -686,6 +697,11 @@ xsetsel(char *str) | |||
| 686 | void | 697 | void |
| 687 | brelease(XEvent *e) | 698 | brelease(XEvent *e) |
| 688 | { | 699 | { |
| 700 | int btn = e->xbutton.button; | ||
| 701 | |||
| 702 | if (1 <= btn && btn <= 11) | ||
| 703 | buttons &= ~(1 << (btn-1)); | ||
| 704 | |||
| 689 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { | 705 | if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) { |
| 690 | mousereport(e); | 706 | mousereport(e); |
| 691 | return; | 707 | return; |
| @@ -693,7 +709,7 @@ brelease(XEvent *e) | |||
| 693 | 709 | ||
| 694 | if (mouseaction(e, 1)) | 710 | if (mouseaction(e, 1)) |
| 695 | return; | 711 | return; |
| 696 | if (e->xbutton.button == Button1) | 712 | if (btn == Button1) |
| 697 | mousesel(e, 1); | 713 | mousesel(e, 1); |
| 698 | } | 714 | } |
| 699 | 715 | ||
