aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobert <robertrussell.72001@gmail.com>2022-01-08 11:40:34 -0800
committerHiltjo Posthuma <hiltjo@codemadness.org>2022-01-10 17:04:01 +0100
commitea7cd7b62fdfa6a1fbd882d1565d557577f2cf32 (patch)
tree5eafff9b5a615369874408a9820471982ac727b3
parent7fb0c0cc681f36be2ad12091ef93a41671f32738 (diff)
downloadst-patched-ea7cd7b62fdfa6a1fbd882d1565d557577f2cf32.tar.bz2
st-patched-ea7cd7b62fdfa6a1fbd882d1565d557577f2cf32.tar.xz
st-patched-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.
-rw-r--r--x.c86
1 files changed, 51 insertions, 35 deletions
diff --git a/x.c b/x.c
index 8a16faa..5f4ea73 100644
--- a/x.c
+++ b/x.c
@@ -252,7 +252,7 @@ static char *opt_line = NULL;
252static char *opt_name = NULL; 252static char *opt_name = NULL;
253static char *opt_title = NULL; 253static char *opt_title = NULL;
254 254
255static int oldbutton = 3; /* button event on startup: 3 = release */ 255static uint buttons; /* bit field of pressed buttons */
256 256
257void 257void
258clipcopy(const Arg *dummy) 258clipcopy(const Arg *dummy)
@@ -364,61 +364,68 @@ mousesel(XEvent *e, int done)
364void 364void
365mousereport(XEvent *e) 365mousereport(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)
461void 468void
462bpress(XEvent *e) 469bpress(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)
686void 697void
687brelease(XEvent *e) 698brelease(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