From 9142d36228acc954b289705244ce2477187091e9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 30 Jun 2008 19:41:08 -0400 Subject: devdraw: OS X native version --- src/cmd/devdraw/osx-srv.c | 410 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 410 insertions(+) create mode 100644 src/cmd/devdraw/osx-srv.c (limited to 'src/cmd/devdraw/osx-srv.c') diff --git a/src/cmd/devdraw/osx-srv.c b/src/cmd/devdraw/osx-srv.c new file mode 100644 index 00000000..9dded632 --- /dev/null +++ b/src/cmd/devdraw/osx-srv.c @@ -0,0 +1,410 @@ +/* + * Window system protocol server. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "osx-screen.h" +#include "devdraw.h" + +#undef time + +#define MouseMask (\ + ButtonPressMask|\ + ButtonReleaseMask|\ + PointerMotionMask|\ + Button1MotionMask|\ + Button2MotionMask|\ + Button3MotionMask) + +#define Mask MouseMask|ExposureMask|StructureNotifyMask|KeyPressMask|EnterWindowMask|LeaveWindowMask + +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]; + int ri; + int wi; + int stall; +}; + +struct Tagbuf +{ + int t[32]; + int ri; + int wi; +}; + +Kbdbuf kbd; +Mousebuf mouse; +Tagbuf kbdtags; +Tagbuf mousetags; + +void fdslide(Fdbuf*); +void runmsg(Wsysmsg*); +void replymsg(Wsysmsg*); +void matchkbd(void); +void matchmouse(void); +int fdnoblock(int); +Rectangle mouserect; +int mouseresized; + + +QLock lk; +void +zlock(void) +{ + qlock(&lk); +} + +void +zunlock(void) +{ + qunlock(&lk); +} + +int chatty; +int drawsleep; +int trace; + +void +usage(void) +{ + fprint(2, "usage: devdraw (don't run directly)\n"); + threadexitsall("usage"); +} + +void +bell(void *v, char *msg) +{ + if(strcmp(msg, "alarm") == 0) + drawsleep = drawsleep ? 0 : 1000; + noted(NCONT); +} + +void +threadmain(int argc, char **argv) +{ + uchar buf[4], *mbuf; + int nmbuf, n, nn; + Wsysmsg m; + + /* + * Move the protocol off stdin/stdout so that + * any inadvertent prints don't screw things up. + */ + dup(0, 3); + dup(1, 4); + close(0); + close(1); + open("/dev/null", OREAD); + open("/dev/null", OWRITE); + +//trace = 1; + fmtinstall('W', drawfcallfmt); + + ARGBEGIN{ + case 'D': + chatty++; + break; + default: + usage(); + }ARGEND + + /* + * Ignore arguments. They're only for good ps -a listings. + */ + + 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); + } + threadexitsall(0); +} + +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"); + /* fprint(2, "mouse unstall\n"); */ + 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: + setlabel(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. + */ +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); + if(n > nmbuf){ + free(mbuf); + mbuf = malloc(n); + if(mbuf == nil) + sysfatal("out of memory"); + nmbuf = n; + } + convW2M(m, mbuf, n); + write(4, mbuf, n); +} + +/* + * 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(); + m = &mouse.m[mouse.wi]; + m->xy.x = x; + m->xy.y = y; + m->buttons = b; + m->msec = ms; + mouse.wi++; + 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 +keystroke(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(); +} -- cgit v1.2.3