Charles.Forsyth20060303a828770d19 years agoHistory
304 lines · 4.9 KB · C
RawDownload
/* * mouse or stylus */ #include	"dat.h"#include	"fns.h"#include	"../port/error.h" #include <draw.h>#include <memdraw.h>#include <cursor.h> #define	cursorenable()#define	cursordisable() enum{	Qdir,	Qpointer,	Qcursor}; typedef struct Pointer Pointer; struct Pointer {	int	x;	int	y;	int	b;	ulong	msec;}; static struct{	Pointer	v;	int	modify;	int	lastb;	Rendez	r;	Ref	ref;	QLock	q;} mouse; staticDirtab pointertab[]={	".",			{Qdir, 0, QTDIR},	0,	0555,	"pointer",		{Qpointer},	0,	0666,	"cursor",		{Qcursor},		0,	0222,}; enum {	Nevent = 16	/* enough for some */}; static struct {	int	rd;	int	wr;	Pointer	clicks[Nevent];	Rendez r;	int	full;	int	put;	int	get;} ptrq; /* * called by any source of pointer data */voidmousetrack(int b, int x, int y, int isdelta){	int lastb;	ulong msec;	Pointer e; 	if(isdelta){		x += mouse.v.x;		y += mouse.v.y;	}	msec = osmillisec();	if(0 && b && (mouse.v.b ^ b)&0x1f){		if(msec - mouse.v.msec < 300 && mouse.lastb == b		   && abs(mouse.v.x - x) < 12 && abs(mouse.v.y - y) < 12)			b |= 1<<8;		mouse.lastb = b & 0x1f;		mouse.v.msec = msec;	}	if((b&(1<<8))==0 && x == mouse.v.x && y == mouse.v.y && mouse.v.b == b)		return;	lastb = mouse.v.b;	mouse.v.x = x;	mouse.v.y = y;	mouse.v.b = b;	mouse.v.msec = msec;	if(!ptrq.full && lastb != b){		e = mouse.v;		ptrq.clicks[ptrq.wr] = e;		if(++ptrq.wr >= Nevent)			ptrq.wr = 0;		if(ptrq.wr == ptrq.rd)			ptrq.full = 1;	}	mouse.modify = 1;	ptrq.put++;	Wakeup(&ptrq.r);/*	drawactive(1);	*//*	setpointer(x, y); */} static intptrqnotempty(void *x){	USED(x);	return ptrq.full || ptrq.put != ptrq.get;} static Pointermouseconsume(void){	Pointer e; 	Sleep(&ptrq.r, ptrqnotempty, 0);	ptrq.full = 0;	ptrq.get = ptrq.put;	if(ptrq.rd != ptrq.wr){		e = ptrq.clicks[ptrq.rd];		if(++ptrq.rd >= Nevent)			ptrq.rd = 0;	}else		e = mouse.v;	return e;} Pointmousexy(void){	return Pt(mouse.v.x, mouse.v.y);}  static Chan*pointerattach(char* spec){	return devattach('m', spec);} static Walkqid*pointerwalk(Chan *c, Chan *nc, char **name, int nname){	Walkqid *wq; 	wq = devwalk(c, nc, name, nname, pointertab, nelem(pointertab), devgen);	if(wq != nil && wq->clone != c && wq->clone != nil && (ulong)c->qid.path == Qpointer)		incref(&mouse.ref);	/* can this happen? */	return wq;} static intpointerstat(Chan* c, uchar *db, int n){	return devstat(c, db, n, pointertab, nelem(pointertab), devgen);} static Chan*pointeropen(Chan* c, int omode){	c = devopen(c, omode, pointertab, nelem(pointertab), devgen);	if((ulong)c->qid.path == Qpointer){		if(waserror()){			c->flag &= ~COPEN;			nexterror();		}		if(!canqlock(&mouse.q))			error(Einuse);		if(incref(&mouse.ref) != 1){			qunlock(&mouse.q);			error(Einuse);		}		cursorenable();		qunlock(&mouse.q);		poperror();	}	return c;} static voidpointerclose(Chan* c){	if((c->flag & COPEN) == 0)		return;	switch((ulong)c->qid.path){	case Qpointer:		qlock(&mouse.q);		if(decref(&mouse.ref) == 0){			cursordisable();		}		qunlock(&mouse.q);		break;	}} static longpointerread(Chan* c, void* a, long n, vlong off){	Pointer mt;	char buf[1+4*12+1];	int l; 	USED(&off);	switch((ulong)c->qid.path){	case Qdir:		return devdirread(c, a, n, pointertab, nelem(pointertab), devgen);	case Qpointer:		qlock(&mouse.q);		if(waserror()) {			qunlock(&mouse.q);			nexterror();		}		mt = mouseconsume();		poperror();		qunlock(&mouse.q);		l = snprint(buf, sizeof(buf), "m%11d %11d %11d %11lud ", mt.x, mt.y, mt.b, mt.msec);		if(l < n)			n = l;		memmove(a, buf, n);		break;	default:		n=0;		break;	}	return n;} static longpointerwrite(Chan* c, void* va, long n, vlong off){	char *a = va;	char buf[128];	int b, x, y;	Drawcursor cur; 	USED(&off);	switch((ulong)c->qid.path){	case Qpointer:		if(n > sizeof buf-1)			n = sizeof buf -1;		memmove(buf, va, n);		buf[n] = 0;		x = strtoul(buf+1, &a, 0);		if(*a == 0)			error(Eshort);		y = strtoul(a, &a, 0);		if(*a != 0)			b = strtoul(a, 0, 0);		else			b = mouse.v.b;		/*mousetrack(b, x, y, msec);*/		setpointer(x, y);		USED(b);		break;	case Qcursor:		/* TO DO: perhaps interpret data as an Image */		/*		 *  hotx[4] hoty[4] dx[4] dy[4] clr[dx/8 * dy/2] set[dx/8 * dy/2]		 *  dx must be a multiple of 8; dy must be a multiple of 2.		 */		if(n == 0){			cur.data = nil;			drawcursor(&cur);			break;		}		if(n < 8)			error(Eshort);		cur.hotx = BGLONG((uchar*)va+0*4);		cur.hoty = BGLONG((uchar*)va+1*4);		cur.minx = 0;		cur.miny = 0;		cur.maxx = BGLONG((uchar*)va+2*4);		cur.maxy = BGLONG((uchar*)va+3*4);		if(cur.maxx%8 != 0 || cur.maxy%2 != 0 || n-4*4 != (cur.maxx/8 * cur.maxy))			error(Ebadarg);		cur.data = (uchar*)va + 4*4;		drawcursor(&cur);		break;	default:		error(Ebadusefd);	}	return n;} Dev pointerdevtab = {	'm',	"pointer", 	devinit,	pointerattach,	pointerwalk,	pointerstat,	pointeropen,	devcreate,	pointerclose,	pointerread,	devbread,	pointerwrite,	devbwrite,	devremove,	devwstat,};