#include #include #include #include #include #include void moveto(Mousectl *m, Point pt) { fprint(m->mfd, "m%d %d", pt.x, pt.y); m->xy = pt; } void closemouse(Mousectl *mc) { if(mc == nil) return; postnote(PNPROC, mc->pid, "kill"); do; while(nbrecv(mc->c, &mc->Mouse) > 0); close(mc->mfd); close(mc->cfd); free(mc->file); free(mc->c); free(mc->resizec); free(mc); } int readmouse(Mousectl *mc) { if(mc->image) flushimage(mc->image->display, 1); if(recv(mc->c, &mc->Mouse) < 0){ fprint(2, "readmouse: %r\n"); return -1; } return 0; } static void _ioproc(void *arg) { int n, nerr, one; char buf[1+5*12]; Mouse m; Mousectl *mc; mc = arg; threadsetname("mouseproc"); one = 1; memset(&m, 0, sizeof m); mc->pid = getpid(); nerr = 0; for(;;){ n = read(mc->mfd, buf, sizeof buf); if(n != 1+4*12){ yield(); /* if error is due to exiting, we'll exit here */ fprint(2, "mouse: bad count %d not 49: %r\n", n); if(n<0 || ++nerr>10) threadexits("read error"); continue; } nerr = 0; switch(buf[0]){ case 'r': send(mc->resizec, &one); /* fall through */ case 'm': m.xy.x = atoi(buf+1+0*12); m.xy.y = atoi(buf+1+1*12); m.buttons = atoi(buf+1+2*12); m.msec = atoi(buf+1+3*12); send(mc->c, &m); /* * mc->Mouse is updated after send so it doesn't have wrong value if we block during send. * This means that programs should receive into mc->Mouse (see readmouse() above) if * they want full synchrony. */ mc->Mouse = m; break; } } } Mousectl* initmouse(char *file, Image *i) { Mousectl *mc; char *t, *sl; mc = mallocz(sizeof(Mousectl), 1); if(file == nil) file = "/dev/mouse"; mc->file = strdup(file); mc->mfd = open(file, ORDWR|OCEXEC); if(mc->mfd<0 && strcmp(file, "/dev/mouse")==0){ bind("#m", "/dev", MAFTER); mc->mfd = open(file, ORDWR|OCEXEC); } if(mc->mfd < 0){ free(mc); return nil; } t = malloc(strlen(file)+16); if (t == nil) { close(mc->mfd); free(mc); return nil; } strcpy(t, file); sl = utfrrune(t, '/'); if(sl) strcpy(sl, "/cursor"); else strcpy(t, "/dev/cursor"); mc->cfd = open(t, ORDWR|OCEXEC); free(t); mc->image = i; mc->c = chancreate(sizeof(Mouse), 0); mc->resizec = chancreate(sizeof(int), 2); proccreate(_ioproc, mc, 4096); return mc; } void setcursor(Mousectl *mc, Cursor *c) { char curs[2*4+2*2*16]; if(c == nil) write(mc->cfd, curs, 0); else{ BPLONG(curs+0*4, c->offset.x); BPLONG(curs+1*4, c->offset.y); memmove(curs+2*4, c->clr, 2*2*16); write(mc->cfd, curs, sizeof curs); } }