## diffname bitsy/devpenmouse.c 2000/1021 ## diff -e /dev/null /n/emeliedump/2000/1021/sys/src/9/bitsy/devpenmouse.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #define Image IMAGE #include #include #include #include "screen.h" typedef struct Mouseinfo Mouseinfo; typedef struct Mousestate Mousestate; typedef struct Calibration Calibration; struct Calibration { long scalex; long scaley; long transx; long transy; } calibration = { -0x10000*0x400/320, -0x10000*0x400/240, 320, 240 }; struct Mousestate { Point xy; /* mouse.xy */ int buttons; /* mouse.buttons */ ulong counter; /* increments every update */ ulong msec; /* time of last event */ }; struct Mouseinfo { Mousestate; ulong lastcounter; /* value when /dev/mouse read */ Rendez r; Ref; QLock; int open; int inopen; Mousestate queue[16]; /* circular buffer of click events */ int ri; /* read index into queue */ int wi; /* write index into queue */ uchar qfull; /* queue is full */ }; Mouseinfo mouse; int mouseshifted; int penmousechanged(void*); static void penmousetrack(int b, int x, int y); enum{ Qdir, Qmouse, Qmousein, Qmousectl, }; static Dirtab mousedir[]={ "mouse", {Qmouse}, 0, 0666, "mousein", {Qmousein}, 0, 0220, "mousectl", {Qmousectl}, 0, 0220, }; static uchar buttonmap[8] = { 0, 1, 2, 3, 4, 5, 6, 7, }; static int mouseswap; extern Memimage* gscreen; void penbutton(int up, int b) { if (up) mouse.buttons &= ~ (1 << b); else mouse.buttons |= 1 << b; penmousetrack(mouse.buttons, -1, -1); } void pentrackxy(int x, int y) { if (x == -1) { /* pen up. associate with button 1, 2, 3 up */ if (mouse.buttons & 0x7) mouse.buttons &= ~0x7; } else { x = (x<<16)/calibration.scalex + calibration.transx; y = (y<<16)/calibration.scaley + calibration.transy; } penmousetrack(mouse.buttons, x, y); } static void penmousereset(void) { if(!conf.monitor) return; } static void penmouseinit(void) { if(!conf.monitor) return; } static Chan* penmouseattach(char *spec) { if(!conf.monitor) error(Egreg); return devattach('m', spec); } static Chan* penmouseclone(Chan *c, Chan *nc) { nc = devclone(c, nc); if(c->qid.path != CHDIR) incref(&mouse); return nc; } static int penmousewalk(Chan *c, char *name) { return devwalk(c, name, mousedir, nelem(mousedir), devgen); } static void penmousestat(Chan *c, char *db) { devstat(c, db, mousedir, nelem(mousedir), devgen); } static Chan* penmouseopen(Chan *c, int omode) { switch(c->qid.path){ case CHDIR: if(omode != OREAD) error(Eperm); break; case Qmouse: lock(&mouse); if(mouse.open){ unlock(&mouse); error(Einuse); } mouse.open = 1; mouse.ref++; unlock(&mouse); break; case Qmousein: /* error("disabled"); */ lock(&mouse); if(mouse.inopen){ unlock(&mouse); error(Einuse); } mouse.inopen = 1; unlock(&mouse); break; default: incref(&mouse); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } static void penmousecreate(Chan*, char*, int, ulong) { if(!conf.monitor) error(Egreg); error(Eperm); } static void penmouseclose(Chan *c) { if(c->qid.path!=CHDIR && (c->flag&COPEN)){ lock(&mouse); if(c->qid.path == Qmouse) mouse.open = 0; else if(c->qid.path == Qmousein){ mouse.inopen = 0; unlock(&mouse); return; } --mouse.ref; unlock(&mouse); } } static long penmouseread(Chan *c, void *va, long n, vlong) { char buf[4*12+1]; static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; Mousestate m; int b; switch(c->qid.path){ case CHDIR: return devdirread(c, va, n, mousedir, nelem(mousedir), devgen); case Qmouse: while(penmousechanged(0) == 0) sleep(&mouse.r, penmousechanged, 0); mouse.qfull = 0; /* * No lock of the indicies is necessary here, because ri is only * updated by us, and there is only one mouse reader * at a time. I suppose that more than one process * could try to read the fd at one time, but such behavior * is degenerate and already violates the calling * conventions for sleep above. */ if(mouse.ri != mouse.wi) { m = mouse.queue[mouse.ri]; if(++mouse.ri == nelem(mouse.queue)) mouse.ri = 0; } else { m = mouse.Mousestate; } b = buttonmap[m.buttons&7]; /* put buttons 4 and 5 back in */ b |= m.buttons & (3<<3); sprint(buf, "m%11d %11d %11d %11lud", m.xy.x, m.xy.y, b, m.msec); mouse.lastcounter = m.counter; if(n > 1+4*12) n = 1+4*12; memmove(va, buf, n); return n; } return 0; } static void setbuttonmap(char* map) { int i, x, one, two, three; one = two = three = 0; for(i = 0; i < 3; i++){ if(map[i] == 0) error(Ebadarg); if(map[i] == '1'){ if(one) error(Ebadarg); one = 1<qid.path){ case CHDIR: error(Eisdir); case Qmousectl: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); if(buf[n - 1] == '\n') buf[n-1] = 0; else buf[n] = 0; nf = getfields(buf, field, 3, 1, " "); if(strcmp(field[0], "swap") == 0){ if(mouseswap) setbuttonmap("123"); else setbuttonmap("321"); mouseswap ^= 1; } else if(strcmp(field[0], "calibrate") == 0){ if (nf == 1) { calibration.scalex = 1; calibration.scaley = 1; calibration.transx = 0; calibration.transy = 0; } else if (nf == 5) { calibration.scalex = strtol(field[1], nil, 0); calibration.scaley = strtol(field[2], nil, 0); calibration.transx = strtol(field[3], nil, 0); calibration.transy = strtol(field[4], nil, 0); } } return n; case Qmousein: if(n > sizeof buf-1) n = sizeof buf -1; memmove(buf, va, n); buf[n] = 0; p = 0; pt.x = strtol(buf+1, &p, 0); if(p == 0) error(Eshort); pt.y = strtol(p, &p, 0); if(p == 0) error(Eshort); b = strtol(p, &p, 0); penmousetrack(b, pt.x, pt.y); return n; case Qmouse: if(n > sizeof buf-1) n = sizeof buf -1; memmove(buf, va, n); buf[n] = 0; p = 0; pt.x = strtoul(buf+1, &p, 0); if(p == 0) error(Eshort); pt.y = strtoul(p, 0, 0); qlock(&mouse); if(ptinrect(pt, gscreen->r)) penmousetrack(mouse.buttons, pt.x, pt.y); qunlock(&mouse); return n; } error(Egreg); return -1; } Dev penmousedevtab = { 'm', "penmouse", penmousereset, penmouseinit, penmouseattach, penmouseclone, penmousewalk, penmousestat, penmouseopen, penmousecreate, penmouseclose, penmouseread, devbread, penmousewrite, devbwrite, devremove, devwstat, }; /* * called at interrupt level to update the structure and * awaken any waiting procs. */ static void penmousetrack(int b, int x, int y) { int lastb; if(gscreen==nil) return; if (x >= 0) { mouse.xy = Pt(x, y); } lastb = mouse.buttons; mouse.buttons = b; mouse.counter++; mouse.msec = TK2MS(MACHP(0)->ticks); /* * if the queue fills, we discard the entire queue and don't * queue any more events until a reader polls the mouse. */ if(!mouse.qfull && lastb != b) { /* add to ring */ mouse.queue[mouse.wi] = mouse.Mousestate; if(++mouse.wi == nelem(mouse.queue)) mouse.wi = 0; if(mouse.wi == mouse.ri) mouse.qfull = 1; } wakeup(&mouse.r); } int penmousechanged(void*) { return mouse.lastcounter != mouse.counter; } Point penmousexy(void) { return mouse.xy; } . ## diffname bitsy/devpenmouse.c 2000/1024 ## diff -e /n/emeliedump/2000/1021/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1024/sys/src/9/bitsy/devpenmouse.c 341c } else print("calibrate %d fields\n", nf); . 322c nf = getfields(buf, field, 5, 1, " "); . 306c char buf[64], *field[5]; . 247c m.buttons, . 242,244d 214d 207d 97a if ((mouse.buttons & 0x7) == 0) mouse.buttons |= 0x1; . 93,94c mouse.buttons &= ~0x7; . ## diffname bitsy/devpenmouse.c 2000/1025 ## diff -e /n/emeliedump/2000/1024/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1025/sys/src/9/bitsy/devpenmouse.c 414d 409,412c if (x >= 0) . 85c mouse.buttons |= b; . 83c mouse.buttons &= ~b; . ## diffname bitsy/devpenmouse.c 2000/1101 ## diff -e /n/emeliedump/2000/1025/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1101/sys/src/9/bitsy/devpenmouse.c 328,329c calibration.scalex = 1<<16; calibration.scaley = 1<<16; . 95,96c x = ((x*calibration.scalex)>>16) + calibration.transx; y = ((y*calibration.scaley)>>16) + calibration.transy; . ## diffname bitsy/devpenmouse.c 2000/1102 ## diff -e /n/emeliedump/2000/1101/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1102/sys/src/9/bitsy/devpenmouse.c 25,28c -23540, -16858, 342, 252 . ## diffname bitsy/devpenmouse.c 2000/1104 ## diff -e /n/emeliedump/2000/1102/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1104/sys/src/9/bitsy/devpenmouse.c 27,28c 23540, 252, 342 . 25d ## diffname bitsy/devpenmouse.c 2000/1120 ## diff -e /n/emeliedump/2000/1104/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1120/sys/src/9/bitsy/devpenmouse.c 25,28c -16435, 23275, 253, -23 . ## diffname bitsy/devpenmouse.c 2000/1130 ## diff -e /n/emeliedump/2000/1120/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1130/sys/src/9/bitsy/devpenmouse.c 427a drawactive(1); . ## diffname bitsy/devpenmouse.c 2000/1206 ## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1206/sys/src/9/bitsy/devpenmouse.c 226c * No lock of the indices is necessary here, because ri is only . ## diffname bitsy/devpenmouse.c 2000/1207 ## diff -e /n/emeliedump/2000/1206/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1207/sys/src/9/bitsy/devpenmouse.c 97,98c if ((mouse.buttons & 0x1f) == 0) { if (mouse.modifiers) mouse.buttons |= mouse.modifiers; else mouse.buttons |= 0x1; } . 92,93c /* pen up. associate with button 1 through 5 up */ mouse.buttons &= ~0x1f; . 82,86c if (b & 0x20) { if (up) mouse.buttons &= ~b; else mouse.buttons |= b; penmousetrack(mouse.buttons, -1, -1); } else { if (up) mouse.modifiers &= ~b; else mouse.modifiers |= b; } . 34a int modifiers; /* state of physical buttons 2, 3, 4, 5 */ . 30a /* The pen goes down, tracks some and goes up again. The pen alone can * only simulate a one-button mouse. * To simulate a more-button (five, in this case) mouse, we use the four * keys along the the bottom of the iPaq as modifiers. * When one (or more) of the modifier keys is (are) down, a pen-down event * causes the corresponding bottons to go down. If no modifier key is * depressed, a pen-down event is translated into a button-one down event. * Releasing the modifier keys has no direct effect. The pen-up event is * the one that triggers mouse-up events. */ . ## diffname bitsy/devpenmouse.c 2000/1214 ## diff -e /n/emeliedump/2000/1207/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1214/sys/src/9/bitsy/devpenmouse.c 239a case Qmousectl: sprint(buf, "c%11ld %11ld %11ld %11ld", calibration.scalex, calibration.scaley, calibration.transx, calibration.transy); if(n > 1+4*12) n = 1+4*12; memmove(va, buf, n); return n; . 81c "mousectl", {Qmousectl}, 0, 0660, . ## diffname bitsy/devpenmouse.c 2000/1215 ## diff -e /n/emeliedump/2000/1214/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1215/sys/src/9/bitsy/devpenmouse.c 363a if ((!isdigit(*field[1]) && *field[1] != '-') || (!isdigit(*field[2]) && *field[2] != '-') || (!isdigit(*field[3]) && *field[3] != '-') || (!isdigit(*field[4]) && *field[4] != '-')) error(Ectlsyntax); . 12a #include . ## diffname bitsy/devpenmouse.c 2000/1216 ## diff -e /n/emeliedump/2000/1215/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2000/1216/sys/src/9/bitsy/devpenmouse.c 272d ## diffname bitsy/devpenmouse.c 2001/0115 ## diff -e /n/emeliedump/2000/1216/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/0115/sys/src/9/bitsy/devpenmouse.c 368c error("bad syntax in control file message"); . ## diffname bitsy/devpenmouse.c 2001/0529 ## diff -e /n/emeliedump/2001/0115/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/0529/sys/src/9/bitsy/devpenmouse.c 422d 337,338c switch((ulong)c->qid.path){ case Qdir: . 238,239c switch((ulong)c->qid.path){ case Qdir: . 217c if(c->qid.path != Qdir && (c->flag&COPEN)){ . 172,173c switch((ulong)c->qid.path){ case Qdir: . 163,168d 160c return devstat(c, db, n, mousedir, nelem(mousedir), devgen); . 158c penmousestat(Chan *c, uchar *db, int n) . 151,154c return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen); . 148,149c static Walkqid* penmousewalk(Chan *c, Chan *nc, char **name, int nname) . 80,82c ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, "mouse", {Qmouse}, 0, 0666, "mousein", {Qmousein}, 0, 0220, "mousectl", {Qmousectl}, 0, 0660, . ## diffname bitsy/devpenmouse.c 2001/0822 ## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/0822/sys/src/9/bitsy/devpenmouse.c 95c // button 5 (side button) immediately causes an event // when the pen is down (button 1), other buttons also // cause events, allowing chording with button 1 if ((b & 0x20) || (mouse.buttons & 0x1)) { . ## diffname bitsy/devpenmouse.c 2001/1117 ## diff -e /n/emeliedump/2001/0822/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/1117/sys/src/9/bitsy/devpenmouse.c 344c nf = tokenize(buf, field, 5); . ## diffname bitsy/devpenmouse.c 2001/1121 ## diff -e /n/emeliedump/2001/1117/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/1121/sys/src/9/bitsy/devpenmouse.c 370a free(cb); poperror(); . 369c cmderror(cb, Ecmdargs); break; . 358c } else if (cb->nf == 5) { . 351,353c break; case CMcalibrate: if (cb->nf == 1) { . 337,345c cb = parsecmd(va, n); if(waserror()){ free(cb); nexterror(); } ct = lookupcmd(cb, penmousecmd, nelem(penmousecmd)); switch(ct->index){ case CMswap: . 327a Cmdbuf *cb; Cmdtab *ct; . 85a enum { CMcalibrate, CMswap, }; static Cmdtab penmousecmd[] = { CMcalibrate, "calibrate", 0, CMswap, "swap", 1, }; . ## diffname bitsy/devpenmouse.c 2001/1130 ## diff -e /n/emeliedump/2001/1121/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2001/1130/sys/src/9/bitsy/devpenmouse.c 377,380c calibration.scalex = strtol(cb->f[1], nil, 0); calibration.scaley = strtol(cb->f[2], nil, 0); calibration.transx = strtol(cb->f[3], nil, 0); calibration.transy = strtol(cb->f[4], nil, 0); . 372,375c if ((!isdigit(*cb->f[1]) && *cb->f[1] != '-') || (!isdigit(*cb->f[2]) && *cb->f[2] != '-') || (!isdigit(*cb->f[3]) && *cb->f[3] != '-') || (!isdigit(*cb->f[4]) && *cb->f[4] != '-')) . 342,343c char buf[64]; int b; . 125a . ## diffname bitsy/devpenmouse.c 2002/0109 ## diff -e /n/emeliedump/2001/1130/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2002/0109/sys/src/9/bitsy/devpenmouse.c 432a devshutdown, . ## diffname bitsy/devpenmouse.c 2002/1112 ## diff -e /n/emeliedump/2002/0109/sys/src/9/bitsy/devpenmouse.c /n/emeliedump/2002/1112/sys/src/9/bitsy/devpenmouse.c 476a resetsuspendtimer(); .