| plan 9 kernel history: overview | file list | diff list |
1999/1005/port/devmouse.c (diff list | history)
| port/devmouse.c on 1993/1006 | ||
| 1993/1006 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" | |
| 1997/1101 | #define Image IMAGE #include <draw.h> #include <memdraw.h> | |
| 1999/0119 | #include <cursor.h> | |
| 1994/0210 | #include "screen.h" | |
| 1993/1006 | typedef struct Mouseinfo Mouseinfo; struct Mouseinfo { int dx; int dy; | |
| 1997/1101 | int track; /* dx & dy updated */ | |
| 1999/0119 | Point xy; /* mouse.xy */ int buttons; /* mouse.buttons */ | |
| 1993/1006 | int redraw; /* update cursor on screen */ ulong counter; /* increments every update */ ulong lastcounter; /* value when /dev/mouse read */ Rendez r; Ref; QLock; int open; | |
| 1995/1216 | int acceleration; int maxacc; | |
| 1993/1006 | }; Mouseinfo mouse; Cursorinfo cursor; int mouseshifted; | |
| 1994/0414 | Cursor curs; | |
| 1993/1006 | void Cursortocursor(Cursor*); int mousechanged(void*); | |
| 1997/0327 | static void mouseclock(void); | |
| 1993/1006 | enum{ Qdir, | |
| 1993/1009 | Qcursor, | |
| 1993/1006 | Qmouse, Qmousectl, }; | |
| 1998/0417 | static Dirtab mousedir[]={ | |
| 1993/1009 | "cursor", {Qcursor}, 0, 0666, | |
| 1993/1006 | "mouse", {Qmouse}, 0, 0666, "mousectl", {Qmousectl}, 0, 0220, }; | |
| 1998/0417 | static uchar buttonmap[8] = { 0, 1, 2, 3, 4, 5, 6, 7, }; static int mouseswap; | |
| 1999/1005 | extern Memimage* gscreen; | |
| 1993/1006 | ||
| 1997/0327 | static void | |
| 1993/1006 | mousereset(void) { if(!conf.monitor) return; | |
| 1993/1009 | curs = arrow; | |
| 1993/1006 | Cursortocursor(&arrow); | |
| 1997/0327 | addclock0link(mouseclock); | |
| 1993/1006 | } | |
| 1997/0327 | static void | |
| 1993/1006 | mouseinit(void) { if(!conf.monitor) return; | |
| 1994/0413 | ||
| 1993/1006 | cursoron(1); } | |
| 1997/0327 | static Chan* | |
| 1993/1006 | mouseattach(char *spec) { if(!conf.monitor) error(Egreg); return devattach('m', spec); } | |
| 1997/0327 | static Chan* | |
| 1993/1006 | mouseclone(Chan *c, Chan *nc) { nc = devclone(c, nc); if(c->qid.path != CHDIR) incref(&mouse); return nc; } | |
| 1997/0327 | static int | |
| 1993/1006 | mousewalk(Chan *c, char *name) { | |
| 1997/0327 | return devwalk(c, name, mousedir, nelem(mousedir), devgen); | |
| 1993/1006 | } | |
| 1997/0327 | static void | |
| 1993/1006 | mousestat(Chan *c, char *db) { | |
| 1997/0327 | devstat(c, db, mousedir, nelem(mousedir), devgen); | |
| 1993/1006 | } | |
| 1997/0327 | static Chan* | |
| 1993/1006 | mouseopen(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; default: incref(&mouse); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } | |
| 1997/0327 | static void | |
| 1995/0804 | mousecreate(Chan*, char*, int, ulong) | |
| 1993/1006 | { if(!conf.monitor) error(Egreg); error(Eperm); } | |
| 1997/0327 | static void | |
| 1993/1006 | mouseclose(Chan *c) { if(c->qid.path!=CHDIR && (c->flag&COPEN)){ lock(&mouse); if(c->qid.path == Qmouse) mouse.open = 0; | |
| 1993/1009 | if(--mouse.ref == 0){ cursoroff(1); curs = arrow; Cursortocursor(&arrow); cursoron(1); } | |
| 1993/1006 | unlock(&mouse); } } | |
| 1994/0216 | ||
| 1997/0327 | static long | |
| 1998/0319 | mouseread(Chan *c, void *va, long n, vlong off) | |
| 1993/1006 | { | |
| 1993/1008 | char buf[4*12+1]; | |
| 1993/1009 | uchar *p; | |
| 1994/0216 | static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; | |
| 1998/0319 | ulong offset = off; | |
| 1993/1006 | ||
| 1993/1009 | p = va; switch(c->qid.path){ case CHDIR: | |
| 1997/0327 | return devdirread(c, va, n, mousedir, nelem(mousedir), devgen); | |
| 1993/1006 | ||
| 1993/1009 | case Qcursor: if(offset != 0) return 0; if(n < 2*4+2*2*16) error(Eshort); n = 2*4+2*2*16; lock(&cursor); BPLONG(p+0, curs.offset.x); BPLONG(p+4, curs.offset.y); memmove(p+8, curs.clr, 2*16); memmove(p+40, curs.set, 2*16); unlock(&cursor); return n; case Qmouse: | |
| 1993/1006 | while(mousechanged(0) == 0) sleep(&mouse.r, mousechanged, 0); | |
| 1995/0812 | while(!canlock(&cursor)) tsleep(&up->sleep, return0, 0, TK2MS(1)); | |
| 1998/0825 | sprint(buf, "m%11d %11d %11d %11lud", | |
| 1994/0216 | mouse.xy.x, mouse.xy.y, | |
| 1998/0417 | buttonmap[mouse.buttons&7], | |
| 1993/1008 | TK2MS(MACHP(0)->ticks)); | |
| 1993/1006 | mouse.lastcounter = mouse.counter; unlock(&cursor); | |
| 1994/1013 | if(n > 1+4*12) n = 1+4*12; | |
| 1993/1008 | memmove(va, buf, n); return n; | |
| 1993/1006 | } return 0; } | |
| 1998/0417 | 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; } } | |
| 1997/0327 | static long | |
| 1998/0319 | mousewrite(Chan *c, void *va, long n, vlong) | |
| 1993/1006 | { | |
| 1993/1008 | char *p; | |
| 1993/1006 | Point pt; | |
| 1998/0417 | char buf[64], *field[3]; int nf; | |
| 1993/1006 | ||
| 1993/1009 | p = va; | |
| 1993/1006 | switch(c->qid.path){ case CHDIR: error(Eisdir); | |
| 1993/1009 | case Qcursor: cursoroff(1); if(n < 2*4+2*2*16){ curs = arrow; Cursortocursor(&arrow); }else{ n = 2*4+2*2*16; curs.offset.x = BGLONG(p+0); curs.offset.y = BGLONG(p+4); memmove(curs.clr, p+8, 2*16); memmove(curs.set, p+40, 2*16); Cursortocursor(&curs); } | |
| 1993/1108 | qlock(&mouse); mouse.redraw = 1; mouseclock(); qunlock(&mouse); | |
| 1993/1009 | cursoron(1); return n; | |
| 1993/1006 | case Qmousectl: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); | |
| 1995/1216 | if(buf[n - 1] == '\n') buf[n-1] = 0; else buf[n] = 0; | |
| 1998/0417 | nf = parsefields(buf, field, 3, " "); if(strcmp(field[0], "swap") == 0){ if(mouseswap) setbuttonmap("123"); else setbuttonmap("321"); mouseswap ^= 1; } else if(strcmp(field[0], "buttonmap") == 0){ if(nf == 1) setbuttonmap("123"); else setbuttonmap(field[1]); } else mousectl(field, nf); | |
| 1993/1006 | return n; case Qmouse: | |
| 1993/1008 | if(n > sizeof buf-1) n = sizeof buf -1; memmove(buf, va, n); buf[n] = 0; p = 0; | |
| 1994/1013 | pt.x = strtoul(buf+1, &p, 0); | |
| 1993/1008 | if(p == 0) | |
| 1993/1006 | error(Eshort); | |
| 1993/1008 | pt.y = strtoul(p, 0, 0); | |
| 1993/1006 | qlock(&mouse); | |
| 1999/1005 | if(ptinrect(pt, gscreen->r)){ | |
| 1993/1006 | mouse.xy = pt; mouse.redraw = 1; mouse.track = 1; mouseclock(); } qunlock(&mouse); return n; } error(Egreg); return -1; | |
| 1995/0108 | } | |
| 1997/0327 | Dev mousedevtab = { | |
| 1997/0408 | 'm', "mouse", | |
| 1997/0327 | mousereset, mouseinit, mouseattach, mouseclone, mousewalk, mousestat, mouseopen, mousecreate, mouseclose, mouseread, devbread, mousewrite, devbwrite, devremove, devwstat, }; | |
| 1993/1006 | void Cursortocursor(Cursor *c) { lock(&cursor); | |
| 1994/0414 | memmove(&cursor.Cursor, c, sizeof(Cursor)); | |
| 1994/0520 | setcursor(c); | |
| 1993/1026 | unlock(&cursor); } | |
| 1993/1006 | /* * called by the clock routine to redraw the cursor */ | |
| 1997/0327 | static void | |
| 1993/1006 | mouseclock(void) { if(mouse.track){ mousetrack(mouse.buttons, mouse.dx, mouse.dy); mouse.track = 0; mouse.dx = 0; mouse.dy = 0; } if(mouse.redraw && canlock(&cursor)){ mouse.redraw = 0; cursoroff(0); | |
| 1994/0624 | mouse.redraw = cursoron(0); | |
| 1993/1006 | unlock(&cursor); } | |
| 1997/1101 | drawactive(0); | |
| 1993/1006 | } | |
| 1995/1216 | static int scale(int x) { int sign = 1; if(x < 0){ sign = -1; x = -x; } switch(x){ case 0: case 1: case 2: case 3: break; case 4: x = 6 + (mouse.acceleration>>2); break; case 5: x = 9 + (mouse.acceleration>>1); break; default: x *= mouse.maxacc; break; } return sign*x; } | |
| 1993/1006 | /* * called at interrupt level to update the structure and * awaken any waiting procs. */ void mousetrack(int b, int dx, int dy) { int x, y; | |
| 1999/1005 | if(gscreen==nil) return; | |
| 1995/1216 | if(mouse.acceleration){ dx = scale(dx); dy = scale(dy); } | |
| 1993/1006 | x = mouse.xy.x + dx; | |
| 1999/1005 | if(x < gscreen->r.min.x) x = gscreen->r.min.x; if(x >= gscreen->r.max.x) x = gscreen->r.max.x; | |
| 1993/1006 | y = mouse.xy.y + dy; | |
| 1999/1005 | if(y < gscreen->r.min.y) y = gscreen->r.min.y; if(y >= gscreen->r.max.y) y = gscreen->r.max.y; | |
| 1993/1006 | mouse.counter++; mouse.xy = Pt(x, y); mouse.buttons = b; mouse.redraw = 1; wakeup(&mouse.r); | |
| 1997/1101 | drawactive(1); | |
| 1993/1006 | } /* * microsoft 3 button, 7 bit bytes * * byte 0 - 1 L R Y7 Y6 X7 X6 * byte 1 - 0 X5 X4 X3 X2 X1 X0 * byte 2 - 0 Y5 Y4 Y3 Y2 Y1 Y0 * byte 3 - 0 M x x x x x (optional) * * shift & right button is the same as middle button (for 2 button mice) */ int | |
| 1999/0320 | m3mouseputc(Queue*, int c) | |
| 1993/1006 | { static uchar msg[3]; static int nb; static int middle; static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 5 }; short x; int dx, dy, newbuttons; if(nb==0){ | |
| 1997/1112 | /* * an extra byte comes for middle button motion. * only two possible values for the extra byte. */ if(c == 0x00 || c == 0x20){ | |
| 1993/1006 | /* an extra byte gets sent for the middle button */ middle = (c&0x20) ? 2 : 0; newbuttons = (mouse.buttons & ~2) | middle; mousetrack(newbuttons, 0, 0); return 0; } } msg[nb] = c; if(++nb == 3){ nb = 0; newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)]; x = (msg[0]&0x3)<<14; dx = (x>>8) | msg[1]; x = (msg[0]&0xc)<<12; dy = (x>>8) | msg[2]; mousetrack(newbuttons, dx, dy); } return 0; } /* * Logitech 5 byte packed binary mouse format, 8 bit bytes * * shift & right button is the same as middle button (for 2 button mice) */ int | |
| 1999/0320 | mouseputc(Queue*, int c) | |
| 1993/1006 | { static short msg[5]; static int nb; static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 5, 3, 7}; int dx, dy, newbuttons; if((c&0xF0) == 0x80) nb=0; msg[nb] = c; if(c & 0x80) msg[nb] |= ~0xFF; /* sign extend */ if(++nb == 5){ newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)]; dx = msg[1]+msg[3]; dy = -(msg[2]+msg[4]); mousetrack(newbuttons, dx, dy); nb = 0; } return 0; } int | |
| 1995/0804 | mousechanged(void*) | |
| 1993/1006 | { return mouse.lastcounter - mouse.counter; | |
| 1994/0414 | } Point mousexy(void) { return mouse.xy; | |
| 1995/1216 | } void | |
| 1999/0225 | mouseaccelerate(int x) | |
| 1995/1216 | { | |
| 1999/0225 | mouse.acceleration = x; | |
| 1995/1216 | if(mouse.acceleration < 3) mouse.maxacc = 2; else mouse.maxacc = mouse.acceleration; | |
| 1993/1006 | } | |