#include #include #include #include #include #include #include #include typedef struct Slave Slave; typedef struct Ebuf Ebuf; extern Mouse _drawmouse; struct Slave { int inuse; Ebuf *head; /* queue of messages for this descriptor */ Ebuf *tail; int (*fn)(int, Event*, uchar*, int); Muxrpc *rpc; vlong nexttick; int fd; int n; }; struct Ebuf { Ebuf *next; int n; /* number of bytes in buf */ union { uchar buf[EMAXMSG]; Rune rune; Mouse mouse; } u; }; static Slave eslave[MAXSLAVE]; static int Skeyboard = -1; static int Smouse = -1; static int Stimer = -1; static int nslave; static int newkey(ulong); static int extract(int canblock); static Ebuf* ebread(Slave *s) { Ebuf *eb; while(!s->head) extract(1); eb = s->head; s->head = s->head->next; if(s->head == 0) s->tail = 0; return eb; } ulong event(Event *e) { return eread(~0UL, e); } ulong eread(ulong keys, Event *e) { Ebuf *eb; int i, id; if(keys == 0) return 0; for(;;){ for(i=0; imouse = emouse(); else if(i == Skeyboard) e->kbdc = ekbd(); else if(i == Stimer) eslave[i].head = 0; else{ eb = ebread(&eslave[i]); e->n = eb->n; if(eslave[i].fn) id = (*eslave[i].fn)(id, e, eb->u.buf, eb->n); else memmove(e->data, eb->u.buf, eb->n); free(eb); } return id; } extract(1); } return 0; } int ecanmouse(void) { if(Smouse < 0) drawerror(display, "events: mouse not initialized"); return ecanread(Emouse); } int ecankbd(void) { if(Skeyboard < 0) drawerror(display, "events: keyboard not initialzed"); return ecanread(Ekeyboard); } int ecanread(ulong keys) { int i; for(;;){ for(i=0; i EMAXMSG) n = EMAXMSG; i = newkey(key); eslave[i].fn = fn; eslave[i].fd = fd; eslave[i].n = n; return 1<u.buf) + n); if(eb == nil) drawerror(display, "events: out of memory"); eb->n = n; eb->next = 0; if(s->head) s->tail = s->tail->next = eb; else s->head = s->tail = eb; return eb; } static Muxrpc* startrpc(int type) { uchar buf[512]; Wsysmsg w; w.type = type; if(convW2M(&w, buf, sizeof buf) == 0) return nil; return muxrpcstart(display->mux, buf); } static int finishrpc(Muxrpc *r, Wsysmsg *w) { uchar *p; void *v; int n; if(!muxrpccanfinish(r, &v)) return 0; p = v; if(p == nil) /* eof on connection */ exit(0); GET(p, n); convM2W(p, n, w); free(p); return 1; } static int extract(int canblock) { Ebuf *eb; int i, n, max; fd_set rset, wset, xset; struct timeval tv, *timeout; Wsysmsg w; vlong t0; /* * Flush draw buffer before waiting for responses. * Avoid doing so if buffer is empty. * Also make sure that we don't interfere with app-specific locking. */ if(display->locking){ /* * if locking is being done by program, * this means it can't depend on automatic * flush in emouse() etc. */ if(canqlock(&display->qlock)){ if(display->bufp > display->buf) flushimage(display, 1); unlockdisplay(display); } }else if(display->bufp > display->buf) flushimage(display, 1); /* * Set up for select. */ FD_ZERO(&rset); FD_ZERO(&wset); FD_ZERO(&xset); max = -1; timeout = nil; for(i=0; ip) canblock = 0; FD_SET(display->srvfd, &rset); FD_SET(display->srvfd, &xset); if(display->srvfd > max) max = display->srvfd; } }else if(i == Skeyboard){ if(eslave[i].rpc == nil) eslave[i].rpc = startrpc(Trdkbd4); if(eslave[i].rpc){ /* if ready, don't block in select */ if(eslave[i].rpc->p) canblock = 0; FD_SET(display->srvfd, &rset); FD_SET(display->srvfd, &xset); if(display->srvfd > max) max = display->srvfd; } }else if(i == Stimer){ t0 = nsec(); if(t0 >= eslave[i].nexttick){ tv.tv_sec = 0; tv.tv_usec = 0; }else{ tv.tv_sec = (eslave[i].nexttick-t0)/1000000000; tv.tv_usec = (eslave[i].nexttick-t0)%1000000000 / 1000; } timeout = &tv; }else{ FD_SET(eslave[i].fd, &rset); FD_SET(eslave[i].fd, &xset); if(eslave[i].fd > max) max = eslave[i].fd; } } if(!canblock){ tv.tv_sec = 0; tv.tv_usec = 0; timeout = &tv; } if(select(max+1, &rset, &wset, &xset, timeout) < 0) drawerror(display, "select failure"); /* * Look to see what can proceed. */ n = 0; for(i=0; iu.mouse = w.mouse; if(w.resized) eresized(1); n++; } }else if(i == Skeyboard){ if(finishrpc(eslave[i].rpc, &w)){ eslave[i].rpc = nil; eb = newebuf(&eslave[i], sizeof(Rune)+2); /* +8: alignment */ eb->u.rune = w.rune; n++; } }else if(i == Stimer){ t0 = nsec(); while(t0 > eslave[i].nexttick){ eslave[i].nexttick += eslave[i].n*1000000LL; eslave[i].head = (Ebuf*)1; n++; } }else{ if(FD_ISSET(eslave[i].fd, &rset)){ eb = newebuf(&eslave[i], eslave[i].n); eb->n = read(eslave[i].fd, eb->u.buf, eslave[i].n); n++; } } } return n; } static int newkey(ulong key) { int i; for(i=0; iu.mouse; free(eb); return m; } int ekbd(void) { Ebuf *eb; int c; if(Skeyboard < 0) drawerror(display, "events: keyboard not initialzed"); eb = ebread(&eslave[Skeyboard]); c = eb->u.rune; free(eb); return c; } void emoveto(Point pt) { _displaymoveto(display, pt); } void esetcursor(Cursor *c) { _displaycursor(display, c, nil); } void esetcursor2(Cursor *c, Cursor2 *c2) { _displaycursor(display, c, c2); } int ereadmouse(Mouse *m) { int resized; resized = 0; if(_displayrdmouse(display, m, &resized) < 0) return -1; if(resized) eresized(1); return 1; }