1 #include <u.h> 2 #include <libc.h> 3 #include <draw.h> 4 #include <thread.h> 5 #include <cursor.h> 6 #include <mouse.h> 7 8 void 9 moveto(Mousectl *m, Point pt) 10 { 11 fprint(m->mfd, "m%d %d", pt.x, pt.y); 12 m->xy = pt; 13 } 14 15 void 16 closemouse(Mousectl *mc) 17 { 18 if(mc == nil) 19 return; 20 21 postnote(PNPROC, mc->pid, "kill"); 22 23 do; while(nbrecv(mc->c, &mc->Mouse) > 0); 24 25 close(mc->mfd); 26 close(mc->cfd); 27 free(mc->file); 28 free(mc->c); 29 free(mc->resizec); 30 free(mc); 31 } 32 33 int 34 readmouse(Mousectl *mc) 35 { 36 if(mc->image) 37 flushimage(mc->image->display, 1); 38 if(recv(mc->c, &mc->Mouse) < 0){ 39 fprint(2, "readmouse: %r\n"); 40 return -1; 41 } 42 return 0; 43 } 44 45 static 46 void 47 _ioproc(void *arg) 48 { 49 int n, nerr, one; 50 char buf[1+5*12]; 51 Mouse m; 52 Mousectl *mc; 53 54 mc = arg; 55 threadsetname("mouseproc"); 56 one = 1; 57 memset(&m, 0, sizeof m); 58 mc->pid = getpid(); 59 nerr = 0; 60 for(;;){ 61 n = read(mc->mfd, buf, sizeof buf); 62 if(n != 1+4*12){ 63 yield(); /* if error is due to exiting, we'll exit here */ 64 fprint(2, "mouse: bad count %d not 49: %r\n", n); 65 if(n<0 || ++nerr>10) 66 threadexits("read error"); 67 continue; 68 } 69 nerr = 0; 70 switch(buf[0]){ 71 case 'r': 72 send(mc->resizec, &one); 73 /* fall through */ 74 case 'm': 75 m.xy.x = atoi(buf+1+0*12); 76 m.xy.y = atoi(buf+1+1*12); 77 m.buttons = atoi(buf+1+2*12); 78 m.msec = atoi(buf+1+3*12); 79 send(mc->c, &m); 80 /* 81 * mc->Mouse is updated after send so it doesn't have wrong value if we block during send. 82 * This means that programs should receive into mc->Mouse (see readmouse() above) if 83 * they want full synchrony. 84 */ 85 mc->Mouse = m; 86 break; 87 } 88 } 89 } 90 91 Mousectl* 92 initmouse(char *file, Image *i) 93 { 94 Mousectl *mc; 95 char *t, *sl; 96 97 mc = mallocz(sizeof(Mousectl), 1); 98 if(file == nil) 99 file = "/dev/mouse"; 100 mc->file = strdup(file); 101 mc->mfd = open(file, ORDWR|OCEXEC); 102 if(mc->mfd<0 && strcmp(file, "/dev/mouse")==0){ 103 bind("#m", "/dev", MAFTER); 104 mc->mfd = open(file, ORDWR|OCEXEC); 105 } 106 if(mc->mfd < 0){ 107 free(mc); 108 return nil; 109 } 110 t = malloc(strlen(file)+16); 111 strcpy(t, file); 112 sl = utfrrune(t, '/'); 113 if(sl) 114 strcpy(sl, "/cursor"); 115 else 116 strcpy(t, "/dev/cursor"); 117 mc->cfd = open(t, ORDWR|OCEXEC); 118 free(t); 119 mc->image = i; 120 mc->c = chancreate(sizeof(Mouse), 0); 121 mc->resizec = chancreate(sizeof(int), 2); 122 proccreate(_ioproc, mc, 4096); 123 return mc; 124 } 125 126 void 127 setcursor(Mousectl *mc, Cursor *c) 128 { 129 char curs[2*4+2*2*16]; 130 131 if(c == nil) 132 write(mc->cfd, curs, 0); 133 else{ 134 BPLONG(curs+0*4, c->offset.x); 135 BPLONG(curs+1*4, c->offset.y); 136 memmove(curs+2*4, c->clr, 2*2*16); 137 write(mc->cfd, curs, sizeof curs); 138 } 139 } 140