xref: /plan9/sys/src/cmd/vnc/devmouse.c (revision 7b6fd1d25ebab24ad9019c6b743fc531d6ced642)
19a747e4fSDavid du Colombier #include	<u.h>
29a747e4fSDavid du Colombier #include	<libc.h>
39a747e4fSDavid du Colombier #include	"compat.h"
49a747e4fSDavid du Colombier #include	"error.h"
59a747e4fSDavid du Colombier 
69a747e4fSDavid du Colombier #define	Image	IMAGE
79a747e4fSDavid du Colombier #include	<draw.h>
89a747e4fSDavid du Colombier #include	<memdraw.h>
99a747e4fSDavid du Colombier #include	<cursor.h>
109a747e4fSDavid du Colombier #include	"screen.h"
119a747e4fSDavid du Colombier 
129a747e4fSDavid du Colombier typedef struct Mouseinfo	Mouseinfo;
139a747e4fSDavid du Colombier typedef struct Mousestate	Mousestate;
149a747e4fSDavid du Colombier 
159a747e4fSDavid du Colombier struct Mousestate
169a747e4fSDavid du Colombier {
179a747e4fSDavid du Colombier 	Point	xy;			/* mouse.xy */
189a747e4fSDavid du Colombier 	int	buttons;		/* mouse.buttons */
199a747e4fSDavid du Colombier 	ulong	counter;	/* increments every update */
209a747e4fSDavid du Colombier 	ulong	msec;	/* time of last event */
219a747e4fSDavid du Colombier };
229a747e4fSDavid du Colombier 
239a747e4fSDavid du Colombier struct Mouseinfo
249a747e4fSDavid du Colombier {
259a747e4fSDavid du Colombier 	Mousestate;
269a747e4fSDavid du Colombier 	int	dx;
279a747e4fSDavid du Colombier 	int	dy;
289a747e4fSDavid du Colombier 	int	track;		/* dx & dy updated */
299a747e4fSDavid du Colombier 	int	redraw;		/* update cursor on screen */
309a747e4fSDavid du Colombier 	ulong	lastcounter;	/* value when /dev/mouse read */
319a747e4fSDavid du Colombier 	Rendez	r;
329a747e4fSDavid du Colombier 	Ref;
339a747e4fSDavid du Colombier 	QLock;
349a747e4fSDavid du Colombier 	int	open;
359a747e4fSDavid du Colombier 	int	acceleration;
369a747e4fSDavid du Colombier 	int	maxacc;
379a747e4fSDavid du Colombier 	Mousestate 	queue[16];	/* circular buffer of click events */
389a747e4fSDavid du Colombier 	int	ri;	/* read index into queue */
399a747e4fSDavid du Colombier 	int	wi;	/* write index into queue */
409a747e4fSDavid du Colombier 	uchar	qfull;	/* queue is full */
419a747e4fSDavid du Colombier };
429a747e4fSDavid du Colombier 
439a747e4fSDavid du Colombier Mouseinfo	mouse;
449a747e4fSDavid du Colombier Cursorinfo	cursor;
459a747e4fSDavid du Colombier int		mouseshifted;
469a747e4fSDavid du Colombier Cursor		curs;
479a747e4fSDavid du Colombier 
489a747e4fSDavid du Colombier void	Cursortocursor(Cursor*);
499a747e4fSDavid du Colombier int	mousechanged(void*);
509a747e4fSDavid du Colombier static void mouseclock(void);
519a747e4fSDavid du Colombier 
529a747e4fSDavid du Colombier enum{
539a747e4fSDavid du Colombier 	Qdir,
549a747e4fSDavid du Colombier 	Qcursor,
559a747e4fSDavid du Colombier 	Qmouse,
569a747e4fSDavid du Colombier };
579a747e4fSDavid du Colombier 
589a747e4fSDavid du Colombier static Dirtab mousedir[]={
599a747e4fSDavid du Colombier 	".",	{Qdir, 0, QTDIR},	0,			DMDIR|0555,
609a747e4fSDavid du Colombier 	"cursor",	{Qcursor},	0,			0666,
619a747e4fSDavid du Colombier 	"mouse",	{Qmouse},	0,			0666,
629a747e4fSDavid du Colombier };
639a747e4fSDavid du Colombier 
649a747e4fSDavid du Colombier static uchar buttonmap[8] = {
659a747e4fSDavid du Colombier 	0, 1, 2, 3, 4, 5, 6, 7,
669a747e4fSDavid du Colombier };
679a747e4fSDavid du Colombier static int mouseswap;
689a747e4fSDavid du Colombier 
699a747e4fSDavid du Colombier extern	Memimage*	gscreen;
70*7b6fd1d2SDavid du Colombier extern	void mousewarpnote(Point);
719a747e4fSDavid du Colombier 
729a747e4fSDavid du Colombier static void
mousereset(void)739a747e4fSDavid du Colombier mousereset(void)
749a747e4fSDavid du Colombier {
759a747e4fSDavid du Colombier 	curs = arrow;
769a747e4fSDavid du Colombier 	Cursortocursor(&arrow);
779a747e4fSDavid du Colombier }
789a747e4fSDavid du Colombier 
799a747e4fSDavid du Colombier static void
mouseinit(void)809a747e4fSDavid du Colombier mouseinit(void)
819a747e4fSDavid du Colombier {
829a747e4fSDavid du Colombier 	cursoron(1);
839a747e4fSDavid du Colombier }
849a747e4fSDavid du Colombier 
859a747e4fSDavid du Colombier static Chan*
mouseattach(char * spec)869a747e4fSDavid du Colombier mouseattach(char *spec)
879a747e4fSDavid du Colombier {
889a747e4fSDavid du Colombier 	return devattach('m', spec);
899a747e4fSDavid du Colombier }
909a747e4fSDavid du Colombier 
919a747e4fSDavid du Colombier static Walkqid*
mousewalk(Chan * c,Chan * nc,char ** name,int nname)929a747e4fSDavid du Colombier mousewalk(Chan *c, Chan *nc, char **name, int nname)
939a747e4fSDavid du Colombier {
949a747e4fSDavid du Colombier 	Walkqid *wq;
959a747e4fSDavid du Colombier 
969a747e4fSDavid du Colombier 	wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
979a747e4fSDavid du Colombier 	if(wq != nil && wq->clone != c && (wq->clone->qid.type&QTDIR)==0)
989a747e4fSDavid du Colombier 		incref(&mouse);
999a747e4fSDavid du Colombier 	return wq;
1009a747e4fSDavid du Colombier }
1019a747e4fSDavid du Colombier 
1029a747e4fSDavid du Colombier static int
mousestat(Chan * c,uchar * db,int n)1039a747e4fSDavid du Colombier mousestat(Chan *c, uchar *db, int n)
1049a747e4fSDavid du Colombier {
1059a747e4fSDavid du Colombier 	return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
1069a747e4fSDavid du Colombier }
1079a747e4fSDavid du Colombier 
1089a747e4fSDavid du Colombier static Chan*
mouseopen(Chan * c,int omode)1099a747e4fSDavid du Colombier mouseopen(Chan *c, int omode)
1109a747e4fSDavid du Colombier {
1119a747e4fSDavid du Colombier 	switch((ulong)c->qid.path){
1129a747e4fSDavid du Colombier 	case Qdir:
1139a747e4fSDavid du Colombier 		if(omode != OREAD)
1149a747e4fSDavid du Colombier 			error(Eperm);
1159a747e4fSDavid du Colombier 		break;
1169a747e4fSDavid du Colombier 	case Qmouse:
1179a747e4fSDavid du Colombier 		lock(&mouse);
1189a747e4fSDavid du Colombier 		if(mouse.open){
1199a747e4fSDavid du Colombier 			unlock(&mouse);
1209a747e4fSDavid du Colombier 			error(Einuse);
1219a747e4fSDavid du Colombier 		}
1229a747e4fSDavid du Colombier 		mouse.open = 1;
1239a747e4fSDavid du Colombier 		mouse.ref++;
1249a747e4fSDavid du Colombier 		unlock(&mouse);
1259a747e4fSDavid du Colombier 		break;
1269a747e4fSDavid du Colombier 	default:
1279a747e4fSDavid du Colombier 		incref(&mouse);
1289a747e4fSDavid du Colombier 	}
1299a747e4fSDavid du Colombier 	c->mode = openmode(omode);
1309a747e4fSDavid du Colombier 	c->flag |= COPEN;
1319a747e4fSDavid du Colombier 	c->offset = 0;
1329a747e4fSDavid du Colombier 	return c;
1339a747e4fSDavid du Colombier }
1349a747e4fSDavid du Colombier 
1359a747e4fSDavid du Colombier static void
mousecreate(Chan *,char *,int,ulong)1369a747e4fSDavid du Colombier mousecreate(Chan*, char*, int, ulong)
1379a747e4fSDavid du Colombier {
1389a747e4fSDavid du Colombier 	error(Eperm);
1399a747e4fSDavid du Colombier }
1409a747e4fSDavid du Colombier 
1419a747e4fSDavid du Colombier static void
mouseclose(Chan * c)1429a747e4fSDavid du Colombier mouseclose(Chan *c)
1439a747e4fSDavid du Colombier {
1449a747e4fSDavid du Colombier 	if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
1459a747e4fSDavid du Colombier 		lock(&mouse);
1469a747e4fSDavid du Colombier 		if(c->qid.path == Qmouse)
1479a747e4fSDavid du Colombier 			mouse.open = 0;
1489a747e4fSDavid du Colombier 		if(--mouse.ref == 0){
1499a747e4fSDavid du Colombier 			cursoroff(1);
1509a747e4fSDavid du Colombier 			curs = arrow;
1519a747e4fSDavid du Colombier 			Cursortocursor(&arrow);
1529a747e4fSDavid du Colombier 			cursoron(1);
1539a747e4fSDavid du Colombier 		}
1549a747e4fSDavid du Colombier 		unlock(&mouse);
1559a747e4fSDavid du Colombier 	}
1569a747e4fSDavid du Colombier }
1579a747e4fSDavid du Colombier 
1589a747e4fSDavid du Colombier 
1599a747e4fSDavid du Colombier static long
mouseread(Chan * c,void * va,long n,vlong off)1609a747e4fSDavid du Colombier mouseread(Chan *c, void *va, long n, vlong off)
1619a747e4fSDavid du Colombier {
1629a747e4fSDavid du Colombier 	char buf[4*12+1];
1639a747e4fSDavid du Colombier 	uchar *p;
1649a747e4fSDavid du Colombier 	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
1659a747e4fSDavid du Colombier 	ulong offset = off;
1669a747e4fSDavid du Colombier 	Mousestate m;
1679a747e4fSDavid du Colombier 	int b;
1689a747e4fSDavid du Colombier 
1699a747e4fSDavid du Colombier 	p = va;
1709a747e4fSDavid du Colombier 	switch((ulong)c->qid.path){
1719a747e4fSDavid du Colombier 	case Qdir:
1729a747e4fSDavid du Colombier 		return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
1739a747e4fSDavid du Colombier 
1749a747e4fSDavid du Colombier 	case Qcursor:
1759a747e4fSDavid du Colombier 		if(offset != 0)
1769a747e4fSDavid du Colombier 			return 0;
1779a747e4fSDavid du Colombier 		if(n < 2*4+2*2*16)
1789a747e4fSDavid du Colombier 			error(Eshort);
1799a747e4fSDavid du Colombier 		n = 2*4+2*2*16;
1809a747e4fSDavid du Colombier 		lock(&cursor);
1819a747e4fSDavid du Colombier 		BPLONG(p+0, curs.offset.x);
1829a747e4fSDavid du Colombier 		BPLONG(p+4, curs.offset.y);
1839a747e4fSDavid du Colombier 		memmove(p+8, curs.clr, 2*16);
1849a747e4fSDavid du Colombier 		memmove(p+40, curs.set, 2*16);
1859a747e4fSDavid du Colombier 		unlock(&cursor);
1869a747e4fSDavid du Colombier 		return n;
1879a747e4fSDavid du Colombier 
1889a747e4fSDavid du Colombier 	case Qmouse:
1899a747e4fSDavid du Colombier 		while(mousechanged(0) == 0)
1909a747e4fSDavid du Colombier 			rendsleep(&mouse.r, mousechanged, 0);
1919a747e4fSDavid du Colombier 
1929a747e4fSDavid du Colombier 		mouse.qfull = 0;
1939a747e4fSDavid du Colombier 
1949a747e4fSDavid du Colombier 		/*
1959a747e4fSDavid du Colombier 		 * No lock of the indicies is necessary here, because ri is only
1969a747e4fSDavid du Colombier 		 * updated by us, and there is only one mouse reader
1979a747e4fSDavid du Colombier 		 * at a time.  I suppose that more than one process
1989a747e4fSDavid du Colombier 		 * could try to read the fd at one time, but such behavior
1999a747e4fSDavid du Colombier 		 * is degenerate and already violates the calling
2009a747e4fSDavid du Colombier 		 * conventions for sleep above.
2019a747e4fSDavid du Colombier 		 */
2029a747e4fSDavid du Colombier 		if(mouse.ri != mouse.wi){
2039a747e4fSDavid du Colombier 			m = mouse.queue[mouse.ri];
2049a747e4fSDavid du Colombier 			if(++mouse.ri == nelem(mouse.queue))
2059a747e4fSDavid du Colombier 				mouse.ri = 0;
2069a747e4fSDavid du Colombier 		} else {
2079a747e4fSDavid du Colombier 			lock(&cursor);
2089a747e4fSDavid du Colombier 
2099a747e4fSDavid du Colombier 			m = mouse.Mousestate;
2109a747e4fSDavid du Colombier 			unlock(&cursor);
2119a747e4fSDavid du Colombier 		}
2129a747e4fSDavid du Colombier 
2139a747e4fSDavid du Colombier 		b = buttonmap[m.buttons&7];
2149a747e4fSDavid du Colombier 		/* put buttons 4 and 5 back in */
2159a747e4fSDavid du Colombier 		b |= m.buttons & (3<<3);
2169a747e4fSDavid du Colombier 		sprint(buf, "m%11d %11d %11d %11lud",
2179a747e4fSDavid du Colombier 			m.xy.x, m.xy.y,
2189a747e4fSDavid du Colombier 			b,
2199a747e4fSDavid du Colombier 			m.msec);
2209a747e4fSDavid du Colombier 		mouse.lastcounter = m.counter;
2219a747e4fSDavid du Colombier 		if(n > 1+4*12)
2229a747e4fSDavid du Colombier 			n = 1+4*12;
2239a747e4fSDavid du Colombier 		memmove(va, buf, n);
2249a747e4fSDavid du Colombier 		return n;
2259a747e4fSDavid du Colombier 	}
2269a747e4fSDavid du Colombier 	return 0;
2279a747e4fSDavid du Colombier }
2289a747e4fSDavid du Colombier 
2299a747e4fSDavid du Colombier static void
setbuttonmap(char * map)2309a747e4fSDavid du Colombier setbuttonmap(char* map)
2319a747e4fSDavid du Colombier {
2329a747e4fSDavid du Colombier 	int i, x, one, two, three;
2339a747e4fSDavid du Colombier 
2349a747e4fSDavid du Colombier 	one = two = three = 0;
2359a747e4fSDavid du Colombier 	for(i = 0; i < 3; i++){
2369a747e4fSDavid du Colombier 		if(map[i] == 0)
2379a747e4fSDavid du Colombier 			error(Ebadarg);
2389a747e4fSDavid du Colombier 		if(map[i] == '1'){
2399a747e4fSDavid du Colombier 			if(one)
2409a747e4fSDavid du Colombier 				error(Ebadarg);
2419a747e4fSDavid du Colombier 			one = 1<<i;
2429a747e4fSDavid du Colombier 		}
2439a747e4fSDavid du Colombier 		else if(map[i] == '2'){
2449a747e4fSDavid du Colombier 			if(two)
2459a747e4fSDavid du Colombier 				error(Ebadarg);
2469a747e4fSDavid du Colombier 			two = 1<<i;
2479a747e4fSDavid du Colombier 		}
2489a747e4fSDavid du Colombier 		else if(map[i] == '3'){
2499a747e4fSDavid du Colombier 			if(three)
2509a747e4fSDavid du Colombier 				error(Ebadarg);
2519a747e4fSDavid du Colombier 			three = 1<<i;
2529a747e4fSDavid du Colombier 		}
2539a747e4fSDavid du Colombier 		else
2549a747e4fSDavid du Colombier 			error(Ebadarg);
2559a747e4fSDavid du Colombier 	}
2569a747e4fSDavid du Colombier 	if(map[i])
2579a747e4fSDavid du Colombier 		error(Ebadarg);
2589a747e4fSDavid du Colombier 
2599a747e4fSDavid du Colombier 	memset(buttonmap, 0, 8);
2609a747e4fSDavid du Colombier 	for(i = 0; i < 8; i++){
2619a747e4fSDavid du Colombier 		x = 0;
2629a747e4fSDavid du Colombier 		if(i & 1)
2639a747e4fSDavid du Colombier 			x |= one;
2649a747e4fSDavid du Colombier 		if(i & 2)
2659a747e4fSDavid du Colombier 			x |= two;
2669a747e4fSDavid du Colombier 		if(i & 4)
2679a747e4fSDavid du Colombier 			x |= three;
2689a747e4fSDavid du Colombier 		buttonmap[x] = i;
2699a747e4fSDavid du Colombier 	}
2709a747e4fSDavid du Colombier }
2719a747e4fSDavid du Colombier 
2729a747e4fSDavid du Colombier static long
mousewrite(Chan * c,void * va,long n,vlong)2739a747e4fSDavid du Colombier mousewrite(Chan *c, void *va, long n, vlong)
2749a747e4fSDavid du Colombier {
2759a747e4fSDavid du Colombier 	char *p;
2769a747e4fSDavid du Colombier 	Point pt;
2779a747e4fSDavid du Colombier 	char buf[64];
2789a747e4fSDavid du Colombier 
2799a747e4fSDavid du Colombier 	p = va;
2809a747e4fSDavid du Colombier 	switch((ulong)c->qid.path){
2819a747e4fSDavid du Colombier 	case Qdir:
2829a747e4fSDavid du Colombier 		error(Eisdir);
2839a747e4fSDavid du Colombier 
2849a747e4fSDavid du Colombier 	case Qcursor:
2859a747e4fSDavid du Colombier 		cursoroff(1);
2869a747e4fSDavid du Colombier 		if(n < 2*4+2*2*16){
2879a747e4fSDavid du Colombier 			curs = arrow;
2889a747e4fSDavid du Colombier 			Cursortocursor(&arrow);
2899a747e4fSDavid du Colombier 		}else{
2909a747e4fSDavid du Colombier 			n = 2*4+2*2*16;
2919a747e4fSDavid du Colombier 			curs.offset.x = BGLONG(p+0);
2929a747e4fSDavid du Colombier 			curs.offset.y = BGLONG(p+4);
2939a747e4fSDavid du Colombier 			memmove(curs.clr, p+8, 2*16);
2949a747e4fSDavid du Colombier 			memmove(curs.set, p+40, 2*16);
2959a747e4fSDavid du Colombier 			Cursortocursor(&curs);
2969a747e4fSDavid du Colombier 		}
2979a747e4fSDavid du Colombier 		qlock(&mouse);
2989a747e4fSDavid du Colombier 		mouse.redraw = 1;
2999a747e4fSDavid du Colombier 		mouseclock();
3009a747e4fSDavid du Colombier 		qunlock(&mouse);
3019a747e4fSDavid du Colombier 		cursoron(1);
3029a747e4fSDavid du Colombier 		return n;
3039a747e4fSDavid du Colombier 
3049a747e4fSDavid du Colombier 	case Qmouse:
3059a747e4fSDavid du Colombier 		if(n > sizeof buf-1)
3069a747e4fSDavid du Colombier 			n = sizeof buf -1;
3079a747e4fSDavid du Colombier 		memmove(buf, va, n);
3089a747e4fSDavid du Colombier 		buf[n] = 0;
3099a747e4fSDavid du Colombier 		p = 0;
3109a747e4fSDavid du Colombier 		pt.x = strtoul(buf+1, &p, 0);
3119a747e4fSDavid du Colombier 		if(p == 0)
3129a747e4fSDavid du Colombier 			error(Eshort);
3139a747e4fSDavid du Colombier 		pt.y = strtoul(p, 0, 0);
3149a747e4fSDavid du Colombier 		qlock(&mouse);
3159a747e4fSDavid du Colombier 		if(ptinrect(pt, gscreen->r)){
3169a747e4fSDavid du Colombier 			mousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
317d9306527SDavid du Colombier 			mousewarpnote(pt);
3189a747e4fSDavid du Colombier 		}
3199a747e4fSDavid du Colombier 		qunlock(&mouse);
3209a747e4fSDavid du Colombier 		return n;
3219a747e4fSDavid du Colombier 	}
3229a747e4fSDavid du Colombier 
3239a747e4fSDavid du Colombier 	error(Egreg);
3249a747e4fSDavid du Colombier 	return -1;
3259a747e4fSDavid du Colombier }
3269a747e4fSDavid du Colombier 
3279a747e4fSDavid du Colombier Dev mousedevtab = {
3289a747e4fSDavid du Colombier 	'm',
3299a747e4fSDavid du Colombier 	"mouse",
3309a747e4fSDavid du Colombier 
3319a747e4fSDavid du Colombier 	mousereset,
3329a747e4fSDavid du Colombier 	mouseinit,
3339a747e4fSDavid du Colombier 	mouseattach,
3349a747e4fSDavid du Colombier 	mousewalk,
3359a747e4fSDavid du Colombier 	mousestat,
3369a747e4fSDavid du Colombier 	mouseopen,
3379a747e4fSDavid du Colombier 	mousecreate,
3389a747e4fSDavid du Colombier 	mouseclose,
3399a747e4fSDavid du Colombier 	mouseread,
3409a747e4fSDavid du Colombier 	devbread,
3419a747e4fSDavid du Colombier 	mousewrite,
3429a747e4fSDavid du Colombier 	devbwrite,
3439a747e4fSDavid du Colombier 	devremove,
3449a747e4fSDavid du Colombier 	devwstat,
3459a747e4fSDavid du Colombier };
3469a747e4fSDavid du Colombier 
3479a747e4fSDavid du Colombier void
Cursortocursor(Cursor * c)3489a747e4fSDavid du Colombier Cursortocursor(Cursor *c)
3499a747e4fSDavid du Colombier {
3509a747e4fSDavid du Colombier 	lock(&cursor);
3519a747e4fSDavid du Colombier 	memmove(&cursor.Cursor, c, sizeof(Cursor));
3529a747e4fSDavid du Colombier 	setcursor(c);
3539a747e4fSDavid du Colombier 	unlock(&cursor);
3549a747e4fSDavid du Colombier }
3559a747e4fSDavid du Colombier 
3569a747e4fSDavid du Colombier static int
scale(int x)3579a747e4fSDavid du Colombier scale(int x)
3589a747e4fSDavid du Colombier {
3599a747e4fSDavid du Colombier 	int sign = 1;
3609a747e4fSDavid du Colombier 
3619a747e4fSDavid du Colombier 	if(x < 0){
3629a747e4fSDavid du Colombier 		sign = -1;
3639a747e4fSDavid du Colombier 		x = -x;
3649a747e4fSDavid du Colombier 	}
3659a747e4fSDavid du Colombier 	switch(x){
3669a747e4fSDavid du Colombier 	case 0:
3679a747e4fSDavid du Colombier 	case 1:
3689a747e4fSDavid du Colombier 	case 2:
3699a747e4fSDavid du Colombier 	case 3:
3709a747e4fSDavid du Colombier 		break;
3719a747e4fSDavid du Colombier 	case 4:
3729a747e4fSDavid du Colombier 		x = 6 + (mouse.acceleration>>2);
3739a747e4fSDavid du Colombier 		break;
3749a747e4fSDavid du Colombier 	case 5:
3759a747e4fSDavid du Colombier 		x = 9 + (mouse.acceleration>>1);
3769a747e4fSDavid du Colombier 		break;
3779a747e4fSDavid du Colombier 	default:
3789a747e4fSDavid du Colombier 		x *= mouse.maxacc;
3799a747e4fSDavid du Colombier 		break;
3809a747e4fSDavid du Colombier 	}
3819a747e4fSDavid du Colombier 	return sign*x;
3829a747e4fSDavid du Colombier }
3839a747e4fSDavid du Colombier 
3849a747e4fSDavid du Colombier static void
mouseclock(void)3859a747e4fSDavid du Colombier mouseclock(void)
3869a747e4fSDavid du Colombier {
3879a747e4fSDavid du Colombier 	lock(&cursor);
3889a747e4fSDavid du Colombier 	if(mouse.redraw){
3899a747e4fSDavid du Colombier 		mouse.redraw = 0;
3909a747e4fSDavid du Colombier 		cursoroff(0);
3919a747e4fSDavid du Colombier 		mouse.redraw = cursoron(0);
3929a747e4fSDavid du Colombier 	}
3939a747e4fSDavid du Colombier 	unlock(&cursor);
3949a747e4fSDavid du Colombier }
3959a747e4fSDavid du Colombier 
3969a747e4fSDavid du Colombier /*
3979a747e4fSDavid du Colombier  *  called at interrupt level to update the structure and
3989a747e4fSDavid du Colombier  *  awaken any waiting procs.
3999a747e4fSDavid du Colombier  */
4009a747e4fSDavid du Colombier void
mousetrack(int x,int y,int b,int msec)4019a747e4fSDavid du Colombier mousetrack(int x, int y, int b, int msec)
4029a747e4fSDavid du Colombier {
4039a747e4fSDavid du Colombier 	int lastb;
4049a747e4fSDavid du Colombier 
4059a747e4fSDavid du Colombier 	lastb = mouse.buttons;
4069a747e4fSDavid du Colombier 	mouse.xy = Pt(x, y);
4079a747e4fSDavid du Colombier 	mouse.buttons = b;
4089a747e4fSDavid du Colombier 	mouse.redraw = 1;
4099a747e4fSDavid du Colombier 	mouse.counter++;
4109a747e4fSDavid du Colombier 	mouse.msec = msec;
4119a747e4fSDavid du Colombier 
4129a747e4fSDavid du Colombier 	/*
4139a747e4fSDavid du Colombier 	 * if the queue fills, we discard the entire queue and don't
4149a747e4fSDavid du Colombier 	 * queue any more events until a reader polls the mouse.
4159a747e4fSDavid du Colombier 	 */
4169a747e4fSDavid du Colombier 	if(!mouse.qfull && lastb != b){	/* add to ring */
4179a747e4fSDavid du Colombier 		mouse.queue[mouse.wi] = mouse.Mousestate;
4189a747e4fSDavid du Colombier 		if(++mouse.wi == nelem(mouse.queue))
4199a747e4fSDavid du Colombier 			mouse.wi = 0;
4209a747e4fSDavid du Colombier 		if(mouse.wi == mouse.ri)
4219a747e4fSDavid du Colombier 			mouse.qfull = 1;
4229a747e4fSDavid du Colombier 	}
4239a747e4fSDavid du Colombier 	rendwakeup(&mouse.r);
4249a747e4fSDavid du Colombier 	mouseclock();
4259a747e4fSDavid du Colombier }
4269a747e4fSDavid du Colombier 
4279a747e4fSDavid du Colombier int
mousechanged(void *)4289a747e4fSDavid du Colombier mousechanged(void*)
4299a747e4fSDavid du Colombier {
4309a747e4fSDavid du Colombier 	return mouse.lastcounter != mouse.counter;
4319a747e4fSDavid du Colombier }
4329a747e4fSDavid du Colombier 
4339a747e4fSDavid du Colombier Point
mousexy(void)4349a747e4fSDavid du Colombier mousexy(void)
4359a747e4fSDavid du Colombier {
4369a747e4fSDavid du Colombier 	return mouse.xy;
4379a747e4fSDavid du Colombier }
4389a747e4fSDavid du Colombier 
4399a747e4fSDavid du Colombier void
mouseaccelerate(int x)4409a747e4fSDavid du Colombier mouseaccelerate(int x)
4419a747e4fSDavid du Colombier {
4429a747e4fSDavid du Colombier 	mouse.acceleration = x;
4439a747e4fSDavid du Colombier 	if(mouse.acceleration < 3)
4449a747e4fSDavid du Colombier 		mouse.maxacc = 2;
4459a747e4fSDavid du Colombier 	else
4469a747e4fSDavid du Colombier 		mouse.maxacc = mouse.acceleration;
4479a747e4fSDavid du Colombier }
448