123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <cursor.h>
- #include <event.h>
- typedef struct Slave Slave;
- typedef struct Ebuf Ebuf;
- struct Slave
- {
- int pid;
- Ebuf *head; /* queue of messages for this descriptor */
- Ebuf *tail;
- int (*fn)(int, Event*, uint8_t*, int);
- };
- struct Ebuf
- {
- Ebuf *next;
- int n; /* number of bytes in buf */
- uint8_t buf[EMAXMSG];
- };
- static Slave eslave[MAXSLAVE];
- static int Skeyboard = -1;
- static int Smouse = -1;
- static int Stimer = -1;
- static int logfid;
- static int nslave;
- static int parentpid;
- static int epipe[2];
- static int eforkslave(uint32_t);
- static void extract(void);
- static void ekill(void);
- static int enote(void *, char *);
- static int mousefd;
- static int cursorfd;
- static
- Ebuf*
- ebread(Slave *s)
- {
- Ebuf *eb;
- Dir *d;
- uint32_t l;
- for(;;){
- d = dirfstat(epipe[0]);
- if(d == nil)
- drawerror(display, "events: eread stat error");
- l = d->length;
- free(d);
- if(s->head && l==0)
- break;
- extract();
- }
- eb = s->head;
- s->head = s->head->next;
- if(s->head == 0)
- s->tail = 0;
- return eb;
- }
- uint32_t
- event(Event *e)
- {
- return eread((uint32_t)~0UL, e);
- }
- uint32_t
- eread(uint32_t keys, Event *e)
- {
- Ebuf *eb;
- int i, id;
- if(keys == 0)
- return 0;
- for(;;){
- for(i=0; i<nslave; i++)
- if((keys & (1<<i)) && eslave[i].head){
- id = 1<<i;
- if(i == Smouse)
- e->mouse = 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->buf, eb->n);
- else
- memmove(e->data, eb->buf, eb->n);
- free(eb);
- }
- return id;
- }
- extract();
- }
- }
- 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(uint32_t keys)
- {
- Dir *d;
- int i;
- uint32_t l;
- for(;;){
- for(i=0; i<nslave; i++)
- if((keys & (1<<i)) && eslave[i].head)
- return 1;
- d = dirfstat(epipe[0]);
- if(d == nil)
- drawerror(display, "events: ecanread stat error");
- l = d->length;
- free(d);
- if(l == 0)
- return 0;
- extract();
- }
- }
- uint32_t
- estartfn(uint32_t key, int fd, int n, int (*fn)(int, Event*, uint8_t*, int))
- {
- char buf[EMAXMSG+1];
- int i, r;
- if(fd < 0)
- drawerror(display, "events: bad file descriptor");
- if(n <= 0 || n > EMAXMSG)
- n = EMAXMSG;
- i = eforkslave(key);
- if(i < MAXSLAVE){
- eslave[i].fn = fn;
- return 1<<i;
- }
- buf[0] = i - MAXSLAVE;
- while((r = read(fd, buf+1, n))>0)
- if(write(epipe[1], buf, r+1)!=r+1)
- break;
- buf[0] = MAXSLAVE;
- write(epipe[1], buf, 1);
- _exits(0);
- return 0;
- }
- uint32_t
- estart(uint32_t key, int fd, int n)
- {
- return estartfn(key, fd, n, nil);
- }
- uint32_t
- etimer(uint32_t key, int n)
- {
- char t[2];
- if(Stimer != -1)
- drawerror(display, "events: timer started twice");
- Stimer = eforkslave(key);
- if(Stimer < MAXSLAVE)
- return 1<<Stimer;
- if(n <= 0)
- n = 1000;
- t[0] = t[1] = Stimer - MAXSLAVE;
- do
- sleep(n);
- while(write(epipe[1], t, 2) == 2);
- t[0] = MAXSLAVE;
- write(epipe[1], t, 1);
- _exits(0);
- return 0;
- }
- static void
- ekeyslave(int fd)
- {
- Rune r;
- char t[3], k[10];
- int kr, kn, w;
- if(eforkslave(Ekeyboard) < MAXSLAVE)
- return;
- kn = 0;
- t[0] = Skeyboard;
- for(;;){
- while(!fullrune(k, kn)){
- kr = read(fd, k+kn, sizeof k - kn);
- if(kr <= 0)
- goto breakout;
- kn += kr;
- }
- w = chartorune(&r, k);
- kn -= w;
- memmove(k, &k[w], kn);
- t[1] = r;
- t[2] = r>>8;
- if(write(epipe[1], t, 3) != 3)
- break;
- }
- breakout:;
- t[0] = MAXSLAVE;
- write(epipe[1], t, 1);
- _exits(0);
- }
- void
- einit(uint32_t keys)
- {
- int ctl, fd;
- char buf[256];
- parentpid = getpid();
- if(pipe(epipe) < 0)
- drawerror(display, "events: einit pipe");
- atexit(ekill);
- atnotify(enote, 1);
- snprint(buf, sizeof buf, "%s/mouse", display->devdir);
- mousefd = open(buf, ORDWR|OCEXEC);
- if(mousefd < 0)
- drawerror(display, "einit: can't open mouse\n");
- snprint(buf, sizeof buf, "%s/cursor", display->devdir);
- cursorfd = open(buf, ORDWR|OCEXEC);
- if(cursorfd < 0)
- drawerror(display, "einit: can't open cursor\n");
- if(keys&Ekeyboard){
- snprint(buf, sizeof buf, "%s/cons", display->devdir);
- fd = open(buf, OREAD);
- if(fd < 0)
- drawerror(display, "events: can't open console");
- snprint(buf, sizeof buf, "%s/consctl", display->devdir);
- ctl = open("/dev/consctl", OWRITE|OCEXEC);
- if(ctl < 0)
- drawerror(display, "events: can't open consctl");
- write(ctl, "rawon", 5);
- for(Skeyboard=0; Ekeyboard & ~(1<<Skeyboard); Skeyboard++)
- ;
- ekeyslave(fd);
- // if (ctl > 0) {
- // close(ctl);
- // }
- }
- if(keys&Emouse){
- estart(Emouse, mousefd, 1+4*12);
- for(Smouse=0; Emouse & ~(1<<Smouse); Smouse++)
- ;
- }
- }
- static void
- extract(void)
- {
- Slave *s;
- Ebuf *eb;
- int i, n;
- uint8_t ebuf[EMAXMSG+1];
- /* avoid generating a message if there's nothing to show. */
- /* this test isn't perfect, though; could do flushimage(display, 0) then call extract */
- /* also: make sure we don't interfere if we're multiprocessing the display */
- 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);
- loop:
- if((n=read(epipe[0], ebuf, EMAXMSG+1)) < 0
- || ebuf[0] >= MAXSLAVE)
- drawerror(display, "eof on event pipe");
- if(n == 0)
- goto loop;
- i = ebuf[0];
- if(i >= nslave || n <= 1)
- drawerror(display, "events: protocol error: short read");
- s = &eslave[i];
- if(i == Stimer){
- s->head = (Ebuf *)1;
- return;
- }
- if(i == Skeyboard && n != 3)
- drawerror(display, "events: protocol error: keyboard");
- if(i == Smouse){
- if(n < 1+1+2*12)
- drawerror(display, "events: protocol error: mouse");
- if(ebuf[1] == 'r')
- eresized(1);
- /* squash extraneous mouse events */
- if((eb=s->tail) && memcmp(eb->buf+1+2*12, ebuf+1+1+2*12, 12)==0){
- memmove(eb->buf, &ebuf[1], n - 1);
- return;
- }
- }
- /* try to save space by only allocating as much buffer as we need */
- eb = malloc(sizeof(*eb) - sizeof(eb->buf) + n - 1);
- if(eb == 0)
- drawerror(display, "events: protocol error 4");
- 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(uint32_t key)
- {
- int i, pid;
- for(i=0; i<MAXSLAVE; i++)
- if((key & ~(1<<i)) == 0 && eslave[i].pid == 0){
- if(nslave <= i)
- nslave = i + 1;
- /*
- * share the file descriptors so the last child
- * out closes all connections to the window server.
- */
- switch(pid = rfork(RFPROC)){
- case 0:
- return MAXSLAVE+i;
- case -1:
- fprint(2, "events: fork error\n");
- exits("fork");
- }
- eslave[i].pid = pid;
- eslave[i].head = eslave[i].tail = 0;
- return i;
- }
- drawerror(display, "events: bad slave assignment");
- return 0;
- }
- static int
- enote(void *v, char *s)
- {
- char t[1];
- int i, pid;
- USED(v);USED(s);
- pid = getpid();
- if(pid != parentpid){
- for(i=0; i<nslave; i++){
- if(pid == eslave[i].pid){
- t[0] = MAXSLAVE;
- write(epipe[1], t, 1);
- break;
- }
- }
- return 0;
- }
- close(epipe[0]);
- epipe[0] = -1;
- close(epipe[1]);
- epipe[1] = -1;
- for(i=0; i<nslave; i++){
- if(pid == eslave[i].pid)
- continue; /* don't kill myself */
- postnote(PNPROC, eslave[i].pid, "die");
- }
- return 0;
- }
- static void
- ekill(void)
- {
- enote(0, 0);
- }
- Mouse
- emouse(void)
- {
- Mouse m;
- Ebuf *eb;
- //static but[2];
- int b;
- if(Smouse < 0)
- drawerror(display, "events: mouse not initialized");
- eb = ebread(&eslave[Smouse]);
- m.xy.x = atoi((char*)eb->buf+1+0*12);
- m.xy.y = atoi((char*)eb->buf+1+1*12);
- b = atoi((char*)eb->buf+1+2*12);
- m.buttons = b;
- m.msec = atoi((char*)eb->buf+1+3*12);
- if (logfid)
- fprint(logfid, "b: %d xy: %P\n", m.buttons, m.xy);
- 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->buf[0] + (eb->buf[1]<<8);
- free(eb);
- return c;
- }
- void
- emoveto(Point pt)
- {
- char buf[2*12+2];
- int n;
- n = sprint(buf, "m%d %d", pt.x, pt.y);
- write(mousefd, buf, n);
- }
- void
- esetcursor(Cursor *c)
- {
- uint8_t curs[2*4+2*2*16];
- if(c == 0)
- write(cursorfd, curs, 0);
- else{
- BPLONG(curs+0*4, c->offset.x);
- BPLONG(curs+1*4, c->offset.y);
- memmove(curs+2*4, c->clr, 2*2*16);
- write(cursorfd, curs, sizeof curs);
- }
- }
- int
- ereadmouse(Mouse *m)
- {
- int n;
- char buf[128];
- do{
- n = read(mousefd, buf, sizeof(buf));
- if(n < 0) /* probably interrupted */
- return -1;
- n = eatomouse(m, buf, n);
- }while(n == 0);
- return n;
- }
- int
- eatomouse(Mouse *m, char *buf, int n)
- {
- if(n != 1+4*12){
- werrstr("atomouse: bad count");
- return -1;
- }
- if(buf[0] == 'r')
- eresized(1);
- m->xy.x = atoi(buf+1+0*12);
- m->xy.y = atoi(buf+1+1*12);
- m->buttons = atoi(buf+1+2*12);
- m->msec = atoi(buf+1+3*12);
- return n;
- }
|