| plan 9 kernel history: overview | file list | diff list |
1993/1008/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 <gnot.h> #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "devtab.h" /* * 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 */ Rectangle r; /* location */ }; Mouseinfo mouse; Cursorinfo cursor; int mouseshifted; int mousetype; int hwcurs; 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]; GBitmap set = { setbits, 0, 1, 0, {0, 0, 16, 16}, {0, 0, 16, 16} }; ulong clrbits[16]; GBitmap clr = { clrbits, 0, 1, 0, {0, 0, 16, 16}, {0, 0, 16, 16} }; ulong cursorbackbits[16*4]; GBitmap cursorback = { cursorbackbits, 0, 1, 0, {0, 0, 16, 16}, {0, 0, 16, 16} }; void Cursortocursor(Cursor*); int mousechanged(void*); enum{ Qdir, Qmouse, Qmousectl, }; Dirtab mousedir[]={ "mouse", {Qmouse}, 0, 0666, "mousectl", {Qmousectl}, 0, 0220, }; #define NMOUSE (sizeof(mousedir)/sizeof(Dirtab)) extern GBitmap gscreen; 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? */ Cursortocursor(&arrow); } void mouseinit(void) { if(!conf.monitor) return; if(gscreen.ldepth > 3) cursorback.ldepth = 0; else{ cursorback.ldepth = gscreen.ldepth; cursorback.width = ((16 << gscreen.ldepth) + 31) >> 5; } cursoron(1); } Chan* mouseattach(char *spec) { if(!conf.monitor) error(Egreg); 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; unlock(&mouse); } } long mouseread(Chan *c, void *va, long n, ulong offset) { | |
| 1993/1008 | char buf[4*12+1]; | |
| 1993/1006 | USED(offset); if(c->qid.path & CHDIR) return devdirread(c, va, n, mousedir, NMOUSE, devgen); if(c->qid.path == Qmouse){ while(mousechanged(0) == 0) sleep(&mouse.r, mousechanged, 0); lock(&cursor); | |
| 1993/1008 | sprint(buf, "%11d %11d %11d %11d", mouse.xy.x, mouse.xy.y, mouse.buttons, 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]; USED(offset); switch(c->qid.path){ case CHDIR: error(Eisdir); 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); unlock(&cursor); } void cursoron(int dolock) { 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); gbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S); gbitblt(&gscreen, cursor.r.min, &clr, Rect(0, 0, 16, 16), flipping? flipD[D&~S] : D&~S); gbitblt(&gscreen, cursor.r.min, &set, Rect(0, 0, 16, 16), flipping? flipD[S|D] : S|D); mbbrect(cursor.r); } } if(dolock) unlock(&cursor); } void cursoroff(int dolock) { if(cursor.disable) return; if(dolock) lock(&cursor); if(--cursor.visible == 0) { if(!hwcurs) { gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S); mbbrect(cursor.r); mousescreenupdate(); } } 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); mousescreenupdate(); 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 m3mouseputc(IOQ *q, int c) { 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; USED(q); /* * 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 mouseputc(IOQ *q, int c) { 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; USED(q); 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; } | |