#include #include #include enum{ MAXSLAVE = 32 }; typedef struct Slave Slave; typedef struct Ebuf Ebuf; struct Slave{ int pid; Ebuf *head; /* queue of messages for this descriptor */ Ebuf *tail; }; struct Ebuf{ Ebuf *next; int n; /* number of bytes in buf */ uchar buf[EMAXMSG]; }; static Slave eslave[MAXSLAVE]; static int nslave; static int Smouse = -1; static int Skeyboard = -1; static int Stimer = -1; static int epipe[2]; static Ebuf *ebread(Slave*); static int eforkslave(ulong); static void extract(void); static void ekill(void); static int enote(void *, char *); int logfid; Mouse emouse(void) { Mouse m; Ebuf *eb; static but[2]; int b; if(Smouse < 0) berror("events: mouse not initialzed"); eb = ebread(&eslave[Smouse]); b = eb->buf[1] & 15; but[b>>3] = b & 7; m.buttons = but[0] | but[1]; m.xy.x = BGLONG(eb->buf+2); m.xy.y = BGLONG(eb->buf+6); if (b & 8) /* window relative */ m.xy = add(m.xy, screen.r.min); if (logfid) fprint(logfid, "b: %d xy: %d %d\n", m.buttons, m.xy); free(eb); return m; } int ekbd(void) { Ebuf *eb; int c; if(Skeyboard < 0) berror("events: keyboard not initialzed"); eb = ebread(&eslave[Skeyboard]); c = eb->buf[0] + (eb->buf[1]<<8); free(eb); return c; } ulong event(Event *e) { return eread(~0UL, e); } ulong eread(ulong keys, Event *e) { Ebuf *eb; int i; if(keys) 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; memmove(e->data, eb->buf, e->n); free(eb); } return 1< EMAXMSG) n = EMAXMSG; i = eforkslave(key); if(i < MAXSLAVE) return 1<=0) if(write(epipe[1], buf, r+1)!=r+1) break; buf[0] = MAXSLAVE; write(epipe[1], buf, 1); _exits(0); return 0; } ulong etimer(ulong key, int n) { char t[2]; if(Stimer != -1) berror("events: timer started twice"); Stimer = eforkslave(key); if(Stimer < MAXSLAVE) return 1<>8; write(epipe[1], t, 3); } } void einit(ulong keys) { int ctl, fd; if(pipe(epipe) < 0) berror("events: einit pipe"); atexit(ekill); atnotify(enote, 1); if(keys&Ekeyboard){ fd = open("/dev/cons", OREAD); ctl = open("/dev/consctl", OWRITE); if(fd < 0 || ctl < 0) berror("events: can't open /dev/cons"); write(ctl, "holdoff", 7); write(ctl, "rawon", 5); for(Skeyboard=0; Ekeyboard & ~(1<head && d.length == 0) break; extract(); } eb = s->head; s->head = s->head->next; if(s->head == 0) s->tail = 0; return eb; } static void extract(void) { Slave *s; Ebuf *eb; int i, n; uchar ebuf[EMAXMSG+1]; bflush(); loop: if((n=read(epipe[0], ebuf, EMAXMSG+1)) < 0 || ebuf[0] >= MAXSLAVE) exits("eof on event pipe"); if(n == 0) goto loop; i = ebuf[0]; if(i >= nslave || n <= 1) berror("events: protocol error"); s = &eslave[i]; if(i == Stimer){ s->head = (Ebuf *)1; return; } if(i == Skeyboard && n != 3) berror("events: protocol error"); if(i == Smouse){ if(n!=1+10 || ebuf[1]!='m') berror("events: protocol error"); if(ebuf[2] & 0x80) ereshaped(bscreenrect(0)); /* squash extraneous mouse events */ if(s->head){ free(s->head); s->head = s->tail = 0; } } /* try to save space by only alloacting as much buffer as we need */ eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1); if(eb == 0) berror("events: protocol error"); eb->n = n - 1; memmove(eb->buf, &ebuf[1], n - 1); eb->next = 0; if(s->head) s->tail = s->tail->next = eb; else s->head = s->tail = eb; } static int eforkslave(ulong key) { int i; for(i=0; i 0){ write(fd, "die", 3); close(fd); } } return 0; } static void ekill(void) { enote(0, 0); }