diff options
Diffstat (limited to 'src/libdraw/drawclient.c')
-rw-r--r-- | src/libdraw/drawclient.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/src/libdraw/drawclient.c b/src/libdraw/drawclient.c new file mode 100644 index 00000000..ae8719a9 --- /dev/null +++ b/src/libdraw/drawclient.c @@ -0,0 +1,336 @@ +/* Copyright (c) 2006 Russ Cox */ + +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <mouse.h> +#include <cursor.h> +#include <drawfcall.h> +#include <mux.h> + +int chattydrawclient; + +static int drawgettag(Mux *mux, void *vmsg); +static void* drawrecv(Mux *mux); +static int drawsend(Mux *mux, void *vmsg); +static int drawsettag(Mux *mux, void *vmsg, uint tag); + +int +_displayconnect(Display *d) +{ + int pid, p[2]; + + fmtinstall('W', drawfcallfmt); + fmtinstall('H', encodefmt); + + if(pipe(p) < 0) + return -1; + if((pid=fork()) < 0){ + close(p[0]); + close(p[1]); + return -1; + } + if(pid == 0){ + close(p[0]); + dup(p[1], 0); + dup(p[1], 1); + /* execl("strace", "strace", "-o", "drawsrv.out", "drawsrv", nil); */ + execl("drawsrv", "drawsrv", nil); + sysfatal("exec drawsrv: %r"); + } + close(p[1]); + d->srvfd = p[0]; + return 0; +} + +int +_displaymux(Display *d) +{ + if((d->mux = mallocz(sizeof(*d->mux), 1)) == nil) + return -1; + + d->mux->mintag = 1; + d->mux->maxtag = 255; + d->mux->send = drawsend; + d->mux->recv = drawrecv; + d->mux->gettag = drawgettag; + d->mux->settag = drawsettag; + d->mux->aux = d; + muxinit(d->mux); + + return 0; +} + +#define GET(p, x) \ + ((x) = (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | ((p)[3]))) + +static int +drawsend(Mux *mux, void *vmsg) +{ + int n; + uchar *msg; + Display *d; + + msg = vmsg; + GET(msg, n); + d = mux->aux; + return write(d->srvfd, msg, n); +} + +static void* +drawrecv(Mux *mux) +{ + int n; + uchar buf[4], *p; + Display *d; + + d = mux->aux; + if((n=readn(d->srvfd, buf, 4)) != 4){ +fprint(2, "readn 4 got %d: %r\n", n); + return nil; + } + GET(buf, n); + p = malloc(n); + if(p == nil){ + fprint(2, "out of memory allocating %d in drawrecv\n", n); + return nil; + } + memmove(p, buf, 4); + if(readn(d->srvfd, p+4, n-4) != n-4){ +fprint(2, "short readn\n"); + return nil; + } + return p; +} + +static int +drawgettag(Mux *mux, void *vmsg) +{ + USED(mux); + uchar *msg; + + msg = vmsg; + return msg[4]; +} + +static int +drawsettag(Mux *mux, void *vmsg, uint tag) +{ + USED(mux); + uchar *msg; + + msg = vmsg; + msg[4] = tag; + return 0; +} + +static int +displayrpc(Display *d, Wsysmsg *tx, Wsysmsg *rx, void **freep) +{ + int n, nn; + void *tpkt, *rpkt; + + n = sizeW2M(tx); + tpkt = malloc(n); + if(freep) + *freep = nil; + if(tpkt == nil) + return -1; + tx->tag = 0; + if(chattydrawclient) + fprint(2, "<- %W\n", tx); + nn = convW2M(tx, tpkt, n); + if(nn != n){ + free(tpkt); + werrstr("drawclient: sizeW2M convW2M mismatch"); + fprint(2, "%r\n"); + return -1; + } + rpkt = muxrpc(d->mux, tpkt); + free(tpkt); + if(rpkt == nil){ + werrstr("muxrpc: %r"); + return -1; + } + GET((uchar*)rpkt, n); + nn = convM2W(rpkt, n, rx); + if(nn != n){ + free(rpkt); + werrstr("drawclient: convM2W packet size mismatch %d %d %.*H", n, nn, n, rpkt); + fprint(2, "%r\n"); + return -1; + } + if(chattydrawclient) + fprint(2, "-> %W\n", rx); + if(rx->type == Rerror){ + werrstr("%s", rx->error); + free(rpkt); + return -1; + } + if(rx->type != tx->type+1){ + werrstr("packet type mismatch -- tx %d rx %d", + tx->type, rx->type); + free(rpkt); + return -1; + } + if(freep) + *freep = rpkt; + else + free(rpkt); + return 0; +} + +int +_displayinit(Display *d, char *label, char *winsize) +{ + Wsysmsg tx, rx; + + tx.type = Tinit; + tx.label = ""; + tx.winsize = ""; + return displayrpc(d, &tx, &rx, nil); +} + +int +_displayrdmouse(Display *d, Mouse *m, int *resized) +{ + Wsysmsg tx, rx; + + tx.type = Trdmouse; + if(displayrpc(d, &tx, &rx, nil) < 0) + return -1; + *m = rx.mouse; + *resized = rx.resized; + return 0; +} + +int +_displayrdkbd(Display *d, Rune *r) +{ + Wsysmsg tx, rx; + + tx.type = Trdkbd; + if(displayrpc(d, &tx, &rx, nil) < 0) + return -1; + *r = rx.rune; + return 0; +} + +int +_displaymoveto(Display *d, Point p) +{ + Wsysmsg tx, rx; + + tx.type = Tmoveto; + tx.mouse.xy = p; + return displayrpc(d, &tx, &rx, nil); +} + +int +_displaycursor(Display *d, Cursor *c) +{ + Wsysmsg tx, rx; + + tx.type = Tcursor; + if(c == nil){ + memset(&tx.cursor, 0, sizeof tx.cursor); + tx.arrowcursor = 1; + }else{ + tx.arrowcursor = 0; + tx.cursor = *c; + } + return displayrpc(d, &tx, &rx, nil); +} + +int +_displaybouncemouse(Display *d, Mouse *m) +{ + Wsysmsg tx, rx; + + tx.type = Tbouncemouse; + tx.mouse = *m; + return displayrpc(d, &tx, &rx, nil); +} + +int +_displaylabel(Display *d, char *label) +{ + Wsysmsg tx, rx; + + tx.type = Tlabel; + tx.label = label; + return displayrpc(d, &tx, &rx, nil); +} + +char* +_displayrdsnarf(Display *d) +{ + void *p; + char *s; + Wsysmsg tx, rx; + + tx.type = Trdsnarf; + if(displayrpc(d, &tx, &rx, &p) < 0) + return nil; + s = strdup(rx.snarf); + free(p); + return s; +} + +int +_displaywrsnarf(Display *d, char *snarf) +{ + Wsysmsg tx, rx; + + tx.type = Twrsnarf; + tx.snarf = snarf; + return displayrpc(d, &tx, &rx, nil); +} + +int +_displayrddraw(Display *d, void *v, int n) +{ + void *p; + Wsysmsg tx, rx; + + tx.type = Trddraw; + tx.count = n; + if(displayrpc(d, &tx, &rx, &p) < 0) + return -1; + memmove(v, rx.data, rx.count); + free(p); + return rx.count; +} + +int +_displaywrdraw(Display *d, void *v, int n) +{ + Wsysmsg tx, rx; + + tx.type = Twrdraw; + tx.count = n; + tx.data = v; + if(displayrpc(d, &tx, &rx, nil) < 0) + return -1; + return rx.count; +} + +int +_displaytop(Display *d) +{ + Wsysmsg tx, rx; + + tx.type = Ttop; + return displayrpc(d, &tx, &rx, nil); +} + +int +_displayresize(Display *d, Rectangle r) +{ + Wsysmsg tx, rx; + + tx.type = Tresize; + tx.rect = r; + return displayrpc(d, &tx, &rx, nil); +} + |