Commit Diff


commit - 74dc60da74c62e07f0d63179da9724d705794a6d
commit + 257fb6261eba6026e127e1a42e06b8b2d9c3b722
blob - /dev/null
blob + ae8719a9e618d7e69009d13cd28825f7d9ef795e (mode 644)
--- /dev/null
+++ 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);
+}
+
blob - /dev/null
blob + 09a54f91ef01081f809b06cc6022dfacae277438 (mode 644)
--- /dev/null
+++ src/libdraw/drawfcall.c
@@ -0,0 +1,367 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <mouse.h>
+#include <cursor.h>
+#include <drawfcall.h>
+
+#define PUT(p, x) \
+	(p)[0] = ((x) >> 24)&0xFF, \
+	(p)[1] = ((x) >> 16)&0xFF, \
+	(p)[2] = ((x) >> 8)&0xFF, \
+	(p)[3] = (x)&0xFF
+
+#define GET(p, x) \
+	((x) = (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | ((p)[3])))
+
+#define PUT2(p, x) \
+	(p)[0] = ((x) >> 8)&0xFF, \
+	(p)[1] = (x)&0xFF
+
+#define GET2(p, x) \
+	((x) = (((p)[0] << 8) | ((p)[1])))
+
+static int
+_stringsize(char *s)
+{
+	return 4+strlen(s);
+}
+
+static int
+PUTSTRING(uchar *p, char *s)
+{
+	int n;
+	
+	if(s == nil)
+		s = "";
+	n = strlen(s);
+	PUT(p, n);
+	memmove(p+4, s, n);
+	return n+4;
+}
+
+static int
+GETSTRING(uchar *p, char **s)
+{
+	int n;
+	
+	GET(p, n);
+	memmove(p, p+4, n);
+	*s = (char*)p;
+	p[n] = 0;
+	return n+4;
+}
+	
+uint
+sizeW2M(Wsysmsg *m)
+{
+	switch(m->type){
+	default:
+		return 0;
+	case Trdmouse:
+	case Rbouncemouse:
+	case Rmoveto:
+	case Rcursor:
+	case Trdkbd:
+	case Rlabel:
+	case Rinit:
+	case Trdsnarf:
+	case Rwrsnarf:
+	case Ttop:
+	case Rtop:
+	case Rresize:
+		return 4+1+1;
+	case Rrdmouse:
+		return 4+1+1+4+4+4+4+1;
+	case Tbouncemouse:
+		return 4+1+1+4+4+4;
+	case Tmoveto:
+		return 4+1+1+4+4;
+	case Tcursor:
+		return 4+1+1+4+4+2*16+2*16+1;
+	case Rerror:
+		return 4+1+1+_stringsize(m->error);
+	case Rrdkbd:
+		return 4+1+1+2;
+	case Tlabel:
+		return 4+1+1+_stringsize(m->label);
+	case Tinit:
+		return 4+1+1
+			+_stringsize(m->winsize)
+			+_stringsize(m->label);
+	case Rrdsnarf:
+	case Twrsnarf:
+		return 4+1+1+_stringsize(m->snarf);
+	case Rrddraw:
+	case Twrdraw:
+		return 4+1+1+4+m->count;
+	case Trddraw:
+	case Rwrdraw:
+		return 4+1+1+4;
+	case Tresize:
+		return 4+1+1+4*4;
+	}
+}
+
+uint
+convW2M(Wsysmsg *m, uchar *p, uint n)
+{
+	int nn;
+	
+	nn = sizeW2M(m);
+	if(n < nn || nn == 0 || n < 6)
+		return 0;
+	PUT(p, nn);
+	p[4] = m->tag;
+	p[5] = m->type;
+
+	switch(m->type){
+	default:
+		return 0;
+	case Trdmouse:
+	case Rbouncemouse:
+	case Rmoveto:
+	case Rcursor:
+	case Trdkbd:
+	case Rlabel:
+	case Rinit:
+	case Trdsnarf:
+	case Rwrsnarf:
+	case Ttop:
+	case Rtop:
+	case Rresize:
+		break;
+	case Rerror:
+		PUTSTRING(p+6, m->error);
+		break;
+	case Rrdmouse:
+		PUT(p+6, m->mouse.xy.x);
+		PUT(p+10, m->mouse.xy.y);
+		PUT(p+14, m->mouse.buttons);
+		PUT(p+18, m->mouse.msec);
+		p[19] = m->resized;
+		break;
+	case Tbouncemouse:
+		PUT(p+6, m->mouse.xy.x);
+		PUT(p+10, m->mouse.xy.y);
+		PUT(p+14, m->mouse.buttons);
+		break;
+	case Tmoveto:
+		PUT(p+6, m->mouse.xy.x);
+		PUT(p+10, m->mouse.xy.y);
+		break;
+	case Tcursor:
+		PUT(p+6, m->cursor.offset.x);
+		PUT(p+10, m->cursor.offset.y);
+		memmove(p+14, m->cursor.clr, sizeof m->cursor.clr);
+		memmove(p+46, m->cursor.set, sizeof m->cursor.set);
+		p[78] = m->arrowcursor;
+		break;
+	case Rrdkbd:
+		PUT2(p+6, m->rune);
+		break;
+	case Tlabel:
+		PUTSTRING(p+6, m->label);
+		break;
+	case Tinit:
+		p += 6;
+		p += PUTSTRING(p, m->winsize);
+		p += PUTSTRING(p, m->label);
+		break;
+	case Rrdsnarf:
+	case Twrsnarf:
+		PUTSTRING(p+6, m->snarf);
+		break;
+	case Rrddraw:
+	case Twrdraw:
+		PUT(p+6, m->count);
+		memmove(p+10, m->data, m->count);
+		break;
+	case Trddraw:
+	case Rwrdraw:
+		PUT(p+6, m->count);
+		break;
+	case Tresize:
+		PUT(p+6, m->rect.min.x);
+		PUT(p+10, m->rect.min.y);
+		PUT(p+14, m->rect.max.x);
+		PUT(p+18, m->rect.max.y);
+		break;
+	}		
+	return nn;
+}
+
+uint
+convM2W(uchar *p, uint n, Wsysmsg *m)
+{
+	int nn;
+	
+	if(n < 6)
+		return 0;
+	GET(p, nn);
+	if(nn > n)
+		return 0;
+	m->tag = p[4];
+	m->type = p[5];
+	switch(m->type){
+	default:
+		return 0;
+	case Trdmouse:
+	case Rbouncemouse:
+	case Rmoveto:
+	case Rcursor:
+	case Trdkbd:
+	case Rlabel:
+	case Rinit:
+	case Trdsnarf:
+	case Rwrsnarf:
+	case Ttop:
+	case Rtop:
+	case Rresize:
+		break;
+	case Rerror:
+		GETSTRING(p+6, &m->error);
+		break;
+	case Rrdmouse:
+		GET(p+6, m->mouse.xy.x);
+		GET(p+10, m->mouse.xy.y);
+		GET(p+14, m->mouse.buttons);
+		GET(p+18, m->mouse.msec);
+		m->resized = p[19];
+		break;
+	case Tbouncemouse:
+		GET(p+6, m->mouse.xy.x);
+		GET(p+10, m->mouse.xy.y);
+		GET(p+14, m->mouse.buttons);
+		break;
+	case Tmoveto:
+		GET(p+6, m->mouse.xy.x);
+		GET(p+10, m->mouse.xy.y);
+		break;
+	case Tcursor:
+		GET(p+6, m->cursor.offset.x);
+		GET(p+10, m->cursor.offset.y);
+		memmove(m->cursor.clr, p+14, sizeof m->cursor.clr);
+		memmove(m->cursor.set, p+46, sizeof m->cursor.set);
+		m->arrowcursor = p[78];
+		break;
+	case Rrdkbd:
+		GET2(p+6, m->rune);
+		break;
+	case Tlabel:
+		GETSTRING(p+6, &m->label);
+		break;
+	case Tinit:
+		p += 6;
+		p += GETSTRING(p, &m->winsize);
+		p += GETSTRING(p, &m->label);
+		break;
+	case Rrdsnarf:
+	case Twrsnarf:
+		GETSTRING(p+6, &m->snarf);
+		break;
+	case Rrddraw:
+	case Twrdraw:
+		GET(p+6, m->count);
+		m->data = p+10;
+		break;
+	case Trddraw:
+	case Rwrdraw:
+		GET(p+6, m->count);
+		break;
+	case Tresize:
+		GET(p+6, m->rect.min.x);
+		GET(p+10, m->rect.min.y);
+		GET(p+14, m->rect.max.x);
+		GET(p+18, m->rect.max.y);
+		break;
+	}	
+	return nn;
+}
+
+int
+readwsysmsg(int fd, uchar *buf, uint nbuf)
+{
+	int n;
+
+	if(nbuf < 6)
+		return -1;
+	if(readn(fd, buf, 4) != 4)
+		return -1;
+	GET(buf, n);
+	if(n > nbuf)
+		return -1;
+	if(readn(fd, buf+4, n-4) != n-4)
+		return -1;
+	return n;
+}
+
+int
+drawfcallfmt(Fmt *fmt)
+{
+	Wsysmsg *m;
+	
+	m = va_arg(fmt->args, Wsysmsg*);
+	fmtprint(fmt, "tag=%d ", m->tag);
+	switch(m->type){
+	default:
+		return fmtprint(fmt, "unknown msg %d", m->type);
+	case Rerror:
+		return fmtprint(fmt, "Rerror error='%s'", m->error);
+	case Trdmouse:
+		return fmtprint(fmt, "Trdmouse");
+	case Rrdmouse:
+		return fmtprint(fmt, "Rrdmouse x=%d y=%d buttons=%d msec=%d resized=%d",
+			m->mouse.xy.x, m->mouse.xy.y, 
+			m->mouse.buttons, m->mouse.msec, m->resized);
+	case Tbouncemouse:
+		return fmtprint(fmt, "Tbouncemouse x=%d y=%d buttons=%d",
+			m->mouse.xy.x, m->mouse.xy.y, m->mouse.buttons);
+	case Rbouncemouse:
+		return fmtprint(fmt, "Rbouncemouse");
+	case Tmoveto:
+		return fmtprint(fmt, "Tmoveto x=%d y=%d", m->mouse.xy.x, m->mouse.xy.y);
+	case Rmoveto:
+		return fmtprint(fmt, "Rmoveto");
+	case Tcursor:
+		return fmtprint(fmt, "Tcursor arrow=%d", m->arrowcursor);
+	case Rcursor:
+		return fmtprint(fmt, "Rcursor");
+	case Trdkbd:
+		return fmtprint(fmt, "Trdkbd");
+	case Rrdkbd:
+		return fmtprint(fmt, "Rrdkbd rune=%C", m->rune);
+	case Tlabel:
+		return fmtprint(fmt, "Tlabel label='%s'", m->label);
+	case Rlabel:
+		return fmtprint(fmt, "Rlabel");
+	case Tinit:
+		return fmtprint(fmt, "Tinit label='%s' winsize='%s'", m->label, m->winsize);
+	case Rinit:
+		return fmtprint(fmt, "Rinit");
+	case Trdsnarf:
+		return fmtprint(fmt, "Trdsnarf");
+	case Rrdsnarf:
+		return fmtprint(fmt, "Rrdsnarf snarf='%s'", m->snarf);
+	case Twrsnarf:
+		return fmtprint(fmt, "Twrsnarf snarf='%s'", m->snarf);
+	case Rwrsnarf:
+		return fmtprint(fmt, "Rwrsnarf");
+	case Trddraw:
+		return fmtprint(fmt, "Trddraw %d", m->count);
+	case Rrddraw:
+		return fmtprint(fmt, "Rrddraw %d %.*H", m->count, m->count, m->data);
+	case Twrdraw:
+		return fmtprint(fmt, "Twrdraw %d %.*H", m->count, m->count, m->data);
+	case Rwrdraw:
+		return fmtprint(fmt, "Rwrdraw %d", m->count);
+	case Ttop:
+		return fmtprint(fmt, "Ttop");
+	case Rtop:
+		return fmtprint(fmt, "Rtop");
+	case Tresize:
+		return fmtprint(fmt, "Tresize %R", m->rect);
+	case Rresize:
+		return fmtprint(fmt, "Rresize");
+	}
+}
blob - /dev/null
blob + d5ad4827e015047841c6771ec8036a53a43ee5e9 (mode 644)
--- /dev/null
+++ src/libdraw/snarf.c
@@ -0,0 +1,15 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+void
+putsnarf(char *snarf)
+{
+	_displaywrsnarf(display, snarf);
+}
+
+char*
+getsnarf(void)
+{
+	return _displayrdsnarf(display);
+}
blob - /dev/null
blob + e8136177a0c574f4696660e484fbfafb71b1581e (mode 644)
--- /dev/null
+++ src/libdraw/wsys.c
@@ -0,0 +1,24 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+int _wantfocuschanges;
+
+void
+drawtopwindow(void)
+{
+	_displaytop(display);
+}
+
+int
+drawsetlabel(char *label)
+{
+	return _displaylabel(display, label);
+}
+
+void
+bouncemouse(Mouse *m)
+{
+	_displaybouncemouse(display, m);
+}
+