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.
This commit is contained in:
parent
7fb0c0cc68
commit
ea7cd7b62f
82
x.c
82
x.c
|
@ -252,7 +252,7 @@ static char *opt_line = NULL;
|
||||||
static char *opt_name = NULL;
|
static char *opt_name = NULL;
|
||||||
static char *opt_title = NULL;
|
static char *opt_title = NULL;
|
||||||
|
|
||||||
static int oldbutton = 3; /* button event on startup: 3 = release */
|
static uint buttons; /* bit field of pressed buttons */
|
||||||
|
|
||||||
void
|
void
|
||||||
clipcopy(const Arg *dummy)
|
clipcopy(const Arg *dummy)
|
||||||
|
@ -364,61 +364,68 @@ mousesel(XEvent *e, int done)
|
||||||
void
|
void
|
||||||
mousereport(XEvent *e)
|
mousereport(XEvent *e)
|
||||||
{
|
{
|
||||||
int len, x = evcol(e), y = evrow(e),
|
int len, btn, code;
|
||||||
button = e->xbutton.button, state = e->xbutton.state;
|
int x = evcol(e), y = evrow(e);
|
||||||
|
int state = e->xbutton.state;
|
||||||
char buf[40];
|
char buf[40];
|
||||||
static int ox, oy;
|
static int ox, oy;
|
||||||
|
|
||||||
/* from urxvt */
|
if (e->type == MotionNotify) {
|
||||||
if (e->xbutton.type == MotionNotify) {
|
|
||||||
if (x == ox && y == oy)
|
if (x == ox && y == oy)
|
||||||
return;
|
return;
|
||||||
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
|
if (!IS_SET(MODE_MOUSEMOTION) && !IS_SET(MODE_MOUSEMANY))
|
||||||
return;
|
return;
|
||||||
/* MOUSE_MOTION: no reporting if no button is pressed */
|
/* MODE_MOUSEMOTION: no reporting if no button is pressed */
|
||||||
if (IS_SET(MODE_MOUSEMOTION) && oldbutton == 3)
|
if (IS_SET(MODE_MOUSEMOTION) && buttons == 0)
|
||||||
return;
|
return;
|
||||||
|
/* Set btn to lowest-numbered pressed button, or 12 if no
|
||||||
button = oldbutton + 32;
|
* buttons are pressed. */
|
||||||
ox = x;
|
for (btn = 1; btn <= 11 && !(buttons & (1<<(btn-1))); btn++)
|
||||||
oy = y;
|
;
|
||||||
|
code = 32;
|
||||||
} else {
|
} else {
|
||||||
if (!IS_SET(MODE_MOUSESGR) && e->xbutton.type == ButtonRelease) {
|
btn = e->xbutton.button;
|
||||||
button = 3;
|
/* Only buttons 1 through 11 can be encoded */
|
||||||
} else {
|
if (btn < 1 || btn > 11)
|
||||||
button -= Button1;
|
return;
|
||||||
if (button >= 7)
|
if (e->type == ButtonRelease) {
|
||||||
button += 128 - 7;
|
|
||||||
else if (button >= 3)
|
|
||||||
button += 64 - 3;
|
|
||||||
}
|
|
||||||
if (e->xbutton.type == ButtonPress) {
|
|
||||||
oldbutton = button;
|
|
||||||
ox = x;
|
|
||||||
oy = y;
|
|
||||||
} else if (e->xbutton.type == ButtonRelease) {
|
|
||||||
oldbutton = 3;
|
|
||||||
/* MODE_MOUSEX10: no button release reporting */
|
/* MODE_MOUSEX10: no button release reporting */
|
||||||
if (IS_SET(MODE_MOUSEX10))
|
if (IS_SET(MODE_MOUSEX10))
|
||||||
return;
|
return;
|
||||||
if (button == 64 || button == 65)
|
/* Don't send release events for the scroll wheel */
|
||||||
|
if (btn == 4 || btn == 5)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
code = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ox = x;
|
||||||
|
oy = y;
|
||||||
|
|
||||||
|
/* Encode btn into code. If no button is pressed for a motion event in
|
||||||
|
* MODE_MOUSEMANY, then encode it as a release. */
|
||||||
|
if ((!IS_SET(MODE_MOUSESGR) && e->type == ButtonRelease) || btn == 12)
|
||||||
|
code += 3;
|
||||||
|
else if (btn >= 8)
|
||||||
|
code += 128 + btn - 8;
|
||||||
|
else if (btn >= 4)
|
||||||
|
code += 64 + btn - 4;
|
||||||
|
else
|
||||||
|
code += btn - 1;
|
||||||
|
|
||||||
if (!IS_SET(MODE_MOUSEX10)) {
|
if (!IS_SET(MODE_MOUSEX10)) {
|
||||||
button += ((state & ShiftMask ) ? 4 : 0)
|
code += ((state & ShiftMask ) ? 4 : 0)
|
||||||
+ ((state & Mod4Mask ) ? 8 : 0)
|
+ ((state & Mod4Mask ) ? 8 : 0)
|
||||||
+ ((state & ControlMask) ? 16 : 0);
|
+ ((state & ControlMask) ? 16 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSESGR)) {
|
if (IS_SET(MODE_MOUSESGR)) {
|
||||||
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
|
len = snprintf(buf, sizeof(buf), "\033[<%d;%d;%d%c",
|
||||||
button, x+1, y+1,
|
code, x+1, y+1,
|
||||||
e->xbutton.type == ButtonRelease ? 'm' : 'M');
|
e->type == ButtonRelease ? 'm' : 'M');
|
||||||
} else if (x < 223 && y < 223) {
|
} else if (x < 223 && y < 223) {
|
||||||
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
|
len = snprintf(buf, sizeof(buf), "\033[M%c%c%c",
|
||||||
32+button, 32+x+1, 32+y+1);
|
32+code, 32+x+1, 32+y+1);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -461,9 +468,13 @@ mouseaction(XEvent *e, uint release)
|
||||||
void
|
void
|
||||||
bpress(XEvent *e)
|
bpress(XEvent *e)
|
||||||
{
|
{
|
||||||
|
int btn = e->xbutton.button;
|
||||||
struct timespec now;
|
struct timespec now;
|
||||||
int snap;
|
int snap;
|
||||||
|
|
||||||
|
if (1 <= btn && btn <= 11)
|
||||||
|
buttons |= 1 << (btn-1);
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
||||||
mousereport(e);
|
mousereport(e);
|
||||||
return;
|
return;
|
||||||
|
@ -472,7 +483,7 @@ bpress(XEvent *e)
|
||||||
if (mouseaction(e, 0))
|
if (mouseaction(e, 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (e->xbutton.button == Button1) {
|
if (btn == Button1) {
|
||||||
/*
|
/*
|
||||||
* If the user clicks below predefined timeouts specific
|
* If the user clicks below predefined timeouts specific
|
||||||
* snapping behaviour is exposed.
|
* snapping behaviour is exposed.
|
||||||
|
@ -686,6 +697,11 @@ xsetsel(char *str)
|
||||||
void
|
void
|
||||||
brelease(XEvent *e)
|
brelease(XEvent *e)
|
||||||
{
|
{
|
||||||
|
int btn = e->xbutton.button;
|
||||||
|
|
||||||
|
if (1 <= btn && btn <= 11)
|
||||||
|
buttons &= ~(1 << (btn-1));
|
||||||
|
|
||||||
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
if (IS_SET(MODE_MOUSE) && !(e->xbutton.state & forcemousemod)) {
|
||||||
mousereport(e);
|
mousereport(e);
|
||||||
return;
|
return;
|
||||||
|
@ -693,7 +709,7 @@ brelease(XEvent *e)
|
||||||
|
|
||||||
if (mouseaction(e, 1))
|
if (mouseaction(e, 1))
|
||||||
return;
|
return;
|
||||||
if (e->xbutton.button == Button1)
|
if (btn == Button1)
|
||||||
mousesel(e, 1);
|
mousesel(e, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue