event.c (7557B)
1 #include <u.h> 2 #include <sys/select.h> 3 #include <libc.h> 4 #include <draw.h> 5 #include <cursor.h> 6 #include <event.h> 7 #include <mux.h> 8 #include <drawfcall.h> 9 10 typedef struct Slave Slave; 11 typedef struct Ebuf Ebuf; 12 extern Mouse _drawmouse; 13 14 struct Slave 15 { 16 int inuse; 17 Ebuf *head; /* queue of messages for this descriptor */ 18 Ebuf *tail; 19 int (*fn)(int, Event*, uchar*, int); 20 Muxrpc *rpc; 21 vlong nexttick; 22 int fd; 23 int n; 24 }; 25 26 struct Ebuf 27 { 28 Ebuf *next; 29 int n; /* number of bytes in buf */ 30 union { 31 uchar buf[EMAXMSG]; 32 Rune rune; 33 Mouse mouse; 34 } u; 35 }; 36 37 static Slave eslave[MAXSLAVE]; 38 static int Skeyboard = -1; 39 static int Smouse = -1; 40 static int Stimer = -1; 41 42 static int nslave; 43 static int newkey(ulong); 44 static int extract(int canblock); 45 46 static 47 Ebuf* 48 ebread(Slave *s) 49 { 50 Ebuf *eb; 51 52 while(!s->head) 53 extract(1); 54 eb = s->head; 55 s->head = s->head->next; 56 if(s->head == 0) 57 s->tail = 0; 58 return eb; 59 } 60 61 ulong 62 event(Event *e) 63 { 64 return eread(~0UL, e); 65 } 66 67 ulong 68 eread(ulong keys, Event *e) 69 { 70 Ebuf *eb; 71 int i, id; 72 73 if(keys == 0) 74 return 0; 75 for(;;){ 76 for(i=0; i<nslave; i++) 77 if((keys & (1<<i)) && eslave[i].head){ 78 id = 1<<i; 79 if(i == Smouse) 80 e->mouse = emouse(); 81 else if(i == Skeyboard) 82 e->kbdc = ekbd(); 83 else if(i == Stimer) 84 eslave[i].head = 0; 85 else{ 86 eb = ebread(&eslave[i]); 87 e->n = eb->n; 88 if(eslave[i].fn) 89 id = (*eslave[i].fn)(id, e, eb->u.buf, eb->n); 90 else 91 memmove(e->data, eb->u.buf, eb->n); 92 free(eb); 93 } 94 return id; 95 } 96 extract(1); 97 } 98 return 0; 99 } 100 101 int 102 ecanmouse(void) 103 { 104 if(Smouse < 0) 105 drawerror(display, "events: mouse not initialized"); 106 return ecanread(Emouse); 107 } 108 109 int 110 ecankbd(void) 111 { 112 if(Skeyboard < 0) 113 drawerror(display, "events: keyboard not initialzed"); 114 return ecanread(Ekeyboard); 115 } 116 117 int 118 ecanread(ulong keys) 119 { 120 int i; 121 122 for(;;){ 123 for(i=0; i<nslave; i++) 124 if((keys & (1<<i)) && eslave[i].head) 125 return 1; 126 if(!extract(0)) 127 return 0; 128 } 129 return -1; 130 } 131 132 ulong 133 estartfn(ulong key, int fd, int n, int (*fn)(int, Event*, uchar*, int)) 134 { 135 int i; 136 137 if(fd < 0) 138 drawerror(display, "events: bad file descriptor"); 139 if(n <= 0 || n > EMAXMSG) 140 n = EMAXMSG; 141 i = newkey(key); 142 eslave[i].fn = fn; 143 eslave[i].fd = fd; 144 eslave[i].n = n; 145 return 1<<i; 146 } 147 148 ulong 149 estart(ulong key, int fd, int n) 150 { 151 return estartfn(key, fd, n, nil); 152 } 153 154 ulong 155 etimer(ulong key, int n) 156 { 157 if(Stimer != -1) 158 drawerror(display, "events: timer started twice"); 159 Stimer = newkey(key); 160 if(n <= 0) 161 n = 1000; 162 eslave[Stimer].n = n; 163 eslave[Stimer].nexttick = nsec()+n*1000000LL; 164 return 1<<Stimer; 165 } 166 167 void 168 einit(ulong keys) 169 { 170 if(keys&Ekeyboard){ 171 for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++) 172 ; 173 eslave[Skeyboard].inuse = 1; 174 if(nslave <= Skeyboard) 175 nslave = Skeyboard+1; 176 } 177 if(keys&Emouse){ 178 for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++) 179 ; 180 eslave[Smouse].inuse = 1; 181 if(nslave <= Smouse) 182 nslave = Smouse+1; 183 } 184 } 185 186 static Ebuf* 187 newebuf(Slave *s, int n) 188 { 189 Ebuf *eb; 190 191 eb = malloc(sizeof(*eb) - sizeof(eb->u.buf) + n); 192 if(eb == nil) 193 drawerror(display, "events: out of memory"); 194 eb->n = n; 195 eb->next = 0; 196 if(s->head) 197 s->tail = s->tail->next = eb; 198 else 199 s->head = s->tail = eb; 200 return eb; 201 } 202 203 static Muxrpc* 204 startrpc(int type) 205 { 206 uchar buf[512]; 207 Wsysmsg w; 208 209 w.type = type; 210 if(convW2M(&w, buf, sizeof buf) == 0) 211 return nil; 212 return muxrpcstart(display->mux, buf); 213 } 214 215 static int 216 finishrpc(Muxrpc *r, Wsysmsg *w) 217 { 218 uchar *p; 219 void *v; 220 int n; 221 222 if(!muxrpccanfinish(r, &v)) 223 return 0; 224 p = v; 225 if(p == nil) /* eof on connection */ 226 exit(0); 227 GET(p, n); 228 convM2W(p, n, w); 229 free(p); 230 return 1; 231 } 232 233 static int 234 extract(int canblock) 235 { 236 Ebuf *eb; 237 int i, n, max; 238 fd_set rset, wset, xset; 239 struct timeval tv, *timeout; 240 Wsysmsg w; 241 vlong t0; 242 243 /* 244 * Flush draw buffer before waiting for responses. 245 * Avoid doing so if buffer is empty. 246 * Also make sure that we don't interfere with app-specific locking. 247 */ 248 if(display->locking){ 249 /* 250 * if locking is being done by program, 251 * this means it can't depend on automatic 252 * flush in emouse() etc. 253 */ 254 if(canqlock(&display->qlock)){ 255 if(display->bufp > display->buf) 256 flushimage(display, 1); 257 unlockdisplay(display); 258 } 259 }else 260 if(display->bufp > display->buf) 261 flushimage(display, 1); 262 263 /* 264 * Set up for select. 265 */ 266 FD_ZERO(&rset); 267 FD_ZERO(&wset); 268 FD_ZERO(&xset); 269 max = -1; 270 timeout = nil; 271 for(i=0; i<nslave; i++){ 272 if(!eslave[i].inuse) 273 continue; 274 if(i == Smouse){ 275 if(eslave[i].rpc == nil) 276 eslave[i].rpc = startrpc(Trdmouse); 277 if(eslave[i].rpc){ 278 /* if ready, don't block in select */ 279 if(eslave[i].rpc->p) 280 canblock = 0; 281 FD_SET(display->srvfd, &rset); 282 FD_SET(display->srvfd, &xset); 283 if(display->srvfd > max) 284 max = display->srvfd; 285 } 286 }else if(i == Skeyboard){ 287 if(eslave[i].rpc == nil) 288 eslave[i].rpc = startrpc(Trdkbd4); 289 if(eslave[i].rpc){ 290 /* if ready, don't block in select */ 291 if(eslave[i].rpc->p) 292 canblock = 0; 293 FD_SET(display->srvfd, &rset); 294 FD_SET(display->srvfd, &xset); 295 if(display->srvfd > max) 296 max = display->srvfd; 297 } 298 }else if(i == Stimer){ 299 t0 = nsec(); 300 if(t0 >= eslave[i].nexttick){ 301 tv.tv_sec = 0; 302 tv.tv_usec = 0; 303 }else{ 304 tv.tv_sec = (eslave[i].nexttick-t0)/1000000000; 305 tv.tv_usec = (eslave[i].nexttick-t0)%1000000000 / 1000; 306 } 307 timeout = &tv; 308 }else{ 309 FD_SET(eslave[i].fd, &rset); 310 FD_SET(eslave[i].fd, &xset); 311 if(eslave[i].fd > max) 312 max = eslave[i].fd; 313 } 314 } 315 316 if(!canblock){ 317 tv.tv_sec = 0; 318 tv.tv_usec = 0; 319 timeout = &tv; 320 } 321 322 if(select(max+1, &rset, &wset, &xset, timeout) < 0) 323 drawerror(display, "select failure"); 324 325 /* 326 * Look to see what can proceed. 327 */ 328 n = 0; 329 for(i=0; i<nslave; i++){ 330 if(!eslave[i].inuse) 331 continue; 332 if(i == Smouse){ 333 if(finishrpc(eslave[i].rpc, &w)){ 334 eslave[i].rpc = nil; 335 eb = newebuf(&eslave[i], sizeof(Mouse)); 336 _drawmouse = w.mouse; 337 eb->u.mouse = w.mouse; 338 if(w.resized) 339 eresized(1); 340 n++; 341 } 342 }else if(i == Skeyboard){ 343 if(finishrpc(eslave[i].rpc, &w)){ 344 eslave[i].rpc = nil; 345 eb = newebuf(&eslave[i], sizeof(Rune)+2); /* +8: alignment */ 346 eb->u.rune = w.rune; 347 n++; 348 } 349 }else if(i == Stimer){ 350 t0 = nsec(); 351 while(t0 > eslave[i].nexttick){ 352 eslave[i].nexttick += eslave[i].n*1000000LL; 353 eslave[i].head = (Ebuf*)1; 354 n++; 355 } 356 }else{ 357 if(FD_ISSET(eslave[i].fd, &rset)){ 358 eb = newebuf(&eslave[i], eslave[i].n); 359 eb->n = read(eslave[i].fd, eb->u.buf, eslave[i].n); 360 n++; 361 } 362 } 363 } 364 return n; 365 } 366 367 static int 368 newkey(ulong key) 369 { 370 int i; 371 372 for(i=0; i<MAXSLAVE; i++) 373 if((key & ~(1<<i)) == 0 && eslave[i].inuse == 0){ 374 if(nslave <= i) 375 nslave = i + 1; 376 eslave[i].inuse = 1; 377 return i; 378 } 379 drawerror(display, "events: bad slave assignment"); 380 return 0; 381 } 382 383 Mouse 384 emouse(void) 385 { 386 Mouse m; 387 Ebuf *eb; 388 389 if(Smouse < 0) 390 drawerror(display, "events: mouse not initialized"); 391 eb = ebread(&eslave[Smouse]); 392 m = eb->u.mouse; 393 free(eb); 394 return m; 395 } 396 397 int 398 ekbd(void) 399 { 400 Ebuf *eb; 401 int c; 402 403 if(Skeyboard < 0) 404 drawerror(display, "events: keyboard not initialzed"); 405 eb = ebread(&eslave[Skeyboard]); 406 c = eb->u.rune; 407 free(eb); 408 return c; 409 } 410 411 void 412 emoveto(Point pt) 413 { 414 _displaymoveto(display, pt); 415 } 416 417 void 418 esetcursor(Cursor *c) 419 { 420 _displaycursor(display, c, nil); 421 } 422 423 void 424 esetcursor2(Cursor *c, Cursor2 *c2) 425 { 426 _displaycursor(display, c, c2); 427 } 428 429 int 430 ereadmouse(Mouse *m) 431 { 432 int resized; 433 434 resized = 0; 435 if(_displayrdmouse(display, m, &resized) < 0) 436 return -1; 437 if(resized) 438 eresized(1); 439 return 1; 440 }