1 #include "u.h" 2 #include "lib.h" 3 #include "dat.h" 4 #include "fns.h" 5 #include "error.h" 6 7 #include "draw.h" 8 #include "memdraw.h" 9 #include "screen.h" 10 11 int mousequeue = 1; 12 13 Mouseinfo mouse; 14 Cursorinfo cursor; 15 16 static int mousechanged(void*); 17 18 enum{ 19 Qdir, 20 Qcursor, 21 Qmouse 22 }; 23 24 Dirtab mousedir[]={ 25 ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555, 26 "cursor", {Qcursor}, 0, 0666, 27 "mouse", {Qmouse}, 0, 0666, 28 }; 29 30 #define NMOUSE (sizeof(mousedir)/sizeof(Dirtab)) 31 32 static Chan* 33 mouseattach(char *spec) 34 { 35 return devattach('m', spec); 36 } 37 38 static Walkqid* 39 mousewalk(Chan *c, Chan *nc, char **name, int nname) 40 { 41 return devwalk(c, nc, name, nname, mousedir, NMOUSE, devgen); 42 } 43 44 static int 45 mousestat(Chan *c, uchar *db, int n) 46 { 47 return devstat(c, db, n, mousedir, NMOUSE, devgen); 48 } 49 50 static Chan* 51 mouseopen(Chan *c, int omode) 52 { 53 switch((long)c->qid.path){ 54 case Qdir: 55 if(omode != OREAD) 56 error(Eperm); 57 break; 58 case Qmouse: 59 lock(&mouse.lk); 60 if(mouse.open){ 61 unlock(&mouse.lk); 62 error(Einuse); 63 } 64 mouse.open = 1; 65 unlock(&mouse.lk); 66 break; 67 } 68 c->mode = openmode(omode); 69 c->flag |= COPEN; 70 c->offset = 0; 71 return c; 72 } 73 74 void 75 mouseclose(Chan *c) 76 { 77 if(!(c->flag&COPEN)) 78 return; 79 80 switch((long)c->qid.path) { 81 case Qmouse: 82 lock(&mouse.lk); 83 mouse.open = 0; 84 unlock(&mouse.lk); 85 cursorarrow(); 86 } 87 } 88 89 90 long 91 mouseread(Chan *c, void *va, long n, vlong offset) 92 { 93 char buf[4*12+1]; 94 uchar *p; 95 int i, nn; 96 ulong msec; 97 /* static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 }; */ 98 99 p = va; 100 switch((long)c->qid.path){ 101 case Qdir: 102 return devdirread(c, va, n, mousedir, NMOUSE, devgen); 103 104 case Qcursor: 105 if(offset != 0) 106 return 0; 107 if(n < 2*4+2*2*16) 108 error(Eshort); 109 n = 2*4+2*2*16; 110 lock(&cursor.lk); 111 BPLONG(p+0, cursor.offset.x); 112 BPLONG(p+4, cursor.offset.y); 113 memmove(p+8, cursor.clr, 2*16); 114 memmove(p+40, cursor.set, 2*16); 115 unlock(&cursor.lk); 116 return n; 117 118 case Qmouse: 119 while(mousechanged(0) == 0) 120 sleep(&mouse.r, mousechanged, 0); 121 122 lock(&screen.lk); 123 if(screen.reshaped) { 124 screen.reshaped = 0; 125 sprint(buf, "t%11d %11d", 0, ticks()); 126 if(n > 1+2*12) 127 n = 1+2*12; 128 memmove(va, buf, n); 129 unlock(&screen.lk); 130 return n; 131 } 132 unlock(&screen.lk); 133 134 lock(&mouse.lk); 135 i = mouse.ri; 136 nn = (mouse.wi + Mousequeue - i) % Mousequeue; 137 if(nn < 1) 138 panic("empty mouse queue"); 139 msec = ticks(); 140 while(nn > 1) { 141 if(mouse.queue[i].msec + Mousewindow > msec) 142 break; 143 i = (i+1)%Mousequeue; 144 nn--; 145 } 146 sprint(buf, "m%11d %11d %11d %11d", 147 mouse.queue[i].xy.x, 148 mouse.queue[i].xy.y, 149 mouse.queue[i].buttons, 150 mouse.queue[i].msec); 151 mouse.ri = (i+1)%Mousequeue; 152 unlock(&mouse.lk); 153 if(n > 1+4*12) 154 n = 1+4*12; 155 memmove(va, buf, n); 156 return n; 157 } 158 return 0; 159 } 160 161 long 162 mousewrite(Chan *c, void *va, long n, vlong offset) 163 { 164 char *p; 165 Point pt; 166 char buf[64]; 167 168 USED(offset); 169 170 p = va; 171 switch((long)c->qid.path){ 172 case Qdir: 173 error(Eisdir); 174 175 case Qcursor: 176 if(n < 2*4+2*2*16){ 177 cursorarrow(); 178 }else{ 179 n = 2*4+2*2*16; 180 lock(&cursor.lk); 181 cursor.offset.x = BGLONG(p+0); 182 cursor.offset.y = BGLONG(p+4); 183 memmove(cursor.clr, p+8, 2*16); 184 memmove(cursor.set, p+40, 2*16); 185 unlock(&cursor.lk); 186 setcursor(); 187 } 188 return n; 189 190 case Qmouse: 191 if(n > sizeof buf-1) 192 n = sizeof buf -1; 193 memmove(buf, va, n); 194 buf[n] = 0; 195 p = 0; 196 pt.x = strtoul(buf+1, &p, 0); 197 if(p == 0) 198 error(Eshort); 199 pt.y = strtoul(p, 0, 0); 200 if(ptinrect(pt, gscreen->r)) 201 mouseset(pt); 202 return n; 203 } 204 205 error(Egreg); 206 return -1; 207 } 208 209 int 210 mousechanged(void *a) 211 { 212 USED(a); 213 214 return mouse.ri != mouse.wi || screen.reshaped; 215 } 216 217 Dev mousedevtab = { 218 'm', 219 "mouse", 220 221 devreset, 222 devinit, 223 devshutdown, 224 mouseattach, 225 mousewalk, 226 mousestat, 227 mouseopen, 228 devcreate, 229 mouseclose, 230 mouseread, 231 devbread, 232 mousewrite, 233 devbwrite, 234 devremove, 235 devwstat, 236 }; 237 238