From a287dbab235c9041a32300a9e0bb60ef41864963 Mon Sep 17 00:00:00 2001 From: David Jeannot Date: Tue, 6 Sep 2011 10:10:43 -0400 Subject: devdraw: draft cocoa support R=rsc CC=plan9port.codebot http://codereview.appspot.com/4974060 --- src/cmd/devdraw/cocoa-srv.c | 397 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 397 insertions(+) create mode 100644 src/cmd/devdraw/cocoa-srv.c (limited to 'src/cmd/devdraw/cocoa-srv.c') diff --git a/src/cmd/devdraw/cocoa-srv.c b/src/cmd/devdraw/cocoa-srv.c new file mode 100644 index 00000000..507138f8 --- /dev/null +++ b/src/cmd/devdraw/cocoa-srv.c @@ -0,0 +1,397 @@ +/* + * Window system protocol server. + */ + +#include +#include +#include "cocoa-thread.h" +#include +#include +#include +#include +#include +#include +#include "cocoa-screen.h" +#include "devdraw.h" + +typedef struct Kbdbuf Kbdbuf; +typedef struct Mousebuf Mousebuf; +typedef struct Fdbuf Fdbuf; +typedef struct Tagbuf Tagbuf; + +struct Kbdbuf +{ + Rune r[32]; + int ri; + int wi; + int stall; +}; + +struct Mousebuf +{ + Mouse m[32]; + Mouse last; + int ri; + int wi; + int stall; +}; + +struct Tagbuf +{ + int t[32]; + int ri; + int wi; +}; + +Kbdbuf kbd; +Mousebuf mouse; +Tagbuf kbdtags; +Tagbuf mousetags; + +void runmsg(Wsysmsg*); +void replymsg(Wsysmsg*); +void matchkbd(void); +void matchmouse(void); + + +QLock lk; +void +zlock(void) +{ + qlock(&lk); +} + +void +zunlock(void) +{ + qunlock(&lk); +} + +int trace = 0; + +void +servep9p(void) +{ + uchar buf[4], *mbuf; + int nmbuf, n, nn; + Wsysmsg m; + + fmtinstall('W', drawfcallfmt); + +// notify(bell); + + mbuf = nil; + nmbuf = 0; + while((n = read(3, buf, 4)) == 4){ + GET(buf, n); + if(n > nmbuf){ + free(mbuf); + mbuf = malloc(4+n); + if(mbuf == nil) + sysfatal("malloc: %r"); + nmbuf = n; + } + memmove(mbuf, buf, 4); + nn = readn(3, mbuf+4, n-4); + if(nn != n-4) + sysfatal("eof during message"); + + /* pick off messages one by one */ + if(convM2W(mbuf, nn+4, &m) <= 0) + sysfatal("cannot convert message"); + if(trace) fprint(2, "<- %W\n", &m); + runmsg(&m); + } +} + +void +replyerror(Wsysmsg *m) +{ + char err[256]; + + rerrstr(err, sizeof err); + m->type = Rerror; + m->error = err; + replymsg(m); +} + +/* + * Handle a single wsysmsg. + * Might queue for later (kbd, mouse read) + */ +void +runmsg(Wsysmsg *m) +{ + static uchar buf[65536]; + int n; + Memimage *i; + + switch(m->type){ + case Tinit: + memimageinit(); + i = attachscreen(m->label, m->winsize); + _initdisplaymemimage(i); + replymsg(m); + break; + + case Trdmouse: + zlock(); + mousetags.t[mousetags.wi++] = m->tag; + if(mousetags.wi == nelem(mousetags.t)) + mousetags.wi = 0; + if(mousetags.wi == mousetags.ri) + sysfatal("too many queued mouse reads"); + mouse.stall = 0; + matchmouse(); + zunlock(); + break; + + case Trdkbd: + zlock(); + kbdtags.t[kbdtags.wi++] = m->tag; + if(kbdtags.wi == nelem(kbdtags.t)) + kbdtags.wi = 0; + if(kbdtags.wi == kbdtags.ri) + sysfatal("too many queued keyboard reads"); + kbd.stall = 0; + matchkbd(); + zunlock(); + break; + + case Tmoveto: + setmouse(m->mouse.xy); + replymsg(m); + break; + + case Tcursor: + if(m->arrowcursor) + setcursor(nil); + else + setcursor(&m->cursor); + replymsg(m); + break; + + case Tbouncemouse: + // _xbouncemouse(&m->mouse); + replymsg(m); + break; + + case Tlabel: + kicklabel(m->label); + replymsg(m); + break; + + case Trdsnarf: + m->snarf = getsnarf(); + replymsg(m); + free(m->snarf); + break; + + case Twrsnarf: + putsnarf(m->snarf); + replymsg(m); + break; + + case Trddraw: + n = m->count; + if(n > sizeof buf) + n = sizeof buf; + n = _drawmsgread(buf, n); + if(n < 0) + replyerror(m); + else{ + m->count = n; + m->data = buf; + replymsg(m); + } + break; + + case Twrdraw: + if(_drawmsgwrite(m->data, m->count) < 0) + replyerror(m); + else + replymsg(m); + break; + + case Ttop: + // _xtopwindow(); + replymsg(m); + break; + + case Tresize: + // _xresizewindow(m->rect); + replymsg(m); + break; + } +} + +/* + * Reply to m. + */ +QLock replylock; +void +replymsg(Wsysmsg *m) +{ + int n; + static uchar *mbuf; + static int nmbuf; + + /* T -> R msg */ + if(m->type%2 == 0) + m->type++; + + if(trace) fprint(2, "-> %W\n", m); + /* copy to output buffer */ + n = sizeW2M(m); + + qlock(&replylock); + if(n > nmbuf){ + free(mbuf); + mbuf = malloc(n); + if(mbuf == nil) + sysfatal("out of memory"); + nmbuf = n; + } + convW2M(m, mbuf, n); + if(write(4, mbuf, n) != n) + sysfatal("write: %r"); + qunlock(&replylock); +} + +/* + * Match queued kbd reads with queued kbd characters. + */ +void +matchkbd(void) +{ + Wsysmsg m; + + if(kbd.stall) + return; + while(kbd.ri != kbd.wi && kbdtags.ri != kbdtags.wi){ + m.type = Rrdkbd; + m.tag = kbdtags.t[kbdtags.ri++]; + if(kbdtags.ri == nelem(kbdtags.t)) + kbdtags.ri = 0; + m.rune = kbd.r[kbd.ri++]; + if(kbd.ri == nelem(kbd.r)) + kbd.ri = 0; + replymsg(&m); + } +} + +/* + * Match queued mouse reads with queued mouse events. + */ +void +matchmouse(void) +{ + Wsysmsg m; + + while(mouse.ri != mouse.wi && mousetags.ri != mousetags.wi){ + m.type = Rrdmouse; + m.tag = mousetags.t[mousetags.ri++]; + if(mousetags.ri == nelem(mousetags.t)) + mousetags.ri = 0; + m.mouse = mouse.m[mouse.ri]; + m.resized = mouseresized; + /* + if(m.resized) + fprint(2, "sending resize\n"); + */ + mouseresized = 0; + mouse.ri++; + if(mouse.ri == nelem(mouse.m)) + mouse.ri = 0; + replymsg(&m); + } +} + +void +mousetrack(int x, int y, int b, int ms) +{ + Mouse *m; + + if(x < mouserect.min.x) + x = mouserect.min.x; + if(x > mouserect.max.x) + x = mouserect.max.x; + if(y < mouserect.min.y) + y = mouserect.min.y; + if(y > mouserect.max.y) + y = mouserect.max.y; + + zlock(); + // If reader has stopped reading, don't bother. + // If reader is completely caught up, definitely queue. + // Otherwise, queue only button change events. + if(!mouse.stall) + if(mouse.wi == mouse.ri || mouse.last.buttons != b){ + m = &mouse.last; + m->xy.x = x; + m->xy.y = y; + m->buttons = b; + m->msec = ms; + + mouse.m[mouse.wi] = *m; + if(++mouse.wi == nelem(mouse.m)) + mouse.wi = 0; + if(mouse.wi == mouse.ri){ + mouse.stall = 1; + mouse.ri = 0; + mouse.wi = 1; + mouse.m[0] = *m; + } + matchmouse(); + } + zunlock(); +} + +void +kputc(int c) +{ + zlock(); + kbd.r[kbd.wi++] = c; + if(kbd.wi == nelem(kbd.r)) + kbd.wi = 0; + if(kbd.ri == kbd.wi) + kbd.stall = 1; + matchkbd(); + zunlock(); +} + +void +keystroke(int c) +{ + static Rune k[10]; + static int alting, nk; + int i; + + if(c == Kalt){ + alting = !alting; + return; + } + if(!alting){ + kputc(c); + return; + } + if(nk >= nelem(k)) // should not happen + nk = 0; + k[nk++] = c; + c = _latin1(k, nk); + if(c > 0){ + alting = 0; + kputc(c); + nk = 0; + return; + } + if(c == -1){ + alting = 0; + for(i=0; i