123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509 |
- #include "u.h"
- #include "../port/lib.h"
- #include "mem.h"
- #include "dat.h"
- #include "fns.h"
- #include "../port/error.h"
- #define Image IMAGE
- #include <draw.h>
- #include <memdraw.h>
- #include <cursor.h>
- #include "screen.h"
- #include <ctype.h>
- typedef struct Mouseinfo Mouseinfo;
- typedef struct Mousestate Mousestate;
- typedef struct Calibration Calibration;
- struct Calibration
- {
- long scalex;
- long scaley;
- long transx;
- long transy;
- } calibration = {
- -16435,
- 23275,
- 253,
- -23
- };
- /* 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.
- */
- struct Mousestate
- {
- Point xy; /* mouse.xy */
- int buttons; /* mouse.buttons */
- int modifiers; /* state of physical buttons 2, 3, 4, 5 */
- ulong counter; /* increments every update */
- ulong msec; /* time of last event */
- };
- struct Mouseinfo
- {
- Lock;
- Mousestate;
- ulong lastcounter; /* value when /dev/mouse read */
- ulong resize;
- ulong lastresize;
- 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[]={
- ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
- "mouse", {Qmouse}, 0, 0666,
- "mousein", {Qmousein}, 0, 0220,
- "mousectl", {Qmousectl}, 0, 0660,
- };
- enum
- {
- CMcalibrate,
- CMswap,
- };
- static Cmdtab penmousecmd[] =
- {
- CMcalibrate, "calibrate", 0,
- CMswap, "swap", 1,
- };
- static uchar buttonmap[8] = {
- 0, 1, 2, 3, 4, 5, 6, 7,
- };
- static int mouseswap;
- extern Memimage* gscreen;
- void
- penbutton(int up, int b) {
- // 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)) {
- if (up)
- mouse.buttons &= ~b;
- else
- mouse.buttons |= b;
- penmousetrack(mouse.buttons, -1, -1);
- } else {
- if (up)
- mouse.modifiers &= ~b;
- else
- mouse.modifiers |= b;
- }
- }
- void
- pentrackxy(int x, int y) {
- if (x == -1) {
- /* pen up. associate with button 1 through 5 up */
- mouse.buttons &= ~0x1f;
- } else {
- x = ((x*calibration.scalex)>>16) + calibration.transx;
- y = ((y*calibration.scaley)>>16) + calibration.transy;
- if ((mouse.buttons & 0x1f) == 0) {
- if (mouse.modifiers)
- mouse.buttons |= mouse.modifiers;
- else
- mouse.buttons |= 0x1;
- }
- }
- 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 Walkqid*
- penmousewalk(Chan *c, Chan *nc, char **name, int nname)
- {
- return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
- }
- static int
- penmousestat(Chan *c, uchar *db, int n)
- {
- return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
- }
- static Chan*
- penmouseopen(Chan *c, int omode)
- {
- switch((ulong)c->qid.path){
- case Qdir:
- 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 != Qdir && (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;
- switch((ulong)c->qid.path){
- case Qdir:
- return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
- 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;
- case Qmouse:
- while(penmousechanged(0) == 0)
- sleep(&mouse.r, penmousechanged, 0);
- mouse.qfull = 0;
- /*
- * No lock of the indices 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;
- }
- sprint(buf, "m%11d %11d %11d %11lud",
- m.xy.x, m.xy.y,
- m.buttons,
- m.msec);
- mouse.lastcounter = m.counter;
- if(n > 1+4*12)
- n = 1+4*12;
- if(mouse.lastresize != mouse.resize){
- mouse.lastresize = mouse.resize;
- buf[0] = 'r';
- }
- 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<<i;
- }
- else if(map[i] == '2'){
- if(two)
- error(Ebadarg);
- two = 1<<i;
- }
- else if(map[i] == '3'){
- if(three)
- error(Ebadarg);
- three = 1<<i;
- }
- else
- error(Ebadarg);
- }
- if(map[i])
- error(Ebadarg);
- memset(buttonmap, 0, 8);
- for(i = 0; i < 8; i++){
- x = 0;
- if(i & 1)
- x |= one;
- if(i & 2)
- x |= two;
- if(i & 4)
- x |= three;
- buttonmap[x] = i;
- }
- }
- static long
- penmousewrite(Chan *c, void *va, long n, vlong)
- {
- char *p;
- Point pt;
- Cmdbuf *cb;
- Cmdtab *ct;
- char buf[64];
- int b;
- p = va;
- switch((ulong)c->qid.path){
- case Qdir:
- error(Eisdir);
- case Qmousectl:
- cb = parsecmd(va, n);
- if(waserror()){
- free(cb);
- nexterror();
- }
- ct = lookupcmd(cb, penmousecmd, nelem(penmousecmd));
- switch(ct->index){
- case CMswap:
- if(mouseswap)
- setbuttonmap("123");
- else
- setbuttonmap("321");
- mouseswap ^= 1;
- break;
- case CMcalibrate:
- if (cb->nf == 1) {
- calibration.scalex = 1<<16;
- calibration.scaley = 1<<16;
- calibration.transx = 0;
- calibration.transy = 0;
- } else if (cb->nf == 5) {
- 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] != '-'))
- error("bad syntax in control file message");
- 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);
- } else
- cmderror(cb, Ecmdargs);
- break;
- }
- free(cb);
- poperror();
- 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,
- devshutdown,
- penmouseattach,
- 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 (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);
- drawactive(1);
- resetsuspendtimer();
- }
- int
- penmousechanged(void*)
- {
- return mouse.lastcounter != mouse.counter ||
- mouse.lastresize != mouse.resize;
- }
- Point
- penmousexy(void)
- {
- return mouse.xy;
- }
- /*
- * notify reader that screen has been resized (ha!)
- */
- void
- mouseresize(void)
- {
- mouse.resize++;
- wakeup(&mouse.r);
- }
|