URI:
       tevent.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tevent.c (7535B)
       ---
            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[100];
          207         Wsysmsg w;
          208 
          209         w.type = type;
          210         convW2M(&w, buf, sizeof buf);
          211         return muxrpcstart(display->mux, buf);
          212 }
          213 
          214 static int
          215 finishrpc(Muxrpc *r, Wsysmsg *w)
          216 {
          217         uchar *p;
          218         void *v;
          219         int n;
          220 
          221         if(!muxrpccanfinish(r, &v))
          222                 return 0;
          223         p = v;
          224         if(p == nil)        /* eof on connection */
          225                 exit(0);
          226         GET(p, n);
          227         convM2W(p, n, w);
          228         free(p);
          229         return 1;
          230 }
          231 
          232 static int
          233 extract(int canblock)
          234 {
          235         Ebuf *eb;
          236         int i, n, max;
          237         fd_set rset, wset, xset;
          238         struct timeval tv, *timeout;
          239         Wsysmsg w;
          240         vlong t0;
          241 
          242         /*
          243          * Flush draw buffer before waiting for responses.
          244          * Avoid doing so if buffer is empty.
          245          * Also make sure that we don't interfere with app-specific locking.
          246          */
          247         if(display->locking){
          248                 /*
          249                  * if locking is being done by program,
          250                  * this means it can't depend on automatic
          251                  * flush in emouse() etc.
          252                  */
          253                 if(canqlock(&display->qlock)){
          254                         if(display->bufp > display->buf)
          255                                 flushimage(display, 1);
          256                         unlockdisplay(display);
          257                 }
          258         }else
          259                 if(display->bufp > display->buf)
          260                         flushimage(display, 1);
          261 
          262         /*
          263          * Set up for select.
          264          */
          265         FD_ZERO(&rset);
          266         FD_ZERO(&wset);
          267         FD_ZERO(&xset);
          268         max = -1;
          269         timeout = nil;
          270         for(i=0; i<nslave; i++){
          271                 if(!eslave[i].inuse)
          272                         continue;
          273                 if(i == Smouse){
          274                         if(eslave[i].rpc == nil)
          275                                 eslave[i].rpc = startrpc(Trdmouse);
          276                         if(eslave[i].rpc){
          277                                 /* if ready, don't block in select */
          278                                 if(eslave[i].rpc->p)
          279                                         canblock = 0;
          280                                 FD_SET(display->srvfd, &rset);
          281                                 FD_SET(display->srvfd, &xset);
          282                                 if(display->srvfd > max)
          283                                         max = display->srvfd;
          284                         }
          285                 }else if(i == Skeyboard){
          286                         if(eslave[i].rpc == nil)
          287                                 eslave[i].rpc = startrpc(Trdkbd4);
          288                         if(eslave[i].rpc){
          289                                 /* if ready, don't block in select */
          290                                 if(eslave[i].rpc->p)
          291                                         canblock = 0;
          292                                 FD_SET(display->srvfd, &rset);
          293                                 FD_SET(display->srvfd, &xset);
          294                                 if(display->srvfd > max)
          295                                         max = display->srvfd;
          296                         }
          297                 }else if(i == Stimer){
          298                         t0 = nsec();
          299                         if(t0 >= eslave[i].nexttick){
          300                                 tv.tv_sec = 0;
          301                                 tv.tv_usec = 0;
          302                         }else{
          303                                 tv.tv_sec = (eslave[i].nexttick-t0)/1000000000;
          304                                 tv.tv_usec = (eslave[i].nexttick-t0)%1000000000 / 1000;
          305                         }
          306                         timeout = &tv;
          307                 }else{
          308                         FD_SET(eslave[i].fd, &rset);
          309                         FD_SET(eslave[i].fd, &xset);
          310                         if(eslave[i].fd > max)
          311                                 max = eslave[i].fd;
          312                 }
          313         }
          314 
          315         if(!canblock){
          316                 tv.tv_sec = 0;
          317                 tv.tv_usec = 0;
          318                 timeout = &tv;
          319         }
          320 
          321         if(select(max+1, &rset, &wset, &xset, timeout) < 0)
          322                 drawerror(display, "select failure");
          323 
          324         /*
          325          * Look to see what can proceed.
          326          */
          327         n = 0;
          328         for(i=0; i<nslave; i++){
          329                 if(!eslave[i].inuse)
          330                         continue;
          331                 if(i == Smouse){
          332                         if(finishrpc(eslave[i].rpc, &w)){
          333                                 eslave[i].rpc = nil;
          334                                 eb = newebuf(&eslave[i], sizeof(Mouse));
          335                                 _drawmouse = w.mouse;
          336                                 eb->u.mouse = w.mouse;
          337                                 if(w.resized)
          338                                         eresized(1);
          339                                 n++;
          340                         }
          341                 }else if(i == Skeyboard){
          342                         if(finishrpc(eslave[i].rpc, &w)){
          343                                 eslave[i].rpc = nil;
          344                                 eb = newebuf(&eslave[i], sizeof(Rune)+2);        /* +8: alignment */
          345                                 eb->u.rune = w.rune;
          346                                 n++;
          347                         }
          348                 }else if(i == Stimer){
          349                         t0 = nsec();
          350                         while(t0 > eslave[i].nexttick){
          351                                 eslave[i].nexttick += eslave[i].n*1000000LL;
          352                                 eslave[i].head = (Ebuf*)1;
          353                                 n++;
          354                         }
          355                 }else{
          356                         if(FD_ISSET(eslave[i].fd, &rset)){
          357                                 eb = newebuf(&eslave[i], eslave[i].n);
          358                                 eb->n = read(eslave[i].fd, eb->u.buf, eslave[i].n);
          359                                 n++;
          360                         }
          361                 }
          362         }
          363         return n;
          364 }
          365 
          366 static int
          367 newkey(ulong key)
          368 {
          369         int i;
          370 
          371         for(i=0; i<MAXSLAVE; i++)
          372                 if((key & ~(1<<i)) == 0 && eslave[i].inuse == 0){
          373                         if(nslave <= i)
          374                                 nslave = i + 1;
          375                         eslave[i].inuse = 1;
          376                         return i;
          377                 }
          378         drawerror(display, "events: bad slave assignment");
          379         return 0;
          380 }
          381 
          382 Mouse
          383 emouse(void)
          384 {
          385         Mouse m;
          386         Ebuf *eb;
          387 
          388         if(Smouse < 0)
          389                 drawerror(display, "events: mouse not initialized");
          390         eb = ebread(&eslave[Smouse]);
          391         m = eb->u.mouse;
          392         free(eb);
          393         return m;
          394 }
          395 
          396 int
          397 ekbd(void)
          398 {
          399         Ebuf *eb;
          400         int c;
          401 
          402         if(Skeyboard < 0)
          403                 drawerror(display, "events: keyboard not initialzed");
          404         eb = ebread(&eslave[Skeyboard]);
          405         c = eb->u.rune;
          406         free(eb);
          407         return c;
          408 }
          409 
          410 void
          411 emoveto(Point pt)
          412 {
          413         _displaymoveto(display, pt);
          414 }
          415 
          416 void
          417 esetcursor(Cursor *c)
          418 {
          419         _displaycursor(display, c, nil);
          420 }
          421 
          422 void
          423 esetcursor2(Cursor *c, Cursor2 *c2)
          424 {
          425         _displaycursor(display, c, c2);
          426 }
          427 
          428 int
          429 ereadmouse(Mouse *m)
          430 {
          431         int resized;
          432 
          433         resized = 0;
          434         if(_displayrdmouse(display, m, &resized) < 0)
          435                 return -1;
          436         if(resized)
          437                 eresized(1);
          438         return 1;
          439 }