237 lines · 3.7 KB · C
RawDownload
#include	"u.h"#include	"lib.h"#include	"dat.h"#include	"fns.h"#include	"error.h" #include	"draw.h"#include	"memdraw.h"#include	"screen.h" int	mousequeue = 1; Mouseinfo	mouse;Cursorinfo	cursor; static int	mousechanged(void*); enum{	Qdir,	Qcursor,	Qmouse}; Dirtab mousedir[]={	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555,		"cursor",	{Qcursor},	0,			0666,	"mouse",	{Qmouse},	0,			0666,}; #define	NMOUSE	(sizeof(mousedir)/sizeof(Dirtab)) static Chan*mouseattach(char *spec){	return devattach('m', spec);} static Walkqid*mousewalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, mousedir, NMOUSE, devgen);} static intmousestat(Chan *c, uchar *db, int n){	return devstat(c, db, n, mousedir, NMOUSE, devgen);} static Chan*mouseopen(Chan *c, int omode){	switch((long)c->qid.path){	case Qdir:		if(omode != OREAD)			error(Eperm);		break;	case Qmouse:		lock(&mouse.lk);		if(mouse.open){			unlock(&mouse.lk);			error(Einuse);		}		mouse.open = 1;		unlock(&mouse.lk);		break;	}	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	return c;} voidmouseclose(Chan *c){	if(!(c->flag&COPEN))		return; 	switch((long)c->qid.path) {	case Qmouse:		lock(&mouse.lk);		mouse.open = 0;		unlock(&mouse.lk);		cursorarrow();	}}  longmouseread(Chan *c, void *va, long n, vlong offset){	char buf[4*12+1];	uchar *p;	int i, nn;	ulong msec;/*	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };	*/ 	p = va;	switch((long)c->qid.path){	case Qdir:		return devdirread(c, va, n, mousedir, NMOUSE, devgen); 	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, cursor.offset.x);		BPLONG(p+4, cursor.offset.y);		memmove(p+8, cursor.clr, 2*16);		memmove(p+40, cursor.set, 2*16);		unlock(&cursor.lk);		return n; 	case Qmouse:		while(mousechanged(0) == 0)			sleep(&mouse.r, mousechanged, 0); 		lock(&screen.lk);		if(screen.reshaped) {			screen.reshaped = 0;			sprint(buf, "t%11d %11d", 0, ticks());			if(n > 1+2*12)				n = 1+2*12;			memmove(va, buf, n);			unlock(&screen.lk);			return n;		}		unlock(&screen.lk); 		lock(&mouse.lk);		i = mouse.ri;		nn = (mouse.wi + Mousequeue - i) % Mousequeue;		if(nn < 1)			panic("empty mouse queue");		msec = ticks();		while(nn > 1) {			if(mouse.queue[i].msec + Mousewindow > msec)				break;			i = (i+1)%Mousequeue;			nn--;		}		sprint(buf, "m%11d %11d %11d %11d",			mouse.queue[i].xy.x,			mouse.queue[i].xy.y,			mouse.queue[i].buttons,			mouse.queue[i].msec);		mouse.ri = (i+1)%Mousequeue;		unlock(&mouse.lk);		if(n > 1+4*12)			n = 1+4*12;		memmove(va, buf, n);		return n;	}	return 0;} longmousewrite(Chan *c, void *va, long n, vlong offset){	char *p;	Point pt;	char buf[64]; 	USED(offset); 	p = va;	switch((long)c->qid.path){	case Qdir:		error(Eisdir); 	case Qcursor:		if(n < 2*4+2*2*16){			cursorarrow();		}else{			n = 2*4+2*2*16;			lock(&cursor.lk);			cursor.offset.x = BGLONG(p+0);			cursor.offset.y = BGLONG(p+4);			memmove(cursor.clr, p+8, 2*16);			memmove(cursor.set, p+40, 2*16);			unlock(&cursor.lk);			setcursor();		}		return n; 	case Qmouse:		if(n > sizeof buf-1)			n = sizeof buf -1;		memmove(buf, va, n);		buf[n] = 0;		p = 0;		pt.x = strtoul(buf+1, &p, 0);		if(p == 0)			error(Eshort);		pt.y = strtoul(p, 0, 0);		if(ptinrect(pt, gscreen->r))			mouseset(pt);		return n;	} 	error(Egreg);	return -1;} intmousechanged(void *a){	USED(a); 	return mouse.ri != mouse.wi || screen.reshaped;} Dev mousedevtab = {	'm',	"mouse", 	devreset,	devinit,	devshutdown,	mouseattach,	mousewalk,	mousestat,	mouseopen,	devcreate,	mouseclose,	mouseread,	devbread,	mousewrite,	devbwrite,	devremove,	devwstat,};