xref: /plan9/sys/src/9/port/devmouse.c (revision 4e3613ab15c331a9ada113286cc0f2a35bc0373d)
17dd7cddfSDavid du Colombier #include	"u.h"
27dd7cddfSDavid du Colombier #include	"../port/lib.h"
37dd7cddfSDavid du Colombier #include	"mem.h"
47dd7cddfSDavid du Colombier #include	"dat.h"
57dd7cddfSDavid du Colombier #include	"fns.h"
67dd7cddfSDavid du Colombier #include	"../port/error.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier #define	Image	IMAGE
97dd7cddfSDavid du Colombier #include	<draw.h>
107dd7cddfSDavid du Colombier #include	<memdraw.h>
117dd7cddfSDavid du Colombier #include	<cursor.h>
127dd7cddfSDavid du Colombier #include	"screen.h"
137dd7cddfSDavid du Colombier 
1415174232SDavid du Colombier enum {
1515174232SDavid du Colombier 	ScrollUp = 0x08,
1615174232SDavid du Colombier 	ScrollDown = 0x10,
1715174232SDavid du Colombier 	ScrollLeft = 0x20,
1815174232SDavid du Colombier 	ScrollRight = 0x40,
1915174232SDavid du Colombier };
2015174232SDavid du Colombier 
217dd7cddfSDavid du Colombier typedef struct Mouseinfo	Mouseinfo;
227dd7cddfSDavid du Colombier typedef struct Mousestate	Mousestate;
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier struct Mousestate
257dd7cddfSDavid du Colombier {
267dd7cddfSDavid du Colombier 	Point	xy;		/* mouse.xy */
277dd7cddfSDavid du Colombier 	int	buttons;	/* mouse.buttons */
287dd7cddfSDavid du Colombier 	ulong	counter;	/* increments every update */
297dd7cddfSDavid du Colombier 	ulong	msec;		/* time of last event */
307dd7cddfSDavid du Colombier };
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier struct Mouseinfo
337dd7cddfSDavid du Colombier {
34e288d156SDavid du Colombier 	Lock;
357dd7cddfSDavid du Colombier 	Mousestate;
367dd7cddfSDavid du Colombier 	int	dx;
377dd7cddfSDavid du Colombier 	int	dy;
387dd7cddfSDavid du Colombier 	int	track;		/* dx & dy updated */
397dd7cddfSDavid du Colombier 	int	redraw;		/* update cursor on screen */
407dd7cddfSDavid du Colombier 	ulong	lastcounter;	/* value when /dev/mouse read */
41e29df7b0SDavid du Colombier 	ulong	lastresize;
42e29df7b0SDavid du Colombier 	ulong	resize;
437dd7cddfSDavid du Colombier 	Rendez	r;
447dd7cddfSDavid du Colombier 	Ref;
457dd7cddfSDavid du Colombier 	QLock;
467dd7cddfSDavid du Colombier 	int	open;
477dd7cddfSDavid du Colombier 	int	acceleration;
487dd7cddfSDavid du Colombier 	int	maxacc;
497dd7cddfSDavid du Colombier 	Mousestate	queue[16];	/* circular buffer of click events */
507dd7cddfSDavid du Colombier 	int	ri;		/* read index into queue */
517dd7cddfSDavid du Colombier 	int	wi;		/* write index into queue */
527dd7cddfSDavid du Colombier 	uchar	qfull;		/* queue is full */
537dd7cddfSDavid du Colombier };
547dd7cddfSDavid du Colombier 
559a747e4fSDavid du Colombier enum
569a747e4fSDavid du Colombier {
579a747e4fSDavid du Colombier 	CMbuttonmap,
5849eeb88aSDavid du Colombier 	CMscrollswap,
599a747e4fSDavid du Colombier 	CMswap,
609a747e4fSDavid du Colombier 	CMwildcard,
619a747e4fSDavid du Colombier };
629a747e4fSDavid du Colombier 
639a747e4fSDavid du Colombier static Cmdtab mousectlmsg[] =
649a747e4fSDavid du Colombier {
659a747e4fSDavid du Colombier 	CMbuttonmap,	"buttonmap",	0,
6649eeb88aSDavid du Colombier 	CMscrollswap,	"scrollswap",	0,
679a747e4fSDavid du Colombier 	CMswap,		"swap",		1,
689a747e4fSDavid du Colombier 	CMwildcard,	"*",		0,
699a747e4fSDavid du Colombier };
709a747e4fSDavid du Colombier 
717dd7cddfSDavid du Colombier Mouseinfo	mouse;
727dd7cddfSDavid du Colombier Cursorinfo	cursor;
737dd7cddfSDavid du Colombier int		mouseshifted;
74e29df7b0SDavid du Colombier int		kbdbuttons;
753039af76SDavid du Colombier void		(*kbdmouse)(int);
767dd7cddfSDavid du Colombier Cursor		curs;
777dd7cddfSDavid du Colombier 
787dd7cddfSDavid du Colombier void	Cursortocursor(Cursor*);
797dd7cddfSDavid du Colombier int	mousechanged(void*);
8026b166b7SDavid du Colombier 
817dd7cddfSDavid du Colombier static void mouseclock(void);
823039af76SDavid du Colombier static void xkbdmouse(int);
837dd7cddfSDavid du Colombier 
847dd7cddfSDavid du Colombier enum{
857dd7cddfSDavid du Colombier 	Qdir,
867dd7cddfSDavid du Colombier 	Qcursor,
877dd7cddfSDavid du Colombier 	Qmouse,
887dd7cddfSDavid du Colombier 	Qmousein,
897dd7cddfSDavid du Colombier 	Qmousectl,
907dd7cddfSDavid du Colombier };
917dd7cddfSDavid du Colombier 
927dd7cddfSDavid du Colombier static Dirtab mousedir[]={
939a747e4fSDavid du Colombier 	".",	{Qdir, 0, QTDIR},	0,			DMDIR|0555,
947dd7cddfSDavid du Colombier 	"cursor",	{Qcursor},	0,			0666,
957dd7cddfSDavid du Colombier 	"mouse",	{Qmouse},	0,			0666,
967dd7cddfSDavid du Colombier 	"mousein",	{Qmousein},	0,			0220,
977dd7cddfSDavid du Colombier 	"mousectl",	{Qmousectl},	0,			0220,
987dd7cddfSDavid du Colombier };
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier static uchar buttonmap[8] = {
1017dd7cddfSDavid du Colombier 	0, 1, 2, 3, 4, 5, 6, 7,
1027dd7cddfSDavid du Colombier };
1037dd7cddfSDavid du Colombier static int mouseswap;
10449eeb88aSDavid du Colombier static int scrollswap;
10526b166b7SDavid du Colombier static ulong mousetime;
10626b166b7SDavid du Colombier 
1077dd7cddfSDavid du Colombier extern Memimage* gscreen;
10826b166b7SDavid du Colombier extern ulong kerndate;
1097dd7cddfSDavid du Colombier 
1107dd7cddfSDavid du Colombier static void
mousereset(void)1117dd7cddfSDavid du Colombier mousereset(void)
1127dd7cddfSDavid du Colombier {
1137dd7cddfSDavid du Colombier 	if(!conf.monitor)
1147dd7cddfSDavid du Colombier 		return;
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier 	curs = arrow;
1177dd7cddfSDavid du Colombier 	Cursortocursor(&arrow);
118d9306527SDavid du Colombier 	/* redraw cursor about 30 times per second */
119d9306527SDavid du Colombier 	addclock0link(mouseclock, 33);
1207dd7cddfSDavid du Colombier }
1217dd7cddfSDavid du Colombier 
1227dd7cddfSDavid du Colombier static void
mousefromkbd(int buttons)1233039af76SDavid du Colombier mousefromkbd(int buttons)
1243039af76SDavid du Colombier {
1253039af76SDavid du Colombier 	kbdbuttons = buttons;
1263039af76SDavid du Colombier 	mousetrack(0, 0, 0, TK2MS(MACHP(0)->ticks));
1273039af76SDavid du Colombier }
1283039af76SDavid du Colombier 
12926b166b7SDavid du Colombier static int
mousedevgen(Chan * c,char * name,Dirtab * tab,int ntab,int i,Dir * dp)13026b166b7SDavid du Colombier mousedevgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
13126b166b7SDavid du Colombier {
13226b166b7SDavid du Colombier 	int rc;
13326b166b7SDavid du Colombier 
13426b166b7SDavid du Colombier 	rc = devgen(c, name, tab, ntab, i, dp);
13526b166b7SDavid du Colombier 	if(rc != -1)
13626b166b7SDavid du Colombier 		dp->atime = mousetime;
13726b166b7SDavid du Colombier 	return rc;
13826b166b7SDavid du Colombier }
13926b166b7SDavid du Colombier 
1403039af76SDavid du Colombier static void
mouseinit(void)1417dd7cddfSDavid du Colombier mouseinit(void)
1427dd7cddfSDavid du Colombier {
1437dd7cddfSDavid du Colombier 	if(!conf.monitor)
1447dd7cddfSDavid du Colombier 		return;
1457dd7cddfSDavid du Colombier 
146fb7f0c93SDavid du Colombier 	curs = arrow;
147fb7f0c93SDavid du Colombier 	Cursortocursor(&arrow);
1487dd7cddfSDavid du Colombier 	cursoron(1);
1493039af76SDavid du Colombier 	kbdmouse = mousefromkbd;
15026b166b7SDavid du Colombier 	mousetime = seconds();
1517dd7cddfSDavid du Colombier }
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier static Chan*
mouseattach(char * spec)1547dd7cddfSDavid du Colombier mouseattach(char *spec)
1557dd7cddfSDavid du Colombier {
1567dd7cddfSDavid du Colombier 	if(!conf.monitor)
1577dd7cddfSDavid du Colombier 		error(Egreg);
1587dd7cddfSDavid du Colombier 	return devattach('m', spec);
1597dd7cddfSDavid du Colombier }
1607dd7cddfSDavid du Colombier 
1619a747e4fSDavid du Colombier static Walkqid*
mousewalk(Chan * c,Chan * nc,char ** name,int nname)1629a747e4fSDavid du Colombier mousewalk(Chan *c, Chan *nc, char **name, int nname)
1637dd7cddfSDavid du Colombier {
1649a747e4fSDavid du Colombier 	Walkqid *wq;
1659a747e4fSDavid du Colombier 
16626b166b7SDavid du Colombier 	/*
16726b166b7SDavid du Colombier 	 * We use devgen() and not mousedevgen() here
16826b166b7SDavid du Colombier 	 * see "Ugly problem" in dev.c/devwalk()
16926b166b7SDavid du Colombier 	 */
1709a747e4fSDavid du Colombier 	wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
171d9306527SDavid du Colombier 	if(wq != nil && wq->clone != c && wq->clone != nil && (wq->clone->qid.type&QTDIR)==0)
1727dd7cddfSDavid du Colombier 		incref(&mouse);
1739a747e4fSDavid du Colombier 	return wq;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier static int
mousestat(Chan * c,uchar * db,int n)1779a747e4fSDavid du Colombier mousestat(Chan *c, uchar *db, int n)
1787dd7cddfSDavid du Colombier {
17926b166b7SDavid du Colombier 	return devstat(c, db, n, mousedir, nelem(mousedir), mousedevgen);
1807dd7cddfSDavid du Colombier }
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier static Chan*
mouseopen(Chan * c,int omode)1837dd7cddfSDavid du Colombier mouseopen(Chan *c, int omode)
1847dd7cddfSDavid du Colombier {
1859a747e4fSDavid du Colombier 	switch((ulong)c->qid.path){
1869a747e4fSDavid du Colombier 	case Qdir:
1877dd7cddfSDavid du Colombier 		if(omode != OREAD)
1887dd7cddfSDavid du Colombier 			error(Eperm);
1897dd7cddfSDavid du Colombier 		break;
1907dd7cddfSDavid du Colombier 	case Qmouse:
1917dd7cddfSDavid du Colombier 		lock(&mouse);
1927dd7cddfSDavid du Colombier 		if(mouse.open){
1937dd7cddfSDavid du Colombier 			unlock(&mouse);
1947dd7cddfSDavid du Colombier 			error(Einuse);
1957dd7cddfSDavid du Colombier 		}
1967dd7cddfSDavid du Colombier 		mouse.open = 1;
1977dd7cddfSDavid du Colombier 		mouse.ref++;
198e29df7b0SDavid du Colombier 		mouse.lastresize = mouse.resize;
1997dd7cddfSDavid du Colombier 		unlock(&mouse);
2007dd7cddfSDavid du Colombier 		break;
2017dd7cddfSDavid du Colombier 	case Qmousein:
202b7b24591SDavid du Colombier 		if(!iseve())
203b7b24591SDavid du Colombier 			error(Eperm);
2047dd7cddfSDavid du Colombier 		break;
2057dd7cddfSDavid du Colombier 	default:
2067dd7cddfSDavid du Colombier 		incref(&mouse);
2077dd7cddfSDavid du Colombier 	}
2087dd7cddfSDavid du Colombier 	c->mode = openmode(omode);
2097dd7cddfSDavid du Colombier 	c->flag |= COPEN;
2107dd7cddfSDavid du Colombier 	c->offset = 0;
2117dd7cddfSDavid du Colombier 	return c;
2127dd7cddfSDavid du Colombier }
2137dd7cddfSDavid du Colombier 
2147dd7cddfSDavid du Colombier static void
mousecreate(Chan *,char *,int,ulong)2157dd7cddfSDavid du Colombier mousecreate(Chan*, char*, int, ulong)
2167dd7cddfSDavid du Colombier {
2177dd7cddfSDavid du Colombier 	if(!conf.monitor)
2187dd7cddfSDavid du Colombier 		error(Egreg);
2197dd7cddfSDavid du Colombier 	error(Eperm);
2207dd7cddfSDavid du Colombier }
2217dd7cddfSDavid du Colombier 
2227dd7cddfSDavid du Colombier static void
mouseclose(Chan * c)2237dd7cddfSDavid du Colombier mouseclose(Chan *c)
2247dd7cddfSDavid du Colombier {
2259a747e4fSDavid du Colombier 	if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
2266f8e93f6SDavid du Colombier 		if(c->qid.path == Qmousein)
2276f8e93f6SDavid du Colombier 			return;
2287dd7cddfSDavid du Colombier 		lock(&mouse);
2297dd7cddfSDavid du Colombier 		if(c->qid.path == Qmouse)
2307dd7cddfSDavid du Colombier 			mouse.open = 0;
2317dd7cddfSDavid du Colombier 		if(--mouse.ref == 0){
2327dd7cddfSDavid du Colombier 			cursoroff(1);
2337dd7cddfSDavid du Colombier 			curs = arrow;
2347dd7cddfSDavid du Colombier 			Cursortocursor(&arrow);
2357dd7cddfSDavid du Colombier 			cursoron(1);
2367dd7cddfSDavid du Colombier 		}
2377dd7cddfSDavid du Colombier 		unlock(&mouse);
2387dd7cddfSDavid du Colombier 	}
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier 
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier static long
mouseread(Chan * c,void * va,long n,vlong off)2437dd7cddfSDavid du Colombier mouseread(Chan *c, void *va, long n, vlong off)
2447dd7cddfSDavid du Colombier {
24549eeb88aSDavid du Colombier 	char buf[1+4*12+1];
2467dd7cddfSDavid du Colombier 	uchar *p;
2477dd7cddfSDavid du Colombier 	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
2487dd7cddfSDavid du Colombier 	ulong offset = off;
2497dd7cddfSDavid du Colombier 	Mousestate m;
25059cc4ca5SDavid du Colombier 	int b;
2517dd7cddfSDavid du Colombier 
2527dd7cddfSDavid du Colombier 	p = va;
2539a747e4fSDavid du Colombier 	switch((ulong)c->qid.path){
2549a747e4fSDavid du Colombier 	case Qdir:
25526b166b7SDavid du Colombier 		return devdirread(c, va, n, mousedir, nelem(mousedir), mousedevgen);
2567dd7cddfSDavid du Colombier 
2577dd7cddfSDavid du Colombier 	case Qcursor:
2587dd7cddfSDavid du Colombier 		if(offset != 0)
2597dd7cddfSDavid du Colombier 			return 0;
2607dd7cddfSDavid du Colombier 		if(n < 2*4+2*2*16)
2617dd7cddfSDavid du Colombier 			error(Eshort);
2627dd7cddfSDavid du Colombier 		n = 2*4+2*2*16;
2637dd7cddfSDavid du Colombier 		lock(&cursor);
2647dd7cddfSDavid du Colombier 		BPLONG(p+0, curs.offset.x);
2657dd7cddfSDavid du Colombier 		BPLONG(p+4, curs.offset.y);
2667dd7cddfSDavid du Colombier 		memmove(p+8, curs.clr, 2*16);
2677dd7cddfSDavid du Colombier 		memmove(p+40, curs.set, 2*16);
2687dd7cddfSDavid du Colombier 		unlock(&cursor);
2697dd7cddfSDavid du Colombier 		return n;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier 	case Qmouse:
2727dd7cddfSDavid du Colombier 		while(mousechanged(0) == 0)
2737dd7cddfSDavid du Colombier 			sleep(&mouse.r, mousechanged, 0);
2747dd7cddfSDavid du Colombier 
2757dd7cddfSDavid du Colombier 		mouse.qfull = 0;
27626b166b7SDavid du Colombier 		mousetime = seconds();
2777dd7cddfSDavid du Colombier 
2787dd7cddfSDavid du Colombier 		/*
27926b166b7SDavid du Colombier 		 * No lock of the indices is necessary here, because ri is only
2807dd7cddfSDavid du Colombier 		 * updated by us, and there is only one mouse reader
2817dd7cddfSDavid du Colombier 		 * at a time.  I suppose that more than one process
2827dd7cddfSDavid du Colombier 		 * could try to read the fd at one time, but such behavior
2837dd7cddfSDavid du Colombier 		 * is degenerate and already violates the calling
2847dd7cddfSDavid du Colombier 		 * conventions for sleep above.
2857dd7cddfSDavid du Colombier 		 */
2867dd7cddfSDavid du Colombier 		if(mouse.ri != mouse.wi) {
2877dd7cddfSDavid du Colombier 			m = mouse.queue[mouse.ri];
2887dd7cddfSDavid du Colombier 			if(++mouse.ri == nelem(mouse.queue))
2897dd7cddfSDavid du Colombier 				mouse.ri = 0;
2907dd7cddfSDavid du Colombier 		} else {
2917dd7cddfSDavid du Colombier 			while(!canlock(&cursor))
2927dd7cddfSDavid du Colombier 				tsleep(&up->sleep, return0, 0, TK2MS(1));
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier 			m = mouse.Mousestate;
2957dd7cddfSDavid du Colombier 			unlock(&cursor);
2967dd7cddfSDavid du Colombier 		}
2977dd7cddfSDavid du Colombier 
29859cc4ca5SDavid du Colombier 		b = buttonmap[m.buttons&7];
29959cc4ca5SDavid du Colombier 		/* put buttons 4 and 5 back in */
30059cc4ca5SDavid du Colombier 		b |= m.buttons & (3<<3);
30149eeb88aSDavid du Colombier 		if (scrollswap)
30249eeb88aSDavid du Colombier 			if (b == 8)
30349eeb88aSDavid du Colombier 				b = 16;
30449eeb88aSDavid du Colombier 			else if (b == 16)
30549eeb88aSDavid du Colombier 				b = 8;
306*4e3613abSDavid du Colombier 		snprint(buf, sizeof buf, "m%11d %11d %11d %11lud ",
3077dd7cddfSDavid du Colombier 			m.xy.x, m.xy.y,
30859cc4ca5SDavid du Colombier 			b,
3097dd7cddfSDavid du Colombier 			m.msec);
3107dd7cddfSDavid du Colombier 		mouse.lastcounter = m.counter;
3117dd7cddfSDavid du Colombier 		if(n > 1+4*12)
3127dd7cddfSDavid du Colombier 			n = 1+4*12;
313e29df7b0SDavid du Colombier 		if(mouse.lastresize != mouse.resize){
314e29df7b0SDavid du Colombier 			mouse.lastresize = mouse.resize;
315e29df7b0SDavid du Colombier 			buf[0] = 'r';
316e29df7b0SDavid du Colombier 		}
3177dd7cddfSDavid du Colombier 		memmove(va, buf, n);
3187dd7cddfSDavid du Colombier 		return n;
3197dd7cddfSDavid du Colombier 	}
3207dd7cddfSDavid du Colombier 	return 0;
3217dd7cddfSDavid du Colombier }
3227dd7cddfSDavid du Colombier 
3237dd7cddfSDavid du Colombier static void
setbuttonmap(char * map)3247dd7cddfSDavid du Colombier setbuttonmap(char* map)
3257dd7cddfSDavid du Colombier {
3267dd7cddfSDavid du Colombier 	int i, x, one, two, three;
3277dd7cddfSDavid du Colombier 
3287dd7cddfSDavid du Colombier 	one = two = three = 0;
3297dd7cddfSDavid du Colombier 	for(i = 0; i < 3; i++){
3307dd7cddfSDavid du Colombier 		if(map[i] == 0)
3317dd7cddfSDavid du Colombier 			error(Ebadarg);
3327dd7cddfSDavid du Colombier 		if(map[i] == '1'){
3337dd7cddfSDavid du Colombier 			if(one)
3347dd7cddfSDavid du Colombier 				error(Ebadarg);
3357dd7cddfSDavid du Colombier 			one = 1<<i;
3367dd7cddfSDavid du Colombier 		}
3377dd7cddfSDavid du Colombier 		else if(map[i] == '2'){
3387dd7cddfSDavid du Colombier 			if(two)
3397dd7cddfSDavid du Colombier 				error(Ebadarg);
3407dd7cddfSDavid du Colombier 			two = 1<<i;
3417dd7cddfSDavid du Colombier 		}
3427dd7cddfSDavid du Colombier 		else if(map[i] == '3'){
3437dd7cddfSDavid du Colombier 			if(three)
3447dd7cddfSDavid du Colombier 				error(Ebadarg);
3457dd7cddfSDavid du Colombier 			three = 1<<i;
3467dd7cddfSDavid du Colombier 		}
3477dd7cddfSDavid du Colombier 		else
3487dd7cddfSDavid du Colombier 			error(Ebadarg);
3497dd7cddfSDavid du Colombier 	}
3507dd7cddfSDavid du Colombier 	if(map[i])
3517dd7cddfSDavid du Colombier 		error(Ebadarg);
3527dd7cddfSDavid du Colombier 
3537dd7cddfSDavid du Colombier 	memset(buttonmap, 0, 8);
3547dd7cddfSDavid du Colombier 	for(i = 0; i < 8; i++){
3557dd7cddfSDavid du Colombier 		x = 0;
3567dd7cddfSDavid du Colombier 		if(i & 1)
3577dd7cddfSDavid du Colombier 			x |= one;
3587dd7cddfSDavid du Colombier 		if(i & 2)
3597dd7cddfSDavid du Colombier 			x |= two;
3607dd7cddfSDavid du Colombier 		if(i & 4)
3617dd7cddfSDavid du Colombier 			x |= three;
3627dd7cddfSDavid du Colombier 		buttonmap[x] = i;
3637dd7cddfSDavid du Colombier 	}
3647dd7cddfSDavid du Colombier }
3657dd7cddfSDavid du Colombier 
3667dd7cddfSDavid du Colombier static long
mousewrite(Chan * c,void * va,long n,vlong)3677dd7cddfSDavid du Colombier mousewrite(Chan *c, void *va, long n, vlong)
3687dd7cddfSDavid du Colombier {
3697dd7cddfSDavid du Colombier 	char *p;
3707dd7cddfSDavid du Colombier 	Point pt;
3719a747e4fSDavid du Colombier 	Cmdbuf *cb;
3729a747e4fSDavid du Colombier 	Cmdtab *ct;
3739a747e4fSDavid du Colombier 	char buf[64];
3749a747e4fSDavid du Colombier 	int b, msec;
3757dd7cddfSDavid du Colombier 
3767dd7cddfSDavid du Colombier 	p = va;
3779a747e4fSDavid du Colombier 	switch((ulong)c->qid.path){
3789a747e4fSDavid du Colombier 	case Qdir:
3797dd7cddfSDavid du Colombier 		error(Eisdir);
3807dd7cddfSDavid du Colombier 
3817dd7cddfSDavid du Colombier 	case Qcursor:
3827dd7cddfSDavid du Colombier 		cursoroff(1);
3837dd7cddfSDavid du Colombier 		if(n < 2*4+2*2*16){
3847dd7cddfSDavid du Colombier 			curs = arrow;
3857dd7cddfSDavid du Colombier 			Cursortocursor(&arrow);
3867dd7cddfSDavid du Colombier 		}else{
3877dd7cddfSDavid du Colombier 			n = 2*4+2*2*16;
3887dd7cddfSDavid du Colombier 			curs.offset.x = BGLONG(p+0);
3897dd7cddfSDavid du Colombier 			curs.offset.y = BGLONG(p+4);
3907dd7cddfSDavid du Colombier 			memmove(curs.clr, p+8, 2*16);
3917dd7cddfSDavid du Colombier 			memmove(curs.set, p+40, 2*16);
3927dd7cddfSDavid du Colombier 			Cursortocursor(&curs);
3937dd7cddfSDavid du Colombier 		}
3947dd7cddfSDavid du Colombier 		qlock(&mouse);
3957dd7cddfSDavid du Colombier 		mouse.redraw = 1;
3967dd7cddfSDavid du Colombier 		mouseclock();
3977dd7cddfSDavid du Colombier 		qunlock(&mouse);
3987dd7cddfSDavid du Colombier 		cursoron(1);
3997dd7cddfSDavid du Colombier 		return n;
4007dd7cddfSDavid du Colombier 
4017dd7cddfSDavid du Colombier 	case Qmousectl:
4029a747e4fSDavid du Colombier 		cb = parsecmd(va, n);
4039a747e4fSDavid du Colombier 		if(waserror()){
4049a747e4fSDavid du Colombier 			free(cb);
4059a747e4fSDavid du Colombier 			nexterror();
4069a747e4fSDavid du Colombier 		}
4079a747e4fSDavid du Colombier 
4089a747e4fSDavid du Colombier 		ct = lookupcmd(cb, mousectlmsg, nelem(mousectlmsg));
4099a747e4fSDavid du Colombier 
4109a747e4fSDavid du Colombier 		switch(ct->index){
4119a747e4fSDavid du Colombier 		case CMswap:
4127dd7cddfSDavid du Colombier 			if(mouseswap)
4137dd7cddfSDavid du Colombier 				setbuttonmap("123");
4147dd7cddfSDavid du Colombier 			else
4157dd7cddfSDavid du Colombier 				setbuttonmap("321");
4167dd7cddfSDavid du Colombier 			mouseswap ^= 1;
4179a747e4fSDavid du Colombier 			break;
4189a747e4fSDavid du Colombier 
41949eeb88aSDavid du Colombier 		case CMscrollswap:
42049eeb88aSDavid du Colombier 			scrollswap ^= 1;
42149eeb88aSDavid du Colombier 			break;
42249eeb88aSDavid du Colombier 
4239a747e4fSDavid du Colombier 		case CMbuttonmap:
4249a747e4fSDavid du Colombier 			if(cb->nf == 1)
4257dd7cddfSDavid du Colombier 				setbuttonmap("123");
4267dd7cddfSDavid du Colombier 			else
4279a747e4fSDavid du Colombier 				setbuttonmap(cb->f[1]);
4289a747e4fSDavid du Colombier 			break;
4299a747e4fSDavid du Colombier 
4309a747e4fSDavid du Colombier 		case CMwildcard:
4319a747e4fSDavid du Colombier 			mousectl(cb);
4329a747e4fSDavid du Colombier 			break;
4337dd7cddfSDavid du Colombier 		}
4349a747e4fSDavid du Colombier 
4359a747e4fSDavid du Colombier 		free(cb);
4369a747e4fSDavid du Colombier 		poperror();
4377dd7cddfSDavid du Colombier 		return n;
4387dd7cddfSDavid du Colombier 
4397dd7cddfSDavid du Colombier 	case Qmousein:
4407dd7cddfSDavid du Colombier 		if(n > sizeof buf-1)
4417dd7cddfSDavid du Colombier 			n = sizeof buf -1;
4427dd7cddfSDavid du Colombier 		memmove(buf, va, n);
4437dd7cddfSDavid du Colombier 		buf[n] = 0;
4447dd7cddfSDavid du Colombier 		p = 0;
4457dd7cddfSDavid du Colombier 		pt.x = strtol(buf+1, &p, 0);
4467dd7cddfSDavid du Colombier 		if(p == 0)
4477dd7cddfSDavid du Colombier 			error(Eshort);
4487dd7cddfSDavid du Colombier 		pt.y = strtol(p, &p, 0);
4497dd7cddfSDavid du Colombier 		if(p == 0)
4507dd7cddfSDavid du Colombier 			error(Eshort);
4517dd7cddfSDavid du Colombier 		b = strtol(p, &p, 0);
4529a747e4fSDavid du Colombier 		msec = strtol(p, &p, 0);
4539a747e4fSDavid du Colombier 		if(msec == 0)
4549a747e4fSDavid du Colombier 			msec = TK2MS(MACHP(0)->ticks);
4559a747e4fSDavid du Colombier 		mousetrack(pt.x, pt.y, b, msec);
4567dd7cddfSDavid du Colombier 		return n;
4577dd7cddfSDavid du Colombier 
4587dd7cddfSDavid du Colombier 	case Qmouse:
4597dd7cddfSDavid du Colombier 		if(n > sizeof buf-1)
4607dd7cddfSDavid du Colombier 			n = sizeof buf -1;
4617dd7cddfSDavid du Colombier 		memmove(buf, va, n);
4627dd7cddfSDavid du Colombier 		buf[n] = 0;
4637dd7cddfSDavid du Colombier 		p = 0;
4647dd7cddfSDavid du Colombier 		pt.x = strtoul(buf+1, &p, 0);
4657dd7cddfSDavid du Colombier 		if(p == 0)
4667dd7cddfSDavid du Colombier 			error(Eshort);
4677dd7cddfSDavid du Colombier 		pt.y = strtoul(p, 0, 0);
4687dd7cddfSDavid du Colombier 		qlock(&mouse);
4697dd7cddfSDavid du Colombier 		if(ptinrect(pt, gscreen->r)){
4707dd7cddfSDavid du Colombier 			mouse.xy = pt;
4717dd7cddfSDavid du Colombier 			mouse.redraw = 1;
4727dd7cddfSDavid du Colombier 			mouse.track = 1;
4737dd7cddfSDavid du Colombier 			mouseclock();
4747dd7cddfSDavid du Colombier 		}
4757dd7cddfSDavid du Colombier 		qunlock(&mouse);
4767dd7cddfSDavid du Colombier 		return n;
4777dd7cddfSDavid du Colombier 	}
4787dd7cddfSDavid du Colombier 
4797dd7cddfSDavid du Colombier 	error(Egreg);
4807dd7cddfSDavid du Colombier 	return -1;
4817dd7cddfSDavid du Colombier }
4827dd7cddfSDavid du Colombier 
4837dd7cddfSDavid du Colombier Dev mousedevtab = {
4847dd7cddfSDavid du Colombier 	'm',
4857dd7cddfSDavid du Colombier 	"mouse",
4867dd7cddfSDavid du Colombier 
4877dd7cddfSDavid du Colombier 	mousereset,
4887dd7cddfSDavid du Colombier 	mouseinit,
4899a747e4fSDavid du Colombier 	devshutdown,
4907dd7cddfSDavid du Colombier 	mouseattach,
4917dd7cddfSDavid du Colombier 	mousewalk,
4927dd7cddfSDavid du Colombier 	mousestat,
4937dd7cddfSDavid du Colombier 	mouseopen,
4947dd7cddfSDavid du Colombier 	mousecreate,
4957dd7cddfSDavid du Colombier 	mouseclose,
4967dd7cddfSDavid du Colombier 	mouseread,
4977dd7cddfSDavid du Colombier 	devbread,
4987dd7cddfSDavid du Colombier 	mousewrite,
4997dd7cddfSDavid du Colombier 	devbwrite,
5007dd7cddfSDavid du Colombier 	devremove,
5017dd7cddfSDavid du Colombier 	devwstat,
5027dd7cddfSDavid du Colombier };
5037dd7cddfSDavid du Colombier 
5047dd7cddfSDavid du Colombier void
Cursortocursor(Cursor * c)5057dd7cddfSDavid du Colombier Cursortocursor(Cursor *c)
5067dd7cddfSDavid du Colombier {
5077dd7cddfSDavid du Colombier 	lock(&cursor);
5087dd7cddfSDavid du Colombier 	memmove(&cursor.Cursor, c, sizeof(Cursor));
5097dd7cddfSDavid du Colombier 	setcursor(c);
5107dd7cddfSDavid du Colombier 	unlock(&cursor);
5117dd7cddfSDavid du Colombier }
5127dd7cddfSDavid du Colombier 
5137dd7cddfSDavid du Colombier 
5147dd7cddfSDavid du Colombier /*
5157dd7cddfSDavid du Colombier  *  called by the clock routine to redraw the cursor
5167dd7cddfSDavid du Colombier  */
5177dd7cddfSDavid du Colombier static void
mouseclock(void)5187dd7cddfSDavid du Colombier mouseclock(void)
5197dd7cddfSDavid du Colombier {
5207dd7cddfSDavid du Colombier 	if(mouse.track){
5219a747e4fSDavid du Colombier 		mousetrack(mouse.dx, mouse.dy, mouse.buttons, TK2MS(MACHP(0)->ticks));
5227dd7cddfSDavid du Colombier 		mouse.track = 0;
5237dd7cddfSDavid du Colombier 		mouse.dx = 0;
5247dd7cddfSDavid du Colombier 		mouse.dy = 0;
5257dd7cddfSDavid du Colombier 	}
5267dd7cddfSDavid du Colombier 	if(mouse.redraw && canlock(&cursor)){
5277dd7cddfSDavid du Colombier 		mouse.redraw = 0;
5287dd7cddfSDavid du Colombier 		cursoroff(0);
5297dd7cddfSDavid du Colombier 		mouse.redraw = cursoron(0);
5307dd7cddfSDavid du Colombier 		unlock(&cursor);
5317dd7cddfSDavid du Colombier 	}
5327dd7cddfSDavid du Colombier 	drawactive(0);
5337dd7cddfSDavid du Colombier }
5347dd7cddfSDavid du Colombier 
5357dd7cddfSDavid du Colombier static int
scale(int x)5367dd7cddfSDavid du Colombier scale(int x)
5377dd7cddfSDavid du Colombier {
5387dd7cddfSDavid du Colombier 	int sign = 1;
5397dd7cddfSDavid du Colombier 
5407dd7cddfSDavid du Colombier 	if(x < 0){
5417dd7cddfSDavid du Colombier 		sign = -1;
5427dd7cddfSDavid du Colombier 		x = -x;
5437dd7cddfSDavid du Colombier 	}
5447dd7cddfSDavid du Colombier 	switch(x){
5457dd7cddfSDavid du Colombier 	case 0:
5467dd7cddfSDavid du Colombier 	case 1:
5477dd7cddfSDavid du Colombier 	case 2:
5487dd7cddfSDavid du Colombier 	case 3:
5497dd7cddfSDavid du Colombier 		break;
5507dd7cddfSDavid du Colombier 	case 4:
5517dd7cddfSDavid du Colombier 		x = 6 + (mouse.acceleration>>2);
5527dd7cddfSDavid du Colombier 		break;
5537dd7cddfSDavid du Colombier 	case 5:
5547dd7cddfSDavid du Colombier 		x = 9 + (mouse.acceleration>>1);
5557dd7cddfSDavid du Colombier 		break;
5567dd7cddfSDavid du Colombier 	default:
5577dd7cddfSDavid du Colombier 		x *= mouse.maxacc;
5587dd7cddfSDavid du Colombier 		break;
5597dd7cddfSDavid du Colombier 	}
5607dd7cddfSDavid du Colombier 	return sign*x;
5617dd7cddfSDavid du Colombier }
5627dd7cddfSDavid du Colombier 
5637dd7cddfSDavid du Colombier /*
5647dd7cddfSDavid du Colombier  *  called at interrupt level to update the structure and
5657dd7cddfSDavid du Colombier  *  awaken any waiting procs.
5667dd7cddfSDavid du Colombier  */
5677dd7cddfSDavid du Colombier void
mousetrack(int dx,int dy,int b,int msec)5689a747e4fSDavid du Colombier mousetrack(int dx, int dy, int b, int msec)
5697dd7cddfSDavid du Colombier {
5707dd7cddfSDavid du Colombier 	int x, y, lastb;
5717dd7cddfSDavid du Colombier 
5727dd7cddfSDavid du Colombier 	if(gscreen==nil)
5737dd7cddfSDavid du Colombier 		return;
5747dd7cddfSDavid du Colombier 
5757dd7cddfSDavid du Colombier 	if(mouse.acceleration){
5767dd7cddfSDavid du Colombier 		dx = scale(dx);
5777dd7cddfSDavid du Colombier 		dy = scale(dy);
5787dd7cddfSDavid du Colombier 	}
5797dd7cddfSDavid du Colombier 	x = mouse.xy.x + dx;
5809a747e4fSDavid du Colombier 	if(x < gscreen->clipr.min.x)
5819a747e4fSDavid du Colombier 		x = gscreen->clipr.min.x;
5829a747e4fSDavid du Colombier 	if(x >= gscreen->clipr.max.x)
5839a747e4fSDavid du Colombier 		x = gscreen->clipr.max.x;
5847dd7cddfSDavid du Colombier 	y = mouse.xy.y + dy;
5859a747e4fSDavid du Colombier 	if(y < gscreen->clipr.min.y)
5869a747e4fSDavid du Colombier 		y = gscreen->clipr.min.y;
5879a747e4fSDavid du Colombier 	if(y >= gscreen->clipr.max.y)
5889a747e4fSDavid du Colombier 		y = gscreen->clipr.max.y;
5897dd7cddfSDavid du Colombier 
5907dd7cddfSDavid du Colombier 	lastb = mouse.buttons;
5917dd7cddfSDavid du Colombier 	mouse.xy = Pt(x, y);
592e29df7b0SDavid du Colombier 	mouse.buttons = b|kbdbuttons;
5937dd7cddfSDavid du Colombier 	mouse.redraw = 1;
5947dd7cddfSDavid du Colombier 	mouse.counter++;
5959a747e4fSDavid du Colombier 	mouse.msec = msec;
5967dd7cddfSDavid du Colombier 
5977dd7cddfSDavid du Colombier 	/*
5987dd7cddfSDavid du Colombier 	 * if the queue fills, we discard the entire queue and don't
5997dd7cddfSDavid du Colombier 	 * queue any more events until a reader polls the mouse.
6007dd7cddfSDavid du Colombier 	 */
6017dd7cddfSDavid du Colombier 	if(!mouse.qfull && lastb != b) {	/* add to ring */
6027dd7cddfSDavid du Colombier 		mouse.queue[mouse.wi] = mouse.Mousestate;
6037dd7cddfSDavid du Colombier 		if(++mouse.wi == nelem(mouse.queue))
6047dd7cddfSDavid du Colombier 			mouse.wi = 0;
6057dd7cddfSDavid du Colombier 		if(mouse.wi == mouse.ri)
6067dd7cddfSDavid du Colombier 			mouse.qfull = 1;
6077dd7cddfSDavid du Colombier 	}
6087dd7cddfSDavid du Colombier 	wakeup(&mouse.r);
6097dd7cddfSDavid du Colombier 	drawactive(1);
6107dd7cddfSDavid du Colombier }
6117dd7cddfSDavid du Colombier 
6127dd7cddfSDavid du Colombier /*
6137dd7cddfSDavid du Colombier  *  microsoft 3 button, 7 bit bytes
6147dd7cddfSDavid du Colombier  *
6157dd7cddfSDavid du Colombier  *	byte 0 -	1  L  R Y7 Y6 X7 X6
6167dd7cddfSDavid du Colombier  *	byte 1 -	0 X5 X4 X3 X2 X1 X0
6177dd7cddfSDavid du Colombier  *	byte 2 -	0 Y5 Y4 Y3 Y2 Y1 Y0
6187dd7cddfSDavid du Colombier  *	byte 3 -	0  M  x  x  x  x  x	(optional)
6197dd7cddfSDavid du Colombier  *
6207dd7cddfSDavid du Colombier  *  shift & right button is the same as middle button (for 2 button mice)
6217dd7cddfSDavid du Colombier  */
6227dd7cddfSDavid du Colombier int
m3mouseputc(Queue *,int c)6237dd7cddfSDavid du Colombier m3mouseputc(Queue*, int c)
6247dd7cddfSDavid du Colombier {
6257dd7cddfSDavid du Colombier 	static uchar msg[3];
6267dd7cddfSDavid du Colombier 	static int nb;
6277dd7cddfSDavid du Colombier 	static int middle;
62859cc4ca5SDavid du Colombier 	static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 3 };
6297dd7cddfSDavid du Colombier 	short x;
6307dd7cddfSDavid du Colombier 	int dx, dy, newbuttons;
63124c25b93SDavid du Colombier 	static ulong lasttick;
63224c25b93SDavid du Colombier 	ulong m;
63324c25b93SDavid du Colombier 
63424c25b93SDavid du Colombier 	/* Resynchronize in stream with timing. */
63524c25b93SDavid du Colombier 	m = MACHP(0)->ticks;
63624c25b93SDavid du Colombier 	if(TK2SEC(m - lasttick) > 2)
63724c25b93SDavid du Colombier 		nb = 0;
63824c25b93SDavid du Colombier 	lasttick = m;
6397dd7cddfSDavid du Colombier 
6407dd7cddfSDavid du Colombier 	if(nb==0){
6417dd7cddfSDavid du Colombier 		/*
6427dd7cddfSDavid du Colombier 		 * an extra byte comes for middle button motion.
6437dd7cddfSDavid du Colombier 		 * only two possible values for the extra byte.
6447dd7cddfSDavid du Colombier 		 */
6457dd7cddfSDavid du Colombier 		if(c == 0x00 || c == 0x20){
6467dd7cddfSDavid du Colombier 			/* an extra byte gets sent for the middle button */
6477dd7cddfSDavid du Colombier 			middle = (c&0x20) ? 2 : 0;
6487dd7cddfSDavid du Colombier 			newbuttons = (mouse.buttons & ~2) | middle;
6499a747e4fSDavid du Colombier 			mousetrack(0, 0, newbuttons, TK2MS(MACHP(0)->ticks));
6507dd7cddfSDavid du Colombier 			return 0;
6517dd7cddfSDavid du Colombier 		}
6527dd7cddfSDavid du Colombier 	}
6537dd7cddfSDavid du Colombier 	msg[nb] = c;
6547dd7cddfSDavid du Colombier 	if(++nb == 3){
6557dd7cddfSDavid du Colombier 		nb = 0;
6567dd7cddfSDavid du Colombier 		newbuttons = middle | b[(msg[0]>>4)&3 | (mouseshifted ? 4 : 0)];
6577dd7cddfSDavid du Colombier 		x = (msg[0]&0x3)<<14;
6587dd7cddfSDavid du Colombier 		dx = (x>>8) | msg[1];
6597dd7cddfSDavid du Colombier 		x = (msg[0]&0xc)<<12;
6607dd7cddfSDavid du Colombier 		dy = (x>>8) | msg[2];
6619a747e4fSDavid du Colombier 		mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
6627dd7cddfSDavid du Colombier 	}
6637dd7cddfSDavid du Colombier 	return 0;
6647dd7cddfSDavid du Colombier }
6657dd7cddfSDavid du Colombier 
6667dd7cddfSDavid du Colombier /*
667aa46331bSDavid du Colombier  * microsoft intellimouse 3 buttons + scroll
668aa46331bSDavid du Colombier  * 	byte 0 -	1  L  R Y7 Y6 X7 X6
669aa46331bSDavid du Colombier  *	byte 1 -	0 X5 X4 X3 X2 X1 X0
670aa46331bSDavid du Colombier  *	byte 2 -	0 Y5 Y4 Y3 Y2 Y1 Y0
671aa46331bSDavid du Colombier  *	byte 3 -	0  0  M  %  %  %  %
672aa46331bSDavid du Colombier  *
673aa46331bSDavid du Colombier  *	%: 0xf => U , 0x1 => D
674aa46331bSDavid du Colombier  *
675aa46331bSDavid du Colombier  *	L: left
676aa46331bSDavid du Colombier  *	R: right
677aa46331bSDavid du Colombier  *	U: up
678aa46331bSDavid du Colombier  *	D: down
679aa46331bSDavid du Colombier  */
680aa46331bSDavid du Colombier int
m5mouseputc(Queue *,int c)681aa46331bSDavid du Colombier m5mouseputc(Queue*, int c)
682aa46331bSDavid du Colombier {
683aa46331bSDavid du Colombier 	static uchar msg[3];
684aa46331bSDavid du Colombier 	static int nb;
68524c25b93SDavid du Colombier 	static ulong lasttick;
68624c25b93SDavid du Colombier 	ulong m;
68724c25b93SDavid du Colombier 
68824c25b93SDavid du Colombier 	/* Resynchronize in stream with timing. */
68924c25b93SDavid du Colombier 	m = MACHP(0)->ticks;
69024c25b93SDavid du Colombier 	if(TK2SEC(m - lasttick) > 2)
69124c25b93SDavid du Colombier 		nb = 0;
69224c25b93SDavid du Colombier 	lasttick = m;
69324c25b93SDavid du Colombier 
694aa46331bSDavid du Colombier 	msg[nb++] = c & 0x7f;
695aa46331bSDavid du Colombier 	if (nb == 4) {
696aa46331bSDavid du Colombier 		schar dx,dy,newbuttons;
697aa46331bSDavid du Colombier 		dx = msg[1] | (msg[0] & 0x3) << 6;
698aa46331bSDavid du Colombier 		dy = msg[2] | (msg[0] & 0xc) << 4;
699aa46331bSDavid du Colombier 		newbuttons =
700aa46331bSDavid du Colombier 			(msg[0] & 0x10) >> (mouseshifted ? 3 : 2)
701aa46331bSDavid du Colombier 			| (msg[0] & 0x20) >> 5
702aa46331bSDavid du Colombier 			| ( msg[3] == 0x10 ? 0x02 :
70315174232SDavid du Colombier 			    msg[3] == 0x0f ? ScrollUp :
70415174232SDavid du Colombier 			    msg[3] == 0x01 ? ScrollDown : 0 );
705aa46331bSDavid du Colombier 		mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
706aa46331bSDavid du Colombier 		nb = 0;
707aa46331bSDavid du Colombier 	}
708aa46331bSDavid du Colombier 	return 0;
709aa46331bSDavid du Colombier }
710aa46331bSDavid du Colombier 
711aa46331bSDavid du Colombier /*
7127dd7cddfSDavid du Colombier  *  Logitech 5 byte packed binary mouse format, 8 bit bytes
7137dd7cddfSDavid du Colombier  *
7147dd7cddfSDavid du Colombier  *  shift & right button is the same as middle button (for 2 button mice)
7157dd7cddfSDavid du Colombier  */
7167dd7cddfSDavid du Colombier int
mouseputc(Queue *,int c)7177dd7cddfSDavid du Colombier mouseputc(Queue*, int c)
7187dd7cddfSDavid du Colombier {
7197dd7cddfSDavid du Colombier 	static short msg[5];
7207dd7cddfSDavid du Colombier 	static int nb;
72159cc4ca5SDavid du Colombier 	static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 3, 3, 7};
7227dd7cddfSDavid du Colombier 	int dx, dy, newbuttons;
72324c25b93SDavid du Colombier 	static ulong lasttick;
72424c25b93SDavid du Colombier 	ulong m;
72524c25b93SDavid du Colombier 
72624c25b93SDavid du Colombier 	/* Resynchronize in stream with timing. */
72724c25b93SDavid du Colombier 	m = MACHP(0)->ticks;
72824c25b93SDavid du Colombier 	if(TK2SEC(m - lasttick) > 2)
72924c25b93SDavid du Colombier 		nb = 0;
73024c25b93SDavid du Colombier 	lasttick = m;
7317dd7cddfSDavid du Colombier 
7327dd7cddfSDavid du Colombier 	if((c&0xF0) == 0x80)
7337dd7cddfSDavid du Colombier 		nb=0;
7347dd7cddfSDavid du Colombier 	msg[nb] = c;
7357dd7cddfSDavid du Colombier 	if(c & 0x80)
7367dd7cddfSDavid du Colombier 		msg[nb] |= ~0xFF;	/* sign extend */
7377dd7cddfSDavid du Colombier 	if(++nb == 5){
7387dd7cddfSDavid du Colombier 		newbuttons = b[((msg[0]&7)^7) | (mouseshifted ? 8 : 0)];
7397dd7cddfSDavid du Colombier 		dx = msg[1]+msg[3];
7407dd7cddfSDavid du Colombier 		dy = -(msg[2]+msg[4]);
7419a747e4fSDavid du Colombier 		mousetrack(dx, dy, newbuttons, TK2MS(MACHP(0)->ticks));
7427dd7cddfSDavid du Colombier 		nb = 0;
7437dd7cddfSDavid du Colombier 	}
7447dd7cddfSDavid du Colombier 	return 0;
7457dd7cddfSDavid du Colombier }
7467dd7cddfSDavid du Colombier 
7477dd7cddfSDavid du Colombier int
mousechanged(void *)7487dd7cddfSDavid du Colombier mousechanged(void*)
7497dd7cddfSDavid du Colombier {
750e29df7b0SDavid du Colombier 	return mouse.lastcounter != mouse.counter ||
751e29df7b0SDavid du Colombier 		mouse.lastresize != mouse.resize;
7527dd7cddfSDavid du Colombier }
7537dd7cddfSDavid du Colombier 
7547dd7cddfSDavid du Colombier Point
mousexy(void)7557dd7cddfSDavid du Colombier mousexy(void)
7567dd7cddfSDavid du Colombier {
7577dd7cddfSDavid du Colombier 	return mouse.xy;
7587dd7cddfSDavid du Colombier }
7597dd7cddfSDavid du Colombier 
7607dd7cddfSDavid du Colombier void
mouseaccelerate(int x)7617dd7cddfSDavid du Colombier mouseaccelerate(int x)
7627dd7cddfSDavid du Colombier {
7637dd7cddfSDavid du Colombier 	mouse.acceleration = x;
7647dd7cddfSDavid du Colombier 	if(mouse.acceleration < 3)
7657dd7cddfSDavid du Colombier 		mouse.maxacc = 2;
7667dd7cddfSDavid du Colombier 	else
7677dd7cddfSDavid du Colombier 		mouse.maxacc = mouse.acceleration;
7687dd7cddfSDavid du Colombier }
769e29df7b0SDavid du Colombier 
770e29df7b0SDavid du Colombier /*
771e29df7b0SDavid du Colombier  * notify reader that screen has been resized
772e29df7b0SDavid du Colombier  */
773e29df7b0SDavid du Colombier void
mouseresize(void)774e29df7b0SDavid du Colombier mouseresize(void)
775e29df7b0SDavid du Colombier {
776e29df7b0SDavid du Colombier 	mouse.resize++;
777e29df7b0SDavid du Colombier 	wakeup(&mouse.r);
778e29df7b0SDavid du Colombier }
779e29df7b0SDavid du Colombier 
780