Charles.Forsyth20060303644188019 years agoHistory
279 lines · 4.3 KB · C
RawDownload
/* * mouse or stylus */ #include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h" #include <draw.h>#include <memdraw.h>#include <cursor.h>#include "screen.h" enum{	Qdir,	Qpointer,	Qcursor,}; typedef struct Pointer Pointer; struct Pointer {	int	x;	int	y;	int	b;	ulong	msec;}; static struct{	Pointer;	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.x;		y += mouse.y;	}	msec = TK2MS(MACHP(0)->ticks);	if(b && (mouse.b ^ b)&0x1f){		if(msec - mouse.msec < 300 && mouse.lastb == b		   && abs(mouse.x - x) < 12 && abs(mouse.y - y) < 12)			b |= 1<<8;		mouse.lastb = b & 0x1f;		mouse.msec = msec;	}	if(x == mouse.x && y == mouse.y && mouse.b == b)		return;	lastb = mouse.b;	mouse.x = x;	mouse.y = y;	mouse.b = b;	mouse.msec = msec;	if(!ptrq.full && lastb != b){		e = mouse.Pointer;		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);	/* TO DO: cursor update */} static intptrqnotempty(void*){	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.Pointer;	return e;} Pointmousexy(void){	return Pt(mouse.x, mouse.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){	Pointer mt;	char tmp[128];	int l; 	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 = sprint(tmp, "m%11d %11d %11d %11lud ", mt.x, mt.y, mt.b, mt.msec);		if(l < n)			n = l;		memmove(a, tmp, n);		break;	case Qcursor:		/* TO DO: interpret data written as Image; give to drawcursor() */		break;	default:		n=0;		break;	}	return n;} static longpointerwrite(Chan* c, void* va, long n, vlong){	char *a = va;	char buf[128];	int b, x, y; 	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.b;		mousetrack(b, x, y, 0);		break;	default:		error(Ebadusefd);	}	return n;} Dev pointerdevtab = {	'm',	"pointer", 	devreset,	devinit,	devshutdown,	pointerattach,	pointerwalk,	pointerstat,	pointeropen,	devcreate,	pointerclose,	pointerread,	devbread,	pointerwrite,	devbwrite,	devremove,	devwstat,};