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