| plan 9 kernel history: overview | file list | diff list |
1994/0413/port/devmouse.c (diff list | history)
| port/devmouse.c on 1993/1006 | ||
| 1993/1006 | #include "u.h" #include "../port/lib.h" #include <libg.h> #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "devtab.h" | |
| 1994/0210 | #include "screen.h" | |
| 1993/1006 | /* * Some monochrome screens are reversed from what we like: * We want 0's bright and 1's dark. * Indexed by an Fcode, these compensate for the source bitmap being wrong * (exchange S rows) and destination (exchange D columns and invert result) */ int flipS[] = { 0x0, 0x4, 0x8, 0xC, 0x1, 0x5, 0x9, 0xD, 0x2, 0x6, 0xA, 0xE, 0x3, 0x7, 0xB, 0xF }; int flipD[] = { 0xF, 0xD, 0xE, 0xC, 0x7, 0x5, 0x6, 0x4, 0xB, 0x9, 0xA, 0x8, 0x3, 0x1, 0x2, 0x0, }; int flipping; /* are flip tables being used to transform Fcodes? */ typedef struct Mouseinfo Mouseinfo; typedef struct Cursorinfo Cursorinfo; struct Mouseinfo { /* * First three fields are known in some l.s's */ int dx; int dy; int track; /* l.s has updated dx & dy */ Mouse; int redraw; /* update cursor on screen */ ulong counter; /* increments every update */ ulong lastcounter; /* value when /dev/mouse read */ Rendez r; Ref; QLock; int open; }; struct Cursorinfo { Cursor; Lock; int visible; /* on screen */ int disable; /* from being used */ | |
| 1993/1026 | int frozen; /* from being used */ | |
| 1993/1006 | Rectangle r; /* location */ | |
| 1994/0413 | int l; int tl; int setop; int clrop; Rectangle clipr; | |
| 1993/1006 | }; Mouseinfo mouse; Cursorinfo cursor; int mouseshifted; int mousetype; | |
| 1994/0216 | int mouseswap; | |
| 1993/1006 | int hwcurs; | |
| 1993/1009 | Cursor curs; | |
| 1993/1006 | Cursor arrow = { {-1, -1}, {0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, 0xE7, 0xF0, 0xE3, 0xF8, 0xC1, 0xFC, 0x00, 0xFE, 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, }, {0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0, 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, } }; ulong setbits[16]; | |
| 1994/0413 | Bitmap set = | |
| 1993/1006 | { | |
| 1994/0413 | {0, 0, 16, 16}, {0, 0, 16, 16}, | |
| 1993/1006 | 0, | |
| 1994/0413 | setbits, | |
| 1993/1006 | 1, 0, }; ulong clrbits[16]; | |
| 1994/0413 | Bitmap clr = | |
| 1993/1006 | { {0, 0, 16, 16}, | |
| 1994/0413 | {0, 0, 16, 16}, | |
| 1993/1006 | 0, | |
| 1994/0413 | clrbits, | |
| 1993/1006 | 1, 0, }; | |
| 1994/0413 | ulong backbits[16*5]; ulong workbits[16*5]; Bitmap cursorwork = | |
| 1994/0412 | { | |
| 1994/0413 | {0, 0, 16+8, 16}, {0, 0, 16+8, 16}, | |
| 1994/0412 | 0, | |
| 1994/0413 | workbits, | |
| 1994/0412 | 1, 0, }; | |
| 1993/1006 | void Cursortocursor(Cursor*); int mousechanged(void*); | |
| 1994/0412 | extern void screenload(Rectangle, uchar*, int, int, int); extern void screenunload(Rectangle, uchar*, int, int, int); | |
| 1993/1006 | enum{ Qdir, | |
| 1993/1009 | Qcursor, | |
| 1993/1006 | Qmouse, Qmousectl, }; Dirtab mousedir[]={ | |
| 1993/1009 | "cursor", {Qcursor}, 0, 0666, | |
| 1993/1006 | "mouse", {Qmouse}, 0, 0666, "mousectl", {Qmousectl}, 0, 0220, }; #define NMOUSE (sizeof(mousedir)/sizeof(Dirtab)) | |
| 1994/0413 | extern Bitmap gscreen; | |
| 1993/1006 | void mousereset(void) { ulong r; if(!conf.monitor) return; getcolor(0, &r, &r, &r); if(r == 0) flipping = 1; flipping = 0; /* howard, why is this necessary to get a black arrow on carrera? */ | |
| 1993/1009 | curs = arrow; | |
| 1993/1006 | Cursortocursor(&arrow); } void | |
| 1994/0413 | cursorinit(void) { cursorwork.ldepth = gscreen.ldepth; cursorwork.width = ((cursorwork.r.max.x << gscreen.ldepth) + 31) >> 5; cursor.l = cursorwork.width*BY2WD; if(flipping){ cursor.setop = flipD[S|D]; cursor.clrop = flipD[D&~S]; } else { cursor.setop = S|D; cursor.clrop = D&~S; } } void | |
| 1993/1006 | mouseinit(void) { if(!conf.monitor) return; | |
| 1994/0413 | ||
| 1994/0412 | if(gscreen.ldepth > 3){ | |
| 1994/0413 | print("mouse can't work ldepth > 3"); cursor.disable = 1; | |
| 1993/1006 | } | |
| 1994/0413 | cursorinit(); | |
| 1993/1006 | cursoron(1); } Chan* mouseattach(char *spec) { if(!conf.monitor) error(Egreg); | |
| 1994/0413 | cursorinit(); | |
| 1993/1006 | return devattach('m', spec); } Chan* mouseclone(Chan *c, Chan *nc) { nc = devclone(c, nc); if(c->qid.path != CHDIR) incref(&mouse); return nc; } int mousewalk(Chan *c, char *name) { return devwalk(c, name, mousedir, NMOUSE, devgen); } void mousestat(Chan *c, char *db) { devstat(c, db, mousedir, NMOUSE, devgen); } Chan* 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; } void mousecreate(Chan *c, char *name, int omode, ulong perm) { if(!conf.monitor) error(Egreg); USED(c, name, omode, perm); error(Eperm); } void mouseremove(Chan *c) { USED(c); error(Eperm); } void mousewstat(Chan *c, char *db) { USED(c, db); error(Eperm); } void 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 | ||
| 1993/1006 | long mouseread(Chan *c, void *va, long n, ulong offset) { | |
| 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 }; | |
| 1993/1006 | ||
| 1993/1009 | p = va; switch(c->qid.path){ case CHDIR: | |
| 1993/1006 | return devdirread(c, va, n, mousedir, NMOUSE, devgen); | |
| 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); lock(&cursor); | |
| 1993/1008 | sprint(buf, "%11d %11d %11d %11d", | |
| 1994/0216 | mouse.xy.x, mouse.xy.y, mouseswap ? map[mouse.buttons&7] : mouse.buttons, | |
| 1993/1008 | TK2MS(MACHP(0)->ticks)); | |
| 1993/1006 | mouse.lastcounter = mouse.counter; unlock(&cursor); | |
| 1993/1008 | if(n > 4*12) n = 4*12; memmove(va, buf, n); return n; | |
| 1993/1006 | } return 0; } long mousewrite(Chan *c, void *va, long n, ulong offset) { | |
| 1993/1008 | char *p; | |
| 1993/1006 | Point pt; char buf[64]; | |
| 1994/0325 | USED(offset); | |
| 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); buf[n] = 0; mousectl(buf); return n; case Qmouse: | |
| 1993/1008 | if(n > sizeof buf-1) n = sizeof buf -1; memmove(buf, va, n); buf[n] = 0; p = 0; pt.x = strtoul(buf, &p, 0); if(p == 0) | |
| 1993/1006 | error(Eshort); | |
| 1993/1008 | pt.y = strtoul(p, 0, 0); | |
| 1993/1006 | qlock(&mouse); if(ptinrect(pt, gscreen.r)){ mouse.xy = pt; mouse.redraw = 1; mouse.track = 1; mouseclock(); } qunlock(&mouse); return n; } error(Egreg); return -1; } void Cursortocursor(Cursor *c) { int i; uchar *p; lock(&cursor); memmove(&cursor, c, sizeof(Cursor)); for(i=0; i<16; i++){ p = (uchar*)&setbits[i]; *p = c->set[2*i]; *(p+1) = c->set[2*i+1]; p = (uchar*)&clrbits[i]; *p = c->clr[2*i]; *(p+1) = c->clr[2*i+1]; } if(hwcurs) hwcursset(set.base, clr.base, cursor.offset.x, cursor.offset.y); | |
| 1993/1026 | unlock(&cursor); } void cursorlock(Rectangle r) { if(hwcurs) return; lock(&cursor); if(rectXrect(cursor.r, r)){ cursoroff(0); cursor.frozen = 1; } cursor.disable++; unlock(&cursor); } void cursorunlock(void) { if(hwcurs) return; lock(&cursor); cursor.disable--; if(cursor.frozen) cursoron(0); cursor.frozen = 0; | |
| 1993/1006 | unlock(&cursor); } | |
| 1994/0413 | typedef struct { Bitmap *dm; Point p; Bitmap *sm; Rectangle r; Fcode f; } XXX; | |
| 1993/1006 | void cursoron(int dolock) { | |
| 1994/0413 | int off; Rectangle r; uchar *a; XXX x; extern int graphicssubtile(uchar*, int, int, Rectangle, Rectangle, uchar**); | |
| 1993/1006 | if(cursor.disable) return; if(dolock) lock(&cursor); if(cursor.visible++ == 0){ if(hwcurs) hwcursmove(mouse.xy.x, mouse.xy.y); else { cursor.r.min = mouse.xy; cursor.r.max = add(mouse.xy, Pt(16, 16)); cursor.r = raddp(cursor.r, cursor.offset); | |
| 1994/0413 | /* bit offset into backup area */ off = ((1<<gscreen.ldepth)*cursor.r.min.x) & 7; /* clip the cursor rectangle */ x.dm = &cursorwork; x.p = Pt(off, 0); x.sm = &gscreen; x.r = cursor.r; bitbltclip(&x); /* tile width */ cursor.tl = graphicssubtile(0, cursor.l, gscreen.ldepth, gscreen.r, x.r, &a); if(cursor.tl > 0){ /* get tile */ screenunload(x.r, (uchar*)workbits, cursor.tl, cursor.l, 0); /* save for cursoroff */ memmove(backbits, workbits, cursor.l*16); /* add mouse into work area */ r = Rect(0, 0, Dx(x.r), Dy(x.r)); bitblt(&cursorwork, x.p, &clr, r, cursor.clrop); bitblt(&cursorwork, x.p, &set, r, cursor.setop); /* put back tile */ cursor.clipr = x.r; screenload(x.r, (uchar*)workbits, cursor.tl, cursor.l, 0); } | |
| 1993/1006 | } } if(dolock) unlock(&cursor); } void cursoroff(int dolock) { if(cursor.disable) return; if(dolock) lock(&cursor); | |
| 1994/0413 | if(--cursor.visible == 0 && !hwcurs && cursor.tl > 0) screenload(cursor.clipr, (uchar*)backbits, cursor.tl, cursor.l, 0); | |
| 1993/1006 | if(dolock) unlock(&cursor); } /* * called by the clock routine to redraw the cursor */ void 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); cursoron(0); unlock(&cursor); } } /* * called at interrupt level to update the structure and * awaken any waiting procs. */ void mousetrack(int b, int dx, int dy) { int x, y; x = mouse.xy.x + dx; if(x < gscreen.r.min.x) x = gscreen.r.min.x; if(x >= gscreen.r.max.x) x = gscreen.r.max.x; y = mouse.xy.y + dy; if(y < gscreen.r.min.y) y = gscreen.r.min.y; if(y >= gscreen.r.max.y) y = gscreen.r.max.y; mouse.counter++; mouse.xy = Pt(x, y); mouse.buttons = b; mouse.redraw = 1; wakeup(&mouse.r); } /* * 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 | |
| 1993/1201 | m3mouseputc(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; /* * check bit 6 for consistency */ if(nb==0){ if((c&0x40) == 0){ /* 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 | |
| 1993/1201 | mouseputc(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 mousechanged(void *m) { USED(m); return mouse.lastcounter - mouse.counter; } | |