mouseshortcuts: fix custom modifier on release
This line didn't work at mshortcuts at config.h:
  /*  mask       button   function  arg       release */
    { ShiftMask, Button2, selpaste, {.i = 0}, 1 },
and now it does work.
The issue was that XButtonEvent.state is "the logical state ... just prior
to the event", which means that on release the state has the Button2Mask
bit set because button2 was down just before it was released.
The issue didn't manifest with the default shift + middle-click on release
(to override mouse mode) because its specified modifier is XK_ANY_MOD, at
which case match(...) ignores any specific bits and simply returns true.
The issue also doesn't manifest on press, because prior to the event
Button<N> was not down and its mask bit is not set.
Fix by filtering out the mask of the button which we're currently matching.
We could have said "well, that's how button events behave, you should
use ShiftMask|Button2Mask for release", but this both not obvious to
figure out, and specifically here always filtering does not prevent
configuring any useful modifiers combination. So it's a win-win.
			
			
This commit is contained in:
		
				
					committed by
					
						 Hiltjo Posthuma
						Hiltjo Posthuma
					
				
			
			
				
	
			
			
			
						parent
						
							51e19ea11d
						
					
				
				
					commit
					28ad288399
				
			
							
								
								
									
										19
									
								
								x.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								x.c
									
									
									
									
									
								
							| @@ -171,6 +171,7 @@ static void kpress(XEvent *); | |||||||
| static void cmessage(XEvent *); | static void cmessage(XEvent *); | ||||||
| static void resize(XEvent *); | static void resize(XEvent *); | ||||||
| static void focus(XEvent *); | static void focus(XEvent *); | ||||||
|  | static uint buttonmask(uint); | ||||||
| static int mouseaction(XEvent *, uint); | static int mouseaction(XEvent *, uint); | ||||||
| static void brelease(XEvent *); | static void brelease(XEvent *); | ||||||
| static void bpress(XEvent *); | static void bpress(XEvent *); | ||||||
| @@ -423,16 +424,30 @@ mousereport(XEvent *e) | |||||||
| 	ttywrite(buf, len, 0); | 	ttywrite(buf, len, 0); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | uint | ||||||
|  | buttonmask(uint button) | ||||||
|  | { | ||||||
|  | 	return button == Button1 ? Button1Mask | ||||||
|  | 	     : button == Button2 ? Button2Mask | ||||||
|  | 	     : button == Button3 ? Button3Mask | ||||||
|  | 	     : button == Button4 ? Button4Mask | ||||||
|  | 	     : button == Button5 ? Button5Mask | ||||||
|  | 	     : 0; | ||||||
|  | } | ||||||
|  |  | ||||||
| int | int | ||||||
| mouseaction(XEvent *e, uint release) | mouseaction(XEvent *e, uint release) | ||||||
| { | { | ||||||
| 	MouseShortcut *ms; | 	MouseShortcut *ms; | ||||||
|  |  | ||||||
|  | 	/* ignore Button<N>mask for Button<N> - it's set on release */ | ||||||
|  | 	uint state = e->xbutton.state & ~buttonmask(e->xbutton.button); | ||||||
|  |  | ||||||
| 	for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { | 	for (ms = mshortcuts; ms < mshortcuts + LEN(mshortcuts); ms++) { | ||||||
| 		if (ms->release == release && | 		if (ms->release == release && | ||||||
| 		    ms->button == e->xbutton.button && | 		    ms->button == e->xbutton.button && | ||||||
| 		    (match(ms->mod, e->xbutton.state) ||  /* exact or forced */ | 		    (match(ms->mod, state) ||  /* exact or forced */ | ||||||
| 		     match(ms->mod, e->xbutton.state & ~forcemousemod))) { | 		     match(ms->mod, state & ~forcemousemod))) { | ||||||
| 			ms->func(&(ms->arg)); | 			ms->func(&(ms->arg)); | ||||||
| 			return 1; | 			return 1; | ||||||
| 		} | 		} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user