plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

commit 9da5b4451365e33c4f561d74a99ad5c17ff20fed
parent 13582b1a899b9644071791e862c935384c27cb35
Author: Roger Peppe <rogpeppe@gmail.com>
Date:   Sat, 29 Mar 2025 13:10:49 +0000

cmd/devdraw: avoid use of X button state field

This bug is an intermittent annoyance and does not seem likely to be
fixed soon. It means that every so often my acme becomes unusable
because it behaves as if a mouse button is permanently set.

Avoid that issue by keeping track of mouse button state directly.

While we're about it, fix another annoying issue: under Linux the
FocusOut event reset the kstate field but not the kbuttons field,
meaning that the buttons state could inappropriately persist. This
happened occasionally by accident, but was easy to reproduce: with the
mouse button held down, drag outside the window and click Alt-Tab to
switch away from the window. We see a KeyDown event followed by FocusOut
but no KeyUp event.

Change-Id: I3708316478c80c41806d7157ae9929c6cd84b662

Diffstat:
Msrc/cmd/devdraw/x11-screen.c | 63++++++++++++---------------------------------------------------
1 file changed, 12 insertions(+), 51 deletions(-)

diff --git a/src/cmd/devdraw/x11-screen.c b/src/cmd/devdraw/x11-screen.c @@ -502,6 +502,7 @@ runxevent(XEvent *xev) * so clear out the keyboard state when we lose the focus. */ _x.kstate = 0; + _x.kbuttons = 0; _x.altdown = 0; gfx_abortcompose(w->client); break; @@ -1275,10 +1276,18 @@ _xtoplan9kbd(XEvent *e) return k+0; } +int +_xtoplan9buttons(unsigned int b) +{ + if(b == 0){ + return 0; + } + return 1<<(b-1); +} + static int _xtoplan9mouse(Xwin *w, XEvent *e, Mouse *m) { - int s; XButtonEvent *be; XMotionEvent *me; @@ -1307,54 +1316,18 @@ _xtoplan9mouse(Xwin *w, XEvent *e, Mouse *m) /* BUG? on mac need to inherit these from elsewhere? */ m->xy.x = be->x; m->xy.y = be->y; - s = be->state; m->msec = be->time; - switch(be->button){ - case 1: - s |= Button1Mask; - break; - case 2: - s |= Button2Mask; - break; - case 3: - s |= Button3Mask; - break; - case 4: - s |= Button4Mask; - break; - case 5: - s |= Button5Mask; - break; - } + m->buttons |= _xtoplan9buttons(be->button); break; case ButtonRelease: be = (XButtonEvent*)e; m->xy.x = be->x; m->xy.y = be->y; - s = be->state; m->msec = be->time; - switch(be->button){ - case 1: - s &= ~Button1Mask; - break; - case 2: - s &= ~Button2Mask; - break; - case 3: - s &= ~Button3Mask; - break; - case 4: - s &= ~Button4Mask; - break; - case 5: - s &= ~Button5Mask; - break; - } - break; + m->buttons &= ~_xtoplan9buttons(be->button); case MotionNotify: me = (XMotionEvent*)e; - s = me->state; m->xy.x = me->x; m->xy.y = me->y; m->msec = me->time; @@ -1363,18 +1336,6 @@ _xtoplan9mouse(Xwin *w, XEvent *e, Mouse *m) default: return -1; } - - m->buttons = 0; - if(s & Button1Mask) - m->buttons |= 1; - if(s & Button2Mask) - m->buttons |= 2; - if(s & Button3Mask) - m->buttons |= 4; - if(s & Button4Mask) - m->buttons |= 8; - if(s & Button5Mask) - m->buttons |= 16; return 0; }