Пример #1
0
void
readmouse(Vnc *v)
{
    int cursorfd, len, n;
    char buf[10*EventSize], *start, *end;
    uchar curs[2*4+2*2*16];
    Cursor *cs;
    Mouse m;

    cs = &dotcursor;

    snprint(buf, sizeof buf, "%s/cursor", display->devdir);
    if((cursorfd = open(buf, OWRITE)) < 0)
        sysfatal("open %s: %r", buf);

    BPLONG(curs+0*4, cs->offset.x);
    BPLONG(curs+1*4, cs->offset.y);
    memmove(curs+2*4, cs->clr, 2*2*16);
    write(cursorfd, curs, sizeof curs);

    resize(v, 1);
    requestupdate(vnc, 0);
    start = end = buf;
    len = 0;
    for(;;) {
        if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0)
            sysfatal("read mouse failed");

        len += n;
        end += n;
        while(len >= EventSize) {
            if(*start == 'm') {
                m.xy.x = atoi(start+1);
                m.xy.y = atoi(start+1+12);
                m.buttons = atoi(start+1+2*12) & 0x1F;
                m.xy = subpt(m.xy, screen->r.min);
                if(ptinrect(m.xy, Rpt(ZP, v->dim))) {
                    mouseevent(v, m);
                    /* send wheel button *release* */
                    if ((m.buttons & 0x7) != m.buttons) {
                        m.buttons &= 0x7;
                        mouseevent(v, m);
                    }
                }
            } else
                eresized();

            start += EventSize;
            len -= EventSize;
        }
        if(start - buf > sizeof(buf) - EventSize) {
            memmove(buf, start, len);
            start = buf;
            end = start+len;
        }
    }
}
Пример #2
0
int
unloadimage(Image *i, Rectangle r, uchar *data, int ndata)
{
    int bpl, n, chunk, dx, dy;
    uchar *a, *start;
    Display *d;

    if(!rectinrect(r, i->r)) {
        werrstr("unloadimage: bad rectangle");
        return -1;
    }
    bpl = bytesperline(r, i->depth);
    if(ndata < bpl*Dy(r)) {
        werrstr("unloadimage: buffer too small");
        return -1;
    }
    start = data;
    d = i->display;
    chunk = d->bufsize;
    flushimage(d, 0);	/* make sure subsequent flush is for us only */
    while(r.min.y < r.max.y) {
        dx = Dx(r);
        dy = chunk/bpl;
        if(dy <= 0) {
            dy = 1;
            dx = ((chunk*dx)/bpl) & ~7;
            n = bytesperline(Rect(r.min.x, r.min.y, r.min.x+dx, r.min.y+dy), i->depth);
            if(unloadimage(i, Rect(r.min.x+dx, r.min.y, r.max.x, r.min.y+dy), data+n, bpl-n) < 0)
                return -1;
        } else {
            if(dy > Dy(r))
                dy = Dy(r);
            n = bpl*dy;
        }
        a = bufimage(d, 1+4+4*4);
        if(a == nil) {
            werrstr("unloadimage: %r");
            return -1;
        }
        a[0] = 'r';
        BPLONG(a+1, i->id);
        BPLONG(a+5, r.min.x);
        BPLONG(a+9, r.min.y);
        BPLONG(a+13, r.min.x+dx);
        BPLONG(a+17, r.min.y+dy);
        if(flushimage(d, 0) < 0)
            return -1;
        if(read(d->fd, data, n) < 0)
            return -1;
        data += bpl*dy;
        r.min.y += dy;
    }
    return data - start;
}
Пример #3
0
void
esetcursor(Cursor *c)
{
	uchar curs[2*4+2*2*16];

	if(c == 0)
		write(cursorfd, curs, 0);
	else{
		BPLONG(curs+0*4, c->offset.x);
		BPLONG(curs+1*4, c->offset.y);
		memmove(curs+2*4, c->clr, 2*2*16);
		write(cursorfd, curs, sizeof curs);
	}
}
Пример #4
0
void
setcursor(Mousectl *mc, Cursor *c)
{
	char curs[2*4+2*2*16];

	if(c == nil)
		write(mc->cfd, curs, 0);
	else{
		BPLONG(curs+0*4, c->offset.x);
		BPLONG(curs+1*4, c->offset.y);
		memmove(curs+2*4, c->clr, 2*2*16);
		write(mc->cfd, curs, sizeof curs);
	}
}
Пример #5
0
int
loadimage(Image *i, Rectangle r, uchar *data, int ndata)
{
	long dy;
	int n, bpl;
	uchar *a;
	int chunk;

	chunk = i->display->bufsize - 64;

	if(!rectinrect(r, i->r)){
		werrstr("loadimage: bad rectangle");
		return -1;
	}
	bpl = bytesperline(r, i->depth);
	n = bpl*Dy(r);
	if(n > ndata){
		werrstr("loadimage: insufficient data");
		return -1;
	}
	ndata = 0;
	while(r.max.y > r.min.y){
		dy = r.max.y - r.min.y;
		if(dy*bpl > chunk)
			dy = chunk/bpl;
		if(dy <= 0){
			werrstr("loadimage: image too wide for buffer");
			return -1;
		}
		n = dy*bpl;
		a = bufimage(i->display, 21+n);
		if(a == nil){
			werrstr("bufimage failed");
			return -1;
		}
		a[0] = 'y';
		BPLONG(a+1, i->id);
		BPLONG(a+5, r.min.x);
		BPLONG(a+9, r.min.y);
		BPLONG(a+13, r.max.x);
		BPLONG(a+17, r.min.y+dy);
		memmove(a+21, data, n);
		ndata += n;
		data += n;
		r.min.y += dy;
	}
	if(flushimage(i->display, 0) < 0)
		return -1;
	return ndata;
}
Пример #6
0
int
unloadimage(Image *i, Rectangle r, uchar *data, int ndata)
{
	int bpl, n, ntot, dy;
	uchar *a;
	Display *d;

	if(!rectinrect(r, i->r)){
		werrstr("unloadimage: bad rectangle");
		return -1;
	}
	bpl = bytesperline(r, i->depth);
	if(ndata < bpl*Dy(r)){
		werrstr("unloadimage: buffer too small");
		return -1;
	}

	d = i->display;
	flushimage(d, 0);	/* make sure subsequent flush is for us only */
	ntot = 0;
	while(r.min.y < r.max.y){
		a = bufimage(d, 1+4+4*4);
		if(a == 0){
			werrstr("unloadimage: %r");
			return -1;
		}
		dy = 8000/bpl;
		if(dy <= 0){
			werrstr("unloadimage: image too wide");
			return -1;
		}
		if(dy > Dy(r))
			dy = Dy(r);
		a[0] = 'r';
		BPLONG(a+1, i->id);
		BPLONG(a+5, r.min.x);
		BPLONG(a+9, r.min.y);
		BPLONG(a+13, r.max.x);
		BPLONG(a+17, r.min.y+dy);
		if(flushimage(d, 0) < 0)
			return -1;
		n = read(d->fd, data+ntot, ndata-ntot);
		if(n < 0)
			return n;
		ntot += n;
		r.min.y += dy;
	}
	return ntot;
}
Пример #7
0
int
cloadimage(Image *i, Rectangle r, uchar *data, int ndata)
{
	int m, nb, miny, maxy, ncblock;
	uchar *a;

	if(!rectinrect(r, i->r)){
		werrstr("cloadimage: bad rectangle");
		return -1;
	}

	miny = r.min.y;
	m = 0;
	ncblock = _compblocksize(r, i->depth);
	while(miny != r.max.y){
		maxy = atoi((char*)data+0*12);
		nb = atoi((char*)data+1*12);
		if(maxy<=miny || r.max.y<maxy){
			werrstr("creadimage: bad maxy %d", maxy);
			return -1;
		}
		data += 2*12;
		ndata -= 2*12;
		m += 2*12;
		if(nb<=0 || ncblock<nb || nb>ndata){
			werrstr("creadimage: bad count %d", nb);
			return -1;
		}
		a = bufimage(i->display, 21+nb);
		if(a == nil)
			return -1;
		a[0] = 'Y';
		BPLONG(a+1, i->id);
		BPLONG(a+5, r.min.x);
		BPLONG(a+9, miny);
		BPLONG(a+13, r.max.x);
		BPLONG(a+17, maxy);
		memmove(a+21, data, nb);
		miny = maxy;
		data += nb;
		ndata += nb;
		m += nb;
	}
	return m;
}
Пример #8
0
int
flushimage(Display *d, int visible)
{
	if(d == nil)
		return 0;
	if(visible){
		*d->bufp++ = 'v';	/* five bytes always reserved for this */
		if(d->_isnewdisplay){
			BPLONG(d->bufp, d->screenimage->id);
			d->bufp += 4;
		}
	}
	return doflush(d);
}
Пример #9
0
int
nameimage(Image *i, char *name, int in)
{
	uchar *a;
	int n;

	n = strlen(name);
	a = bufimage(i->display, 1+4+1+1+n);
	if(a == 0)
		return 0;
	a[0] = 'N';
	BPLONG(a+1, i->id);
	a[5] = in;
	a[6] = n;
	memmove(a+7, name, n);
	if(flushimage(i->display, 0) < 0)
		return 0;
	return 1;
}
Пример #10
0
static
void
dopoly(int cmd, Image *dst, Point *pp, int np, int end0, int end1, int radius, Image *src, Point *sp, Drawop op)
{
	uchar *a, *t, *u;
	int i, ox, oy;

	if(np == 0)
		return;
	t = malloc(np*2*3);
	if(t == nil)
		return;
	u = t;
	ox = oy = 0;
	for(i=0; i<np; i++){
		u = addcoord(u, ox, pp[i].x);
		ox = pp[i].x;
		u = addcoord(u, oy, pp[i].y);
		oy = pp[i].y;
	}

	_setdrawop(dst->display, op);

	a = bufimage(dst->display, 1+4+2+4+4+4+4+2*4+(u-t));
	if(a == 0){
		free(t);
		fprint(2, "image poly: %r\n");
		return;
	}
	a[0] = cmd;
	BPLONG(a+1, dst->id);
	BPSHORT(a+5, np-1);
	BPLONG(a+7, end0);
	BPLONG(a+11, end1);
	BPLONG(a+15, radius);
	BPLONG(a+19, src->id);
	BPLONG(a+23, sp->x);
	BPLONG(a+27, sp->y);
	memmove(a+31, t, u-t);
	free(t);
}
Пример #11
0
int
_freeimage1(Image *i)
{
	uchar *a;
	Display *d;
	Image *w;

	if(i == 0)
		return 0;
	/* make sure no refresh events occur on this if we block in the write */
	d = i->display;
	/* flush pending data so we don't get error deleting the image */
	flushimage(d, 0);
	a = bufimage(d, 1+4);
	if(a == 0)
		return -1;
	a[0] = 'f';
	BPLONG(a+1, i->id);
	if(i->screen){
		w = d->windows;
		if(w == i)
			d->windows = i->next;
		else
			while(w){
				if(w->next == i){
					w->next = i->next;
					break;
				}
				w = w->next;
			}
	}
	if(flushimage(d, i->screen!=0) < 0)
		return -1;

	return 0;
}
Пример #12
0
Point
_string(Image *dst, Point pt, Image *src, Point sp, Font *f, char *s, Rune *r, int len, Rectangle clipr, Image *bg, Point bgp, Drawop op)
{
	int m, n, wid, max;
	ushort cbuf[Max], *c, *ec;
	uchar *b;
	char *subfontname;
	char **sptr;
	Rune **rptr;
	Font *def;
	Subfont *sf;

	if(s == nil){
		s = "";
		sptr = nil;
	}else
		sptr = &s;
	if(r == nil){
		r = (Rune*) L"";
		rptr = nil;
	}else
		rptr = &r;
	sf = nil;
	while((*s || *r) && len > 0){
		max = Max;
		if(len < max)
			max = len;
		n = cachechars(f, sptr, rptr, cbuf, max, &wid, &subfontname);
		if(n > 0){
			_setdrawop(dst->display, op);

			m = 47+2*n;
			if(bg)
				m += 4+2*4;
			b = bufimage(dst->display, m);
			if(b == 0){
				fprint(2, "string: %r\n");
				break;
			}
			if(bg)
				b[0] = 'x';
			else
				b[0] = 's';
			BPLONG(b+1, dst->id);
			BPLONG(b+5, src->id);
			BPLONG(b+9, f->cacheimage->id);
			BPLONG(b+13, pt.x);
			BPLONG(b+17, pt.y+f->ascent);
			BPLONG(b+21, clipr.min.x);
			BPLONG(b+25, clipr.min.y);
			BPLONG(b+29, clipr.max.x);
			BPLONG(b+33, clipr.max.y);
			BPLONG(b+37, sp.x);
			BPLONG(b+41, sp.y);
			BPSHORT(b+45, n);
			b += 47;
			if(bg){
				BPLONG(b, bg->id);
				BPLONG(b+4, bgp.x);
				BPLONG(b+8, bgp.y);
				b += 12;
			}
			ec = &cbuf[n];
			for(c=cbuf; c<ec; c++, b+=2)
				BPSHORT(b, *c);
			pt.x += wid;
			bgp.x += wid;
			agefont(f);
			len -= n;
		}
		if(subfontname){
			freesubfont(sf);
			if((sf=_getsubfont(f->display, subfontname)) == 0){
				def = f->display ? f->display->defaultfont : nil;
				if(def && f!=def)
					f = def;
				else
					break;
			}
			/* 
			 * must not free sf until cachechars has found it in the cache
			 * and picked up its own reference.
			 */
		}
	}
	return pt;
}
Пример #13
0
static
void
doellipse(int cmd, Image *dst, Point *c, int xr, int yr, int thick, Image *src, Point *sp, int alpha, int phi, Drawop op)
{
    uchar *a;

    _setdrawop(dst->display, op);

    a = bufimage(dst->display, 1+4+4+2*4+4+4+4+2*4+2*4);
    if(a == 0) {
        fprint(2, "image ellipse: %r\n");
        return;
    }
    a[0] = cmd;
    BPLONG(a+1, dst->id);
    BPLONG(a+5, src->id);
    BPLONG(a+9, c->x);
    BPLONG(a+13, c->y);
    BPLONG(a+17, xr);
    BPLONG(a+21, yr);
    BPLONG(a+25, thick);
    BPLONG(a+29, sp->x);
    BPLONG(a+33, sp->y);
    BPLONG(a+37, alpha);
    BPLONG(a+41, phi);
}
Пример #14
0
static void
draw1(Image *dst, Rectangle *r, Image *src, Point *p0, Image *mask, Point *p1, Drawop op)
{
	uchar *a;

	_setdrawop(dst->display, op);

	a = bufimage(dst->display, 1+4+4+4+4*4+2*4+2*4);
	if(a == nil)
		return;
	if(src == nil)
		src = dst->display->black;
	if(mask == nil)
		mask = dst->display->opaque;
	a[0] = 'd';
	BPLONG(a+1, dst->id);
	BPLONG(a+5, src->id);
	BPLONG(a+9, mask->id);
	BPLONG(a+13, r->min.x);
	BPLONG(a+17, r->min.y);
	BPLONG(a+21, r->max.x);
	BPLONG(a+25, r->max.y);
	BPLONG(a+29, p0->x);
	BPLONG(a+33, p0->y);
	BPLONG(a+37, p1->x);
	BPLONG(a+41, p1->y);
}
Пример #15
0
Image*
namedimage(Display *d, char *name)
{
	uchar *a;
	char *err, buf[12*12+1];
	Image *i;
	int id, n;
	ulong chan;

	err = 0;
	i = 0;

	n = strlen(name);
	if(n >= 256){
		err = "name too long";
    Error:
		if(err)
			werrstr("namedimage: %s", err);
		else
			werrstr("namedimage: %r");
		if(i)
			free(i);
		return 0;
	}
	/* flush pending data so we don't get error allocating the image */
	flushimage(d, 0);
	a = bufimage(d, 1+4+1+n);
	if(a == 0)
		goto Error;
	d->imageid++;
	id = d->imageid;
	a[0] = 'n';
	BPLONG(a+1, id);
	a[5] = n;
	memmove(a+6, name, n);
	if(flushimage(d, 0) < 0)
		goto Error;

	if(pread(d->ctlfd, buf, sizeof buf, 0) < 12*12)
		goto Error;
	buf[12*12] = '\0';

	i = malloc(sizeof(Image));
	if(i == nil){
	Error1:
		a = bufimage(d, 1+4);
		if(a){
			a[0] = 'f';
			BPLONG(a+1, id);
			flushimage(d, 0);
		}
		goto Error;
	}
	i->display = d;
	i->id = id;
	if((chan=strtochan(buf+2*12))==0){
		werrstr("bad channel '%.12s' from devdraw", buf+2*12);
		goto Error1;
	}
	i->chan = chan;
	i->depth = chantodepth(chan);
	i->repl = atoi(buf+3*12);
	i->r.min.x = atoi(buf+4*12);
	i->r.min.y = atoi(buf+5*12);
	i->r.max.x = atoi(buf+6*12);
	i->r.max.y = atoi(buf+7*12);
	i->clipr.min.x = atoi(buf+8*12);
	i->clipr.min.y = atoi(buf+9*12);
	i->clipr.max.x = atoi(buf+10*12);
	i->clipr.max.y = atoi(buf+11*12);
	i->screen = 0;
	i->next = 0;
	return i;
}
Пример #16
0
void
lineop(Image *dst, Point p0, Point p1, int end0, int end1, int radius, Image *src, Point sp, Drawop op)
{
	uchar *a;

	_setdrawop(dst->display, op);

	a = bufimage(dst->display, 1+4+2*4+2*4+4+4+4+4+2*4);
	if(a == 0){
		fprint(2, "image line: %r\n");
		return;
	}
	a[0] = 'L';
	BPLONG(a+1, dst->id);
	BPLONG(a+5, p0.x);
	BPLONG(a+9, p0.y);
	BPLONG(a+13, p1.x);
	BPLONG(a+17, p1.y);
	BPLONG(a+21, end0);
	BPLONG(a+25, end1);
	BPLONG(a+29, radius);
	BPLONG(a+33, src->id);
	BPLONG(a+37, sp.x);
	BPLONG(a+41, sp.y);
}
Пример #17
0
Image*
_allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong val, int screenid, int refresh)
{
	uchar *a;
	char *err;
	Image *i;
	Rectangle clipr;
	int id;
	int depth;

	err = 0;
	i = 0;

	if(chan == 0){
		werrstr("bad channel descriptor");
		return nil;
	}

	depth = chantodepth(chan);
	if(depth == 0){
		err = "bad channel descriptor";
    Error:
		if(err)
			werrstr("allocimage: %s", err);
		else
			werrstr("allocimage: %r");
		free(i);
		return 0;
	}

	/* flush pending data so we don't get error allocating the image */
	flushimage(d, 0);
	a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);
	if(a == 0)
		goto Error;
	d->imageid++;
	id = d->imageid;
	a[0] = 'b';
	BPLONG(a+1, id);
	BPLONG(a+5, screenid);
	a[9] = refresh;
	BPLONG(a+10, chan);
	a[14] = repl;
	BPLONG(a+15, r.min.x);
	BPLONG(a+19, r.min.y);
	BPLONG(a+23, r.max.x);
	BPLONG(a+27, r.max.y);
	if(repl)
		/* huge but not infinite, so various offsets will leave it huge, not overflow */
		clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);
	else
		clipr = r;
	BPLONG(a+31, clipr.min.x);
	BPLONG(a+35, clipr.min.y);
	BPLONG(a+39, clipr.max.x);
	BPLONG(a+43, clipr.max.y);
	BPLONG(a+47, val);
	if(flushimage(d, 0) < 0)
		goto Error;

	if(ai)
		i = ai;
	else{
		i = malloc(sizeof(Image));
		if(i == nil){
			a = bufimage(d, 1+4);
			if(a){
				a[0] = 'f';
				BPLONG(a+1, id);
				flushimage(d, 0);
			}
			goto Error;
		}
	}
	i->display = d;
	i->id = id;
	i->depth = depth;
	i->chan = chan;
	i->r = r;
	i->clipr = clipr;
	i->repl = repl;
	i->screen = 0;
	i->next = 0;
	return i;
}
Пример #18
0
static long
mouseread(Chan *c, void *va, long n, vlong off)
{
	char buf[1+4*12+1], *s;
	uchar *p;
	ulong offset = off;
	Mousestate m;
	int b;

	p = va;
	switch((ulong)c->qid.path){
	case Qdir:
		return devdirread(c, va, n, mousedir, nelem(mousedir), mousedevgen);

	case Qcursor:
		if(offset != 0)
			return 0;
		if(n < 2*4+2*2*16)
			error(Eshort);
		n = 2*4+2*2*16;
		lock(&cursor.lk);
		BPLONG(p+0, curs.offset.x);
		BPLONG(p+4, curs.offset.y);
		memmove(p+8, curs.clr, 2*16);
		memmove(p+40, curs.set, 2*16);
		unlock(&cursor.lk);
		return n;

	case Qmouse:
		while(mousechanged(0) == 0)
			sleep(&mouse.r, mousechanged, 0);

		mouse.qfull = 0;
		mousetime = seconds();

		/*
		 * No lock of the indices is necessary here, because ri is only
		 * updated by us, and there is only one mouse reader
		 * at a time.  I suppose that more than one process
		 * could try to read the fd at one time, but such behavior
		 * is degenerate and already violates the calling
		 * conventions for sleep above.
		 */
		if(mouse.ri != mouse.wi) {
			m = mouse.queue[mouse.ri];
			if(++mouse.ri == nelem(mouse.queue))
				mouse.ri = 0;
		} else {
			while(!canlock(&cursor.lk))
				tsleep(&up->sleep, return0, 0, TK2MS(1));

			m = mouse.mstate;
			unlock(&cursor.lk);
		}

		b = buttonmap[m.buttons&7];
		/* put buttons 4 and 5 back in */
		b |= m.buttons & (3<<3);
		if (scrollswap){
			if (b == 8)
				b = 16;
			else if (b == 16)
				b = 8;
		}
		sprint(buf, "m%11d %11d %11d %11lud ",
			m.xy.x, m.xy.y,
			b,
			m.msec);
		mouse.lastcounter = m.counter;
		if(n > 1+4*12)
			n = 1+4*12;
		if(mouse.lastresize != mouse.resize){
			mouse.lastresize = mouse.resize;
			buf[0] = 'r';
		}
		memmove(va, buf, n);
		return n;
	
	case Qsnarf:
		if(offset == 0){
			s = getsnarf();
			if(c->aux)
				free(c->aux);
			c->aux = s;
		}
		if(c->aux == nil)
			return 0;
		return readstr(offset, va, n, c->aux);
	}
	return 0;
}