Blob
1 /* Copyright (c) 2006 Russ Cox */3 #include <u.h>4 #include <sys/select.h>5 #include <libc.h>6 #include <draw.h>7 #include <mouse.h>8 #include <cursor.h>9 #include <drawfcall.h>10 #include <mux.h>12 int chattydrawclient;14 static int drawgettag(Mux *mux, void *vmsg);15 static void* drawrecv(Mux *mux);16 static void* drawnbrecv(Mux *mux);17 static int drawsend(Mux *mux, void *vmsg);18 static int drawsettag(Mux *mux, void *vmsg, uint tag);19 static int canreadfd(int);21 int22 _displayconnect(Display *d)23 {24 int pid, p[2];26 fmtinstall('W', drawfcallfmt);27 fmtinstall('H', encodefmt);29 if(pipe(p) < 0)30 return -1;31 if((pid=fork()) < 0){32 close(p[0]);33 close(p[1]);34 return -1;35 }36 if(pid == 0){37 close(p[0]);38 dup(p[1], 0);39 dup(p[1], 1);40 /* execl("strace", "strace", "-o", "drawsrv.out", "drawsrv", nil); */41 execl("devdraw", "devdraw", nil);42 sysfatal("exec devdraw: %r");43 }44 close(p[1]);45 d->srvfd = p[0];46 return 0;47 }49 int50 _displaymux(Display *d)51 {52 if((d->mux = mallocz(sizeof(*d->mux), 1)) == nil)53 return -1;55 d->mux->mintag = 1;56 d->mux->maxtag = 255;57 d->mux->send = drawsend;58 d->mux->recv = drawrecv;59 d->mux->nbrecv = drawnbrecv;60 d->mux->gettag = drawgettag;61 d->mux->settag = drawsettag;62 d->mux->aux = d;63 muxinit(d->mux);65 return 0;66 }68 static int69 drawsend(Mux *mux, void *vmsg)70 {71 int n;72 uchar *msg;73 Display *d;75 msg = vmsg;76 GET(msg, n);77 d = mux->aux;78 return write(d->srvfd, msg, n);79 }81 static void*82 _drawrecv(Mux *mux, int nb)83 {84 int n;85 uchar buf[4], *p;86 Display *d;88 d = mux->aux;89 if(nb && !canreadfd(d->srvfd))90 return nil;91 if((n=readn(d->srvfd, buf, 4)) != 4)92 return nil;93 GET(buf, n);94 p = malloc(n);95 if(p == nil){96 fprint(2, "out of memory allocating %d in drawrecv\n", n);97 return nil;98 }99 memmove(p, buf, 4);100 if(readn(d->srvfd, p+4, n-4) != n-4)101 return nil;102 return p;103 }105 static void*106 drawrecv(Mux *mux)107 {108 return _drawrecv(mux, 0);109 }111 static void*112 drawnbrecv(Mux *mux)113 {114 return _drawrecv(mux, 1);115 }117 static int118 drawgettag(Mux *mux, void *vmsg)119 {120 USED(mux);121 uchar *msg;123 msg = vmsg;124 return msg[4];125 }127 static int128 drawsettag(Mux *mux, void *vmsg, uint tag)129 {130 USED(mux);131 uchar *msg;133 msg = vmsg;134 msg[4] = tag;135 return 0;136 }138 static int139 displayrpc(Display *d, Wsysmsg *tx, Wsysmsg *rx, void **freep)140 {141 int n, nn;142 void *tpkt, *rpkt;144 n = sizeW2M(tx);145 tpkt = malloc(n);146 if(freep)147 *freep = nil;148 if(tpkt == nil)149 return -1;150 tx->tag = 0;151 if(chattydrawclient)152 fprint(2, "<- %W\n", tx);153 nn = convW2M(tx, tpkt, n);154 if(nn != n){155 free(tpkt);156 werrstr("drawclient: sizeW2M convW2M mismatch");157 fprint(2, "%r\n");158 return -1;159 }160 rpkt = muxrpc(d->mux, tpkt);161 free(tpkt);162 if(rpkt == nil){163 werrstr("muxrpc: %r");164 return -1;165 }166 GET((uchar*)rpkt, n);167 nn = convM2W(rpkt, n, rx);168 if(nn != n){169 free(rpkt);170 werrstr("drawclient: convM2W packet size mismatch %d %d %.*H", n, nn, n, rpkt);171 fprint(2, "%r\n");172 return -1;173 }174 if(chattydrawclient)175 fprint(2, "-> %W\n", rx);176 if(rx->type == Rerror){177 werrstr("%s", rx->error);178 free(rpkt);179 return -1;180 }181 if(rx->type != tx->type+1){182 werrstr("packet type mismatch -- tx %d rx %d",183 tx->type, rx->type);184 free(rpkt);185 return -1;186 }187 if(freep)188 *freep = rpkt;189 else190 free(rpkt);191 return 0;192 }194 int195 _displayinit(Display *d, char *label, char *winsize)196 {197 Wsysmsg tx, rx;199 tx.type = Tinit;200 tx.label = label;201 tx.winsize = winsize;202 return displayrpc(d, &tx, &rx, nil);203 }205 int206 _displayrdmouse(Display *d, Mouse *m, int *resized)207 {208 Wsysmsg tx, rx;210 tx.type = Trdmouse;211 if(displayrpc(d, &tx, &rx, nil) < 0)212 return -1;213 *m = rx.mouse;214 *resized = rx.resized;215 return 0;216 }218 int219 _displayrdkbd(Display *d, Rune *r)220 {221 Wsysmsg tx, rx;223 tx.type = Trdkbd;224 if(displayrpc(d, &tx, &rx, nil) < 0)225 return -1;226 *r = rx.rune;227 return 0;228 }230 int231 _displaymoveto(Display *d, Point p)232 {233 Wsysmsg tx, rx;235 tx.type = Tmoveto;236 tx.mouse.xy = p;237 return displayrpc(d, &tx, &rx, nil);238 }240 int241 _displaycursor(Display *d, Cursor *c)242 {243 Wsysmsg tx, rx;245 tx.type = Tcursor;246 if(c == nil){247 memset(&tx.cursor, 0, sizeof tx.cursor);248 tx.arrowcursor = 1;249 }else{250 tx.arrowcursor = 0;251 tx.cursor = *c;252 }253 return displayrpc(d, &tx, &rx, nil);254 }256 int257 _displaybouncemouse(Display *d, Mouse *m)258 {259 Wsysmsg tx, rx;261 tx.type = Tbouncemouse;262 tx.mouse = *m;263 return displayrpc(d, &tx, &rx, nil);264 }266 int267 _displaylabel(Display *d, char *label)268 {269 Wsysmsg tx, rx;271 tx.type = Tlabel;272 tx.label = label;273 return displayrpc(d, &tx, &rx, nil);274 }276 char*277 _displayrdsnarf(Display *d)278 {279 void *p;280 char *s;281 Wsysmsg tx, rx;283 tx.type = Trdsnarf;284 if(displayrpc(d, &tx, &rx, &p) < 0)285 return nil;286 s = strdup(rx.snarf);287 free(p);288 return s;289 }291 int292 _displaywrsnarf(Display *d, char *snarf)293 {294 Wsysmsg tx, rx;296 tx.type = Twrsnarf;297 tx.snarf = snarf;298 return displayrpc(d, &tx, &rx, nil);299 }301 int302 _displayrddraw(Display *d, void *v, int n)303 {304 void *p;305 Wsysmsg tx, rx;307 tx.type = Trddraw;308 tx.count = n;309 if(displayrpc(d, &tx, &rx, &p) < 0)310 return -1;311 memmove(v, rx.data, rx.count);312 free(p);313 return rx.count;314 }316 int317 _displaywrdraw(Display *d, void *v, int n)318 {319 Wsysmsg tx, rx;321 tx.type = Twrdraw;322 tx.count = n;323 tx.data = v;324 if(displayrpc(d, &tx, &rx, nil) < 0)325 return -1;326 return rx.count;327 }329 int330 _displaytop(Display *d)331 {332 Wsysmsg tx, rx;334 tx.type = Ttop;335 return displayrpc(d, &tx, &rx, nil);336 }338 int339 _displayresize(Display *d, Rectangle r)340 {341 Wsysmsg tx, rx;343 tx.type = Tresize;344 tx.rect = r;345 return displayrpc(d, &tx, &rx, nil);346 }348 static int349 canreadfd(int fd)350 {351 fd_set rs, ws, xs;352 struct timeval tv;354 FD_ZERO(&rs);355 FD_ZERO(&ws);356 FD_ZERO(&xs);357 FD_SET(fd, &rs);358 FD_SET(fd, &xs);359 tv.tv_sec = 0;360 tv.tv_usec = 0;361 if(select(fd+1, &rs, &ws, &xs, &tv) < 0)362 return 0;363 if(FD_ISSET(fd, &rs) || FD_ISSET(fd, &xs))364 return 1;365 return 0;366 }