xref: /plan9/sys/src/cmd/aux/accupoint.c (revision 80ee5cbfe36716af62da8896207e9763b8e3d760)
159cc4ca5SDavid du Colombier #include <u.h>
259cc4ca5SDavid du Colombier #include <libc.h>
359cc4ca5SDavid du Colombier #include <draw.h>
459cc4ca5SDavid du Colombier #include <event.h>
559cc4ca5SDavid du Colombier 
659cc4ca5SDavid du Colombier /*
759cc4ca5SDavid du Colombier  * Convert AccuPoint buttons 4 and 5 to a simulation of button 2.
859cc4ca5SDavid du Colombier  * The buttons generate down events, repeat, and have no up events,
959cc4ca5SDavid du Colombier  * so it's a struggle. This program turns the left button into a near-as-
1059cc4ca5SDavid du Colombier  * possible simulation of a regular button 2, but it can only sense up
1159cc4ca5SDavid du Colombier  * events by timeout, so it's sluggish.  Thus it also turns the right button
1259cc4ca5SDavid du Colombier  * into a click on button 2, useful for acme and chords.
1359cc4ca5SDavid du Colombier  */
1459cc4ca5SDavid du Colombier 
1559cc4ca5SDavid du Colombier typedef struct M M;
1659cc4ca5SDavid du Colombier 
1759cc4ca5SDavid du Colombier struct M
1859cc4ca5SDavid du Colombier {
1959cc4ca5SDavid du Colombier 	Mouse;
2059cc4ca5SDavid du Colombier 	int	byte;
2159cc4ca5SDavid du Colombier };
2259cc4ca5SDavid du Colombier 
2359cc4ca5SDavid du Colombier int	button2;
2459cc4ca5SDavid du Colombier int	interrupted;
2559cc4ca5SDavid du Colombier 
2659cc4ca5SDavid du Colombier int
readmouse(M * m)2759cc4ca5SDavid du Colombier readmouse(M *m)
2859cc4ca5SDavid du Colombier {
2959cc4ca5SDavid du Colombier 	char buf[1+4*12];
3059cc4ca5SDavid du Colombier 	int n;
3159cc4ca5SDavid du Colombier 
3259cc4ca5SDavid du Colombier 	n = read(0, buf, sizeof buf);
3359cc4ca5SDavid du Colombier 	if(n < 0)
3459cc4ca5SDavid du Colombier 		return n;
3559cc4ca5SDavid du Colombier 	if(n != sizeof buf)
3659cc4ca5SDavid du Colombier 		return 0;
3759cc4ca5SDavid du Colombier 	m->byte = buf[0];
3859cc4ca5SDavid du Colombier 	m->xy.x =  atoi(buf+1+0*12);
3959cc4ca5SDavid du Colombier 	m->xy.y =  atoi(buf+1+1*12);
4059cc4ca5SDavid du Colombier 	m->buttons =  atoi(buf+1+2*12);
4159cc4ca5SDavid du Colombier 	m->msec =  atoi(buf+1+3*12);
4259cc4ca5SDavid du Colombier 	return 1;
4359cc4ca5SDavid du Colombier }
4459cc4ca5SDavid du Colombier 
4559cc4ca5SDavid du Colombier void
writemouse(M * m)4659cc4ca5SDavid du Colombier writemouse(M *m)
4759cc4ca5SDavid du Colombier {
4859cc4ca5SDavid du Colombier 	print("%c%11d %11d %11d %11ld ",
4959cc4ca5SDavid du Colombier 		m->byte,
5059cc4ca5SDavid du Colombier 		m->xy.x,
5159cc4ca5SDavid du Colombier 		m->xy.y,
52*80ee5cbfSDavid du Colombier 		m->buttons&7,
5359cc4ca5SDavid du Colombier 		m->msec);
5459cc4ca5SDavid du Colombier }
5559cc4ca5SDavid du Colombier 
5659cc4ca5SDavid du Colombier void
notifyf(void *,char * s)5759cc4ca5SDavid du Colombier notifyf(void*, char *s)
5859cc4ca5SDavid du Colombier {
5959cc4ca5SDavid du Colombier 	if(strcmp(s, "alarm") == 0)
6059cc4ca5SDavid du Colombier 		interrupted = 1;
6159cc4ca5SDavid du Colombier 	noted(NCONT);
6259cc4ca5SDavid du Colombier }
6359cc4ca5SDavid du Colombier 
6459cc4ca5SDavid du Colombier void
main(void)6559cc4ca5SDavid du Colombier main(void)
6659cc4ca5SDavid du Colombier {
6759cc4ca5SDavid du Colombier 	M m, om;
6859cc4ca5SDavid du Colombier 	int n;
6959cc4ca5SDavid du Colombier 
7059cc4ca5SDavid du Colombier 	notify(notifyf);
7159cc4ca5SDavid du Colombier 	memset(&m, 0, sizeof m);
7259cc4ca5SDavid du Colombier 	om = m;
7359cc4ca5SDavid du Colombier 	for(;;){
7459cc4ca5SDavid du Colombier 		interrupted = 0;
7559cc4ca5SDavid du Colombier 		/* first click waits 500ms before repeating; after that they're 150, but that's ok */
7659cc4ca5SDavid du Colombier 		if(button2)
7759cc4ca5SDavid du Colombier 			alarm(550);
7859cc4ca5SDavid du Colombier 		n = readmouse(&m);
7959cc4ca5SDavid du Colombier 		if(button2)
8059cc4ca5SDavid du Colombier 			alarm(0);
8159cc4ca5SDavid du Colombier 		if(interrupted){
8259cc4ca5SDavid du Colombier 			/* timed out; clear button 2 */
8359cc4ca5SDavid du Colombier 			om.buttons &= ~2;
8459cc4ca5SDavid du Colombier 			button2 = 0;
8559cc4ca5SDavid du Colombier 			writemouse(&om);
8659cc4ca5SDavid du Colombier 			continue;
8759cc4ca5SDavid du Colombier 		}
8859cc4ca5SDavid du Colombier 		if(n <= 0)
8959cc4ca5SDavid du Colombier 			break;
9059cc4ca5SDavid du Colombier 		/* avoid bounce caused by button 5 click */
9159cc4ca5SDavid du Colombier 		if((om.buttons&16) && (m.buttons&16)){
9259cc4ca5SDavid du Colombier 			om.buttons &= ~16;
9359cc4ca5SDavid du Colombier 			continue;
9459cc4ca5SDavid du Colombier 		}
9559cc4ca5SDavid du Colombier 		if(m.buttons & 2)
9659cc4ca5SDavid du Colombier 			button2 = 0;
9759cc4ca5SDavid du Colombier 		else{
9859cc4ca5SDavid du Colombier 			/* only check 4 and 5 if 2 isn't down of its own accord */
9959cc4ca5SDavid du Colombier 			if(m.buttons & 16){
10059cc4ca5SDavid du Colombier 				/* generate quick button 2 click */
10159cc4ca5SDavid du Colombier 				button2 = 0;
10259cc4ca5SDavid du Colombier 				m.buttons |= 2;
10359cc4ca5SDavid du Colombier 				writemouse(&m);
10459cc4ca5SDavid du Colombier 				m.buttons &= ~2;
10559cc4ca5SDavid du Colombier 				/* fall through to generate up event */
10659cc4ca5SDavid du Colombier 			}else if(m.buttons & 8){
10759cc4ca5SDavid du Colombier 				/* press and hold button 2 */
10859cc4ca5SDavid du Colombier 				button2 = 1;
10959cc4ca5SDavid du Colombier 			}
11059cc4ca5SDavid du Colombier 		}
11159cc4ca5SDavid du Colombier 		if(button2)
11259cc4ca5SDavid du Colombier 			m.buttons |= 2;
113*80ee5cbfSDavid du Colombier 		if(m.byte!=om.byte || m.buttons!=om.buttons || !eqpt(m.xy, om.xy))
11459cc4ca5SDavid du Colombier 			writemouse(&m);
11559cc4ca5SDavid du Colombier 		om = m;
11659cc4ca5SDavid du Colombier 	}
11759cc4ca5SDavid du Colombier }
118