xref: /plan9/sys/src/cmd/unix/drawterm/kern/devmouse.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1*8ccd4a63SDavid du Colombier #include	"u.h"
2*8ccd4a63SDavid du Colombier #include	"lib.h"
3*8ccd4a63SDavid du Colombier #include	"dat.h"
4*8ccd4a63SDavid du Colombier #include	"fns.h"
5*8ccd4a63SDavid du Colombier #include	"error.h"
6*8ccd4a63SDavid du Colombier 
7*8ccd4a63SDavid du Colombier #include	"draw.h"
8*8ccd4a63SDavid du Colombier #include	"memdraw.h"
9*8ccd4a63SDavid du Colombier #include	"screen.h"
10*8ccd4a63SDavid du Colombier 
11*8ccd4a63SDavid du Colombier int	mousequeue = 1;
12*8ccd4a63SDavid du Colombier 
13*8ccd4a63SDavid du Colombier Mouseinfo	mouse;
14*8ccd4a63SDavid du Colombier Cursorinfo	cursor;
15*8ccd4a63SDavid du Colombier 
16*8ccd4a63SDavid du Colombier static int	mousechanged(void*);
17*8ccd4a63SDavid du Colombier 
18*8ccd4a63SDavid du Colombier enum{
19*8ccd4a63SDavid du Colombier 	Qdir,
20*8ccd4a63SDavid du Colombier 	Qcursor,
21*8ccd4a63SDavid du Colombier 	Qmouse
22*8ccd4a63SDavid du Colombier };
23*8ccd4a63SDavid du Colombier 
24*8ccd4a63SDavid du Colombier Dirtab mousedir[]={
25*8ccd4a63SDavid du Colombier 	".",		{Qdir, 0, QTDIR},	0,	DMDIR|0555,
26*8ccd4a63SDavid du Colombier 	"cursor",	{Qcursor},	0,			0666,
27*8ccd4a63SDavid du Colombier 	"mouse",	{Qmouse},	0,			0666,
28*8ccd4a63SDavid du Colombier };
29*8ccd4a63SDavid du Colombier 
30*8ccd4a63SDavid du Colombier #define	NMOUSE	(sizeof(mousedir)/sizeof(Dirtab))
31*8ccd4a63SDavid du Colombier 
32*8ccd4a63SDavid du Colombier static Chan*
mouseattach(char * spec)33*8ccd4a63SDavid du Colombier mouseattach(char *spec)
34*8ccd4a63SDavid du Colombier {
35*8ccd4a63SDavid du Colombier 	return devattach('m', spec);
36*8ccd4a63SDavid du Colombier }
37*8ccd4a63SDavid du Colombier 
38*8ccd4a63SDavid du Colombier static Walkqid*
mousewalk(Chan * c,Chan * nc,char ** name,int nname)39*8ccd4a63SDavid du Colombier mousewalk(Chan *c, Chan *nc, char **name, int nname)
40*8ccd4a63SDavid du Colombier {
41*8ccd4a63SDavid du Colombier 	return devwalk(c, nc, name, nname, mousedir, NMOUSE, devgen);
42*8ccd4a63SDavid du Colombier }
43*8ccd4a63SDavid du Colombier 
44*8ccd4a63SDavid du Colombier static int
mousestat(Chan * c,uchar * db,int n)45*8ccd4a63SDavid du Colombier mousestat(Chan *c, uchar *db, int n)
46*8ccd4a63SDavid du Colombier {
47*8ccd4a63SDavid du Colombier 	return devstat(c, db, n, mousedir, NMOUSE, devgen);
48*8ccd4a63SDavid du Colombier }
49*8ccd4a63SDavid du Colombier 
50*8ccd4a63SDavid du Colombier static Chan*
mouseopen(Chan * c,int omode)51*8ccd4a63SDavid du Colombier mouseopen(Chan *c, int omode)
52*8ccd4a63SDavid du Colombier {
53*8ccd4a63SDavid du Colombier 	switch((long)c->qid.path){
54*8ccd4a63SDavid du Colombier 	case Qdir:
55*8ccd4a63SDavid du Colombier 		if(omode != OREAD)
56*8ccd4a63SDavid du Colombier 			error(Eperm);
57*8ccd4a63SDavid du Colombier 		break;
58*8ccd4a63SDavid du Colombier 	case Qmouse:
59*8ccd4a63SDavid du Colombier 		lock(&mouse.lk);
60*8ccd4a63SDavid du Colombier 		if(mouse.open){
61*8ccd4a63SDavid du Colombier 			unlock(&mouse.lk);
62*8ccd4a63SDavid du Colombier 			error(Einuse);
63*8ccd4a63SDavid du Colombier 		}
64*8ccd4a63SDavid du Colombier 		mouse.open = 1;
65*8ccd4a63SDavid du Colombier 		unlock(&mouse.lk);
66*8ccd4a63SDavid du Colombier 		break;
67*8ccd4a63SDavid du Colombier 	}
68*8ccd4a63SDavid du Colombier 	c->mode = openmode(omode);
69*8ccd4a63SDavid du Colombier 	c->flag |= COPEN;
70*8ccd4a63SDavid du Colombier 	c->offset = 0;
71*8ccd4a63SDavid du Colombier 	return c;
72*8ccd4a63SDavid du Colombier }
73*8ccd4a63SDavid du Colombier 
74*8ccd4a63SDavid du Colombier void
mouseclose(Chan * c)75*8ccd4a63SDavid du Colombier mouseclose(Chan *c)
76*8ccd4a63SDavid du Colombier {
77*8ccd4a63SDavid du Colombier 	if(!(c->flag&COPEN))
78*8ccd4a63SDavid du Colombier 		return;
79*8ccd4a63SDavid du Colombier 
80*8ccd4a63SDavid du Colombier 	switch((long)c->qid.path) {
81*8ccd4a63SDavid du Colombier 	case Qmouse:
82*8ccd4a63SDavid du Colombier 		lock(&mouse.lk);
83*8ccd4a63SDavid du Colombier 		mouse.open = 0;
84*8ccd4a63SDavid du Colombier 		unlock(&mouse.lk);
85*8ccd4a63SDavid du Colombier 		cursorarrow();
86*8ccd4a63SDavid du Colombier 	}
87*8ccd4a63SDavid du Colombier }
88*8ccd4a63SDavid du Colombier 
89*8ccd4a63SDavid du Colombier 
90*8ccd4a63SDavid du Colombier long
mouseread(Chan * c,void * va,long n,vlong offset)91*8ccd4a63SDavid du Colombier mouseread(Chan *c, void *va, long n, vlong offset)
92*8ccd4a63SDavid du Colombier {
93*8ccd4a63SDavid du Colombier 	char buf[4*12+1];
94*8ccd4a63SDavid du Colombier 	uchar *p;
95*8ccd4a63SDavid du Colombier 	int i, nn;
96*8ccd4a63SDavid du Colombier 	ulong msec;
97*8ccd4a63SDavid du Colombier /*	static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };	*/
98*8ccd4a63SDavid du Colombier 
99*8ccd4a63SDavid du Colombier 	p = va;
100*8ccd4a63SDavid du Colombier 	switch((long)c->qid.path){
101*8ccd4a63SDavid du Colombier 	case Qdir:
102*8ccd4a63SDavid du Colombier 		return devdirread(c, va, n, mousedir, NMOUSE, devgen);
103*8ccd4a63SDavid du Colombier 
104*8ccd4a63SDavid du Colombier 	case Qcursor:
105*8ccd4a63SDavid du Colombier 		if(offset != 0)
106*8ccd4a63SDavid du Colombier 			return 0;
107*8ccd4a63SDavid du Colombier 		if(n < 2*4+2*2*16)
108*8ccd4a63SDavid du Colombier 			error(Eshort);
109*8ccd4a63SDavid du Colombier 		n = 2*4+2*2*16;
110*8ccd4a63SDavid du Colombier 		lock(&cursor.lk);
111*8ccd4a63SDavid du Colombier 		BPLONG(p+0, cursor.offset.x);
112*8ccd4a63SDavid du Colombier 		BPLONG(p+4, cursor.offset.y);
113*8ccd4a63SDavid du Colombier 		memmove(p+8, cursor.clr, 2*16);
114*8ccd4a63SDavid du Colombier 		memmove(p+40, cursor.set, 2*16);
115*8ccd4a63SDavid du Colombier 		unlock(&cursor.lk);
116*8ccd4a63SDavid du Colombier 		return n;
117*8ccd4a63SDavid du Colombier 
118*8ccd4a63SDavid du Colombier 	case Qmouse:
119*8ccd4a63SDavid du Colombier 		while(mousechanged(0) == 0)
120*8ccd4a63SDavid du Colombier 			sleep(&mouse.r, mousechanged, 0);
121*8ccd4a63SDavid du Colombier 
122*8ccd4a63SDavid du Colombier 		lock(&screen.lk);
123*8ccd4a63SDavid du Colombier 		if(screen.reshaped) {
124*8ccd4a63SDavid du Colombier 			screen.reshaped = 0;
125*8ccd4a63SDavid du Colombier 			sprint(buf, "t%11d %11d", 0, ticks());
126*8ccd4a63SDavid du Colombier 			if(n > 1+2*12)
127*8ccd4a63SDavid du Colombier 				n = 1+2*12;
128*8ccd4a63SDavid du Colombier 			memmove(va, buf, n);
129*8ccd4a63SDavid du Colombier 			unlock(&screen.lk);
130*8ccd4a63SDavid du Colombier 			return n;
131*8ccd4a63SDavid du Colombier 		}
132*8ccd4a63SDavid du Colombier 		unlock(&screen.lk);
133*8ccd4a63SDavid du Colombier 
134*8ccd4a63SDavid du Colombier 		lock(&mouse.lk);
135*8ccd4a63SDavid du Colombier 		i = mouse.ri;
136*8ccd4a63SDavid du Colombier 		nn = (mouse.wi + Mousequeue - i) % Mousequeue;
137*8ccd4a63SDavid du Colombier 		if(nn < 1)
138*8ccd4a63SDavid du Colombier 			panic("empty mouse queue");
139*8ccd4a63SDavid du Colombier 		msec = ticks();
140*8ccd4a63SDavid du Colombier 		while(nn > 1) {
141*8ccd4a63SDavid du Colombier 			if(mouse.queue[i].msec + Mousewindow > msec)
142*8ccd4a63SDavid du Colombier 				break;
143*8ccd4a63SDavid du Colombier 			i = (i+1)%Mousequeue;
144*8ccd4a63SDavid du Colombier 			nn--;
145*8ccd4a63SDavid du Colombier 		}
146*8ccd4a63SDavid du Colombier 		sprint(buf, "m%11d %11d %11d %11d",
147*8ccd4a63SDavid du Colombier 			mouse.queue[i].xy.x,
148*8ccd4a63SDavid du Colombier 			mouse.queue[i].xy.y,
149*8ccd4a63SDavid du Colombier 			mouse.queue[i].buttons,
150*8ccd4a63SDavid du Colombier 			mouse.queue[i].msec);
151*8ccd4a63SDavid du Colombier 		mouse.ri = (i+1)%Mousequeue;
152*8ccd4a63SDavid du Colombier 		unlock(&mouse.lk);
153*8ccd4a63SDavid du Colombier 		if(n > 1+4*12)
154*8ccd4a63SDavid du Colombier 			n = 1+4*12;
155*8ccd4a63SDavid du Colombier 		memmove(va, buf, n);
156*8ccd4a63SDavid du Colombier 		return n;
157*8ccd4a63SDavid du Colombier 	}
158*8ccd4a63SDavid du Colombier 	return 0;
159*8ccd4a63SDavid du Colombier }
160*8ccd4a63SDavid du Colombier 
161*8ccd4a63SDavid du Colombier long
mousewrite(Chan * c,void * va,long n,vlong offset)162*8ccd4a63SDavid du Colombier mousewrite(Chan *c, void *va, long n, vlong offset)
163*8ccd4a63SDavid du Colombier {
164*8ccd4a63SDavid du Colombier 	char *p;
165*8ccd4a63SDavid du Colombier 	Point pt;
166*8ccd4a63SDavid du Colombier 	char buf[64];
167*8ccd4a63SDavid du Colombier 
168*8ccd4a63SDavid du Colombier 	USED(offset);
169*8ccd4a63SDavid du Colombier 
170*8ccd4a63SDavid du Colombier 	p = va;
171*8ccd4a63SDavid du Colombier 	switch((long)c->qid.path){
172*8ccd4a63SDavid du Colombier 	case Qdir:
173*8ccd4a63SDavid du Colombier 		error(Eisdir);
174*8ccd4a63SDavid du Colombier 
175*8ccd4a63SDavid du Colombier 	case Qcursor:
176*8ccd4a63SDavid du Colombier 		if(n < 2*4+2*2*16){
177*8ccd4a63SDavid du Colombier 			cursorarrow();
178*8ccd4a63SDavid du Colombier 		}else{
179*8ccd4a63SDavid du Colombier 			n = 2*4+2*2*16;
180*8ccd4a63SDavid du Colombier 			lock(&cursor.lk);
181*8ccd4a63SDavid du Colombier 			cursor.offset.x = BGLONG(p+0);
182*8ccd4a63SDavid du Colombier 			cursor.offset.y = BGLONG(p+4);
183*8ccd4a63SDavid du Colombier 			memmove(cursor.clr, p+8, 2*16);
184*8ccd4a63SDavid du Colombier 			memmove(cursor.set, p+40, 2*16);
185*8ccd4a63SDavid du Colombier 			unlock(&cursor.lk);
186*8ccd4a63SDavid du Colombier 			setcursor();
187*8ccd4a63SDavid du Colombier 		}
188*8ccd4a63SDavid du Colombier 		return n;
189*8ccd4a63SDavid du Colombier 
190*8ccd4a63SDavid du Colombier 	case Qmouse:
191*8ccd4a63SDavid du Colombier 		if(n > sizeof buf-1)
192*8ccd4a63SDavid du Colombier 			n = sizeof buf -1;
193*8ccd4a63SDavid du Colombier 		memmove(buf, va, n);
194*8ccd4a63SDavid du Colombier 		buf[n] = 0;
195*8ccd4a63SDavid du Colombier 		p = 0;
196*8ccd4a63SDavid du Colombier 		pt.x = strtoul(buf+1, &p, 0);
197*8ccd4a63SDavid du Colombier 		if(p == 0)
198*8ccd4a63SDavid du Colombier 			error(Eshort);
199*8ccd4a63SDavid du Colombier 		pt.y = strtoul(p, 0, 0);
200*8ccd4a63SDavid du Colombier 		if(ptinrect(pt, gscreen->r))
201*8ccd4a63SDavid du Colombier 			mouseset(pt);
202*8ccd4a63SDavid du Colombier 		return n;
203*8ccd4a63SDavid du Colombier 	}
204*8ccd4a63SDavid du Colombier 
205*8ccd4a63SDavid du Colombier 	error(Egreg);
206*8ccd4a63SDavid du Colombier 	return -1;
207*8ccd4a63SDavid du Colombier }
208*8ccd4a63SDavid du Colombier 
209*8ccd4a63SDavid du Colombier int
mousechanged(void * a)210*8ccd4a63SDavid du Colombier mousechanged(void *a)
211*8ccd4a63SDavid du Colombier {
212*8ccd4a63SDavid du Colombier 	USED(a);
213*8ccd4a63SDavid du Colombier 
214*8ccd4a63SDavid du Colombier 	return mouse.ri != mouse.wi || screen.reshaped;
215*8ccd4a63SDavid du Colombier }
216*8ccd4a63SDavid du Colombier 
217*8ccd4a63SDavid du Colombier Dev mousedevtab = {
218*8ccd4a63SDavid du Colombier 	'm',
219*8ccd4a63SDavid du Colombier 	"mouse",
220*8ccd4a63SDavid du Colombier 
221*8ccd4a63SDavid du Colombier 	devreset,
222*8ccd4a63SDavid du Colombier 	devinit,
223*8ccd4a63SDavid du Colombier 	devshutdown,
224*8ccd4a63SDavid du Colombier 	mouseattach,
225*8ccd4a63SDavid du Colombier 	mousewalk,
226*8ccd4a63SDavid du Colombier 	mousestat,
227*8ccd4a63SDavid du Colombier 	mouseopen,
228*8ccd4a63SDavid du Colombier 	devcreate,
229*8ccd4a63SDavid du Colombier 	mouseclose,
230*8ccd4a63SDavid du Colombier 	mouseread,
231*8ccd4a63SDavid du Colombier 	devbread,
232*8ccd4a63SDavid du Colombier 	mousewrite,
233*8ccd4a63SDavid du Colombier 	devbwrite,
234*8ccd4a63SDavid du Colombier 	devremove,
235*8ccd4a63SDavid du Colombier 	devwstat,
236*8ccd4a63SDavid du Colombier };
237*8ccd4a63SDavid du Colombier 
238