#include "paint.h" typedef struct Aux { int fd; ImgHdr hdr; } Aux; static int init(Widget *w) { Aux *aux; if((aux = malloc(sizeof(Aux))) == nil) { fprint(2, "pipette: alloc aux: %r\n"); return -1; } ((Canvas *)w->aux)->tool.aux = aux; if((aux->fd = open("/dev/screen", OREAD)) < 0) { fprint(2, "pipette: open /dev/screen: %r\n"); return -1; } if(readimghdr(aux->fd, &aux->hdr) < 0) { fprint(2, "pipette: read screen header: %r\n"); close(aux->fd); return -1; } if(aux->hdr.compressed) { fprint(2, "pipette: screen image is compressed\n"); close(aux->fd); return -1; } return 0; } static int mouse(Widget *w, Mousectl *mctl) { Aux *aux; int nc; vlong o; uchar p[4]; int n; ulong c; char chanstr[9]; Brush *brush, old; int b0; if((mctl->buttons & 7) == 0) return 0; aux = ((Canvas *)w->aux)->tool.aux; nc = chantodepth(aux->hdr.chan) / 8; brush = getbrush(mctl->buttons); old = *brush; b0 = mctl->buttons; do { o = 5*12 + (mctl->xy.y * Dx(aux->hdr.r) + mctl->xy.x) * nc; if((n = pread(aux->fd, p, nc, o)) < nc) { if(n >= 0) werrstr("short read: %d/%d", n, nc); fprint(2, "pipette: read %P: %r\n", mctl->xy); goto err; } switch(aux->hdr.chan) { case XRGB32: c = p[2]<<24 | p[1]<<16 | p[0]<<8 | 0xFF; break; default: fprint(2, "pipette: unexpected screen chan: %.*s\n", sizeof chanstr, chantostr(chanstr, aux->hdr.chan) ); goto err; } brush->c = c; brushwidget->sync(brushwidget); brushwidget->redraw(brushwidget, RDall); setcolorpickercolor(colorpickerwidget, c); colorpickerwidget->redraw(colorpickerwidget, RDinc); readmouse(mctl); } while((mctl->buttons & 7) == b0); if(mctl->buttons == 0) return 0; *brush = old; brushwidget->sync(brushwidget); brushwidget->redraw(brushwidget, RDall); while(mctl->buttons) readmouse(mctl); return 0; err: while(mctl->buttons) readmouse(mctl); return -1; } static void cleanup(Widget *w) { Aux *aux; aux = ((Canvas *)w->aux)->tool.aux; close(aux->fd); free(((Canvas *)w->aux)->tool.aux); } CanvasTool pipette = { mouse, init, cleanup, }; /* image(6) /sys/src/cmd/rio/xfid.c:/Qscreen */