1 /* Copyright (c) 2006 Russ Cox */
4 #include <sys/select.h>
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);
22 _displayconnect(Display *d)
26 fmtinstall('W', drawfcallfmt);
27 fmtinstall('H', encodefmt);
40 /* execl("strace", "strace", "-o", "drawsrv.out", "drawsrv", nil); */
42 * The argv0 has no meaning to devdraw.
43 * Pass it along only so that the various
44 * devdraws in psu -a can be distinguished.
46 execl("devdraw", "devdraw", argv0, nil);
47 sysfatal("exec devdraw: %r");
55 _displaymux(Display *d)
57 if((d->mux = mallocz(sizeof(*d->mux), 1)) == nil)
62 d->mux->send = drawsend;
63 d->mux->recv = drawrecv;
64 d->mux->nbrecv = drawnbrecv;
65 d->mux->gettag = drawgettag;
66 d->mux->settag = drawsettag;
74 drawsend(Mux *mux, void *vmsg)
83 return write(d->srvfd, msg, n);
87 _drawrecv(Mux *mux, int nb)
94 if(nb && !canreadfd(d->srvfd))
96 if((n=readn(d->srvfd, buf, 4)) != 4)
101 fprint(2, "out of memory allocating %d in drawrecv\n", n);
105 if(readn(d->srvfd, p+4, n-4) != n-4)
113 return _drawrecv(mux, 0);
119 return _drawrecv(mux, 1);
123 drawgettag(Mux *mux, void *vmsg)
133 drawsettag(Mux *mux, void *vmsg, uint tag)
144 displayrpc(Display *d, Wsysmsg *tx, Wsysmsg *rx, void **freep)
157 fprint(2, "<- %W\n", tx);
158 nn = convW2M(tx, tpkt, n);
161 werrstr("drawclient: sizeW2M convW2M mismatch");
166 * This is the only point where we might reschedule.
167 * Muxrpc might need to acquire d->mux->lk, which could
168 * be held by some other proc (e.g., the one reading from
169 * the keyboard via Trdkbd messages). If we need to wait
170 * for the lock, don't let other threads from this proc
171 * run. This keeps up the appearance that writes to /dev/draw
172 * don't cause rescheduling. If you *do* allow rescheduling
173 * here, then flushimage(display, 1) happening in two different
174 * threads in the same proc can cause a buffer of commands
175 * to be written out twice, leading to interesting results
178 * Threadpin and threadunpin were added to the thread library
179 * to solve exactly this problem. Be careful! They are dangerous.
181 * _pin and _unpin are aliases for threadpin and threadunpin
182 * in a threaded program and are no-ops in unthreaded programs.
185 rpkt = muxrpc(d->mux, tpkt);
189 werrstr("muxrpc: %r");
192 GET((uchar*)rpkt, n);
193 nn = convM2W(rpkt, n, rx);
196 werrstr("drawclient: convM2W packet size mismatch %d %d %.*H", n, nn, n, rpkt);
201 fprint(2, "-> %W\n", rx);
202 if(rx->type == Rerror){
203 werrstr("%s", rx->error);
207 if(rx->type != tx->type+1){
208 werrstr("packet type mismatch -- tx %d rx %d",
221 _displayinit(Display *d, char *label, char *winsize)
227 tx.winsize = winsize;
228 return displayrpc(d, &tx, &rx, nil);
232 _displayrdmouse(Display *d, Mouse *m, int *resized)
237 if(displayrpc(d, &tx, &rx, nil) < 0)
240 *resized = rx.resized;
245 _displayrdkbd(Display *d, Rune *r)
250 if(displayrpc(d, &tx, &rx, nil) < 0)
257 _displaymoveto(Display *d, Point p)
263 return displayrpc(d, &tx, &rx, nil);
267 _displaycursor(Display *d, Cursor *c)
273 memset(&tx.cursor, 0, sizeof tx.cursor);
279 return displayrpc(d, &tx, &rx, nil);
283 _displaybouncemouse(Display *d, Mouse *m)
287 tx.type = Tbouncemouse;
289 return displayrpc(d, &tx, &rx, nil);
293 _displaylabel(Display *d, char *label)
299 return displayrpc(d, &tx, &rx, nil);
303 _displayrdsnarf(Display *d)
310 if(displayrpc(d, &tx, &rx, &p) < 0)
312 s = strdup(rx.snarf);
318 _displaywrsnarf(Display *d, char *snarf)
324 return displayrpc(d, &tx, &rx, nil);
328 _displayrddraw(Display *d, void *v, int n)
335 if(displayrpc(d, &tx, &rx, &p) < 0)
337 memmove(v, rx.data, rx.count);
343 _displaywrdraw(Display *d, void *v, int n)
350 if(displayrpc(d, &tx, &rx, nil) < 0)
356 _displaytop(Display *d)
361 return displayrpc(d, &tx, &rx, nil);
365 _displayresize(Display *d, Rectangle r)
371 return displayrpc(d, &tx, &rx, nil);
387 if(select(fd+1, &rs, &ws, &xs, &tv) < 0)
389 if(FD_ISSET(fd, &rs) || FD_ISSET(fd, &xs))