From 85bfd19a7beb628f24b051d23e6c94ecc6e4babc Mon Sep 17 00:00:00 2001 From: Xiao-Yong Jin Date: Thu, 11 Apr 2019 19:43:11 -0500 Subject: [PATCH] devdraw/x11: fix modifier key handling for some XkbOptions Certain XkbOptions in X11 would change keysyms for modifier keys between the key press and key release. For example, under the XkbOptions "grp:shifts_toggle", though shift keys remain Shift_L/R when pressed, they become ISO_Group_Next/Prev when released. This behavior makes devdraw unable to detect the release event correctly and as a result mouse button 1 click always interpreted as button 3 event after a shift key is used. --- src/cmd/devdraw/x11-screen.c | 43 ++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/cmd/devdraw/x11-screen.c b/src/cmd/devdraw/x11-screen.c index 0bbc25d6..9490ab8f 100644 --- a/src/cmd/devdraw/x11-screen.c +++ b/src/cmd/devdraw/x11-screen.c @@ -312,6 +312,8 @@ xloop(void) } } +static int kcodecontrol, kcodealt, kcodeshift; + /* * Handle an incoming X event. */ @@ -319,12 +321,15 @@ static void runxevent(XEvent *xev) { int c; + int modp; KeySym k; static Mouse m; XButtonEvent *be; XKeyEvent *ke; Xwin *w; + modp = 0; + #ifdef SHOWEVENT static int first = 1; if(first){ @@ -424,20 +429,34 @@ runxevent(XEvent *xev) break; } - switch(k) { - case XK_Control_L: - if(xev->type == KeyPress) + if(xev->type == KeyPress) + switch(k) { + case XK_Control_L: + case XK_Control_R: + kcodecontrol = ke->keycode; c |= ControlMask; - else - c &= ~ControlMask; - goto kbutton; - case XK_Alt_L: - case XK_Shift_L: - if(xev->type == KeyPress) + modp = 1; + break; + case XK_Alt_L: + case XK_Alt_R: + kcodealt = ke->keycode; + // fall through + case XK_Shift_L: + case XK_Shift_R: + kcodeshift = ke->keycode; c |= Mod1Mask; - else + modp = 1; + } + else { + if(ke->keycode == kcodecontrol){ + c &= ~ControlMask; + modp = 1; + } else if(ke->keycode == kcodealt || ke->keycode == kcodeshift){ c &= ~Mod1Mask; - kbutton: + modp = 1; + } + } + if(modp){ _x.kstate = c; if(m.buttons || _x.kbuttons) { _x.altdown = 0; // used alt @@ -447,8 +466,8 @@ runxevent(XEvent *xev) if(c & Mod1Mask) _x.kbuttons |= 4; gfx_mousetrack(w->client, m.xy.x, m.xy.y, m.buttons|_x.kbuttons, m.msec); - break; } + modp = 0; } if(xev->type != KeyPress)