xref: /inferno-os/emu/port/devpointer.c (revision 4a062f32e3dd93bf371feb27f3ccc28d7930099e)
1*37da2899SCharles.Forsyth /*
2*37da2899SCharles.Forsyth  * mouse or stylus
3*37da2899SCharles.Forsyth  */
4*37da2899SCharles.Forsyth 
5*37da2899SCharles.Forsyth #include	"dat.h"
6*37da2899SCharles.Forsyth #include	"fns.h"
7*37da2899SCharles.Forsyth #include	"../port/error.h"
8*37da2899SCharles.Forsyth 
9*37da2899SCharles.Forsyth #include <draw.h>
10*37da2899SCharles.Forsyth #include <memdraw.h>
11*37da2899SCharles.Forsyth #include <cursor.h>
12*37da2899SCharles.Forsyth 
13*37da2899SCharles.Forsyth #define	cursorenable()
14*37da2899SCharles.Forsyth #define	cursordisable()
15*37da2899SCharles.Forsyth 
16*37da2899SCharles.Forsyth enum{
17*37da2899SCharles.Forsyth 	Qdir,
18*37da2899SCharles.Forsyth 	Qpointer,
19*37da2899SCharles.Forsyth 	Qcursor
20*37da2899SCharles.Forsyth };
21*37da2899SCharles.Forsyth 
22*37da2899SCharles.Forsyth typedef struct Pointer Pointer;
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth struct Pointer {
25*37da2899SCharles.Forsyth 	int	x;
26*37da2899SCharles.Forsyth 	int	y;
27*37da2899SCharles.Forsyth 	int	b;
28*37da2899SCharles.Forsyth 	ulong	msec;
29*37da2899SCharles.Forsyth };
30*37da2899SCharles.Forsyth 
31*37da2899SCharles.Forsyth static struct
32*37da2899SCharles.Forsyth {
33*37da2899SCharles.Forsyth 	Pointer	v;
34*37da2899SCharles.Forsyth 	int	modify;
35*37da2899SCharles.Forsyth 	int	lastb;
36*37da2899SCharles.Forsyth 	Rendez	r;
37*37da2899SCharles.Forsyth 	Ref	ref;
38*37da2899SCharles.Forsyth 	QLock	q;
39*37da2899SCharles.Forsyth } mouse;
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth static
42*37da2899SCharles.Forsyth Dirtab pointertab[]={
43*37da2899SCharles.Forsyth 	".",			{Qdir, 0, QTDIR},	0,	0555,
44*37da2899SCharles.Forsyth 	"pointer",		{Qpointer},	0,	0666,
45*37da2899SCharles.Forsyth 	"cursor",		{Qcursor},		0,	0222,
46*37da2899SCharles.Forsyth };
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth enum {
49*37da2899SCharles.Forsyth 	Nevent = 16	/* enough for some */
50*37da2899SCharles.Forsyth };
51*37da2899SCharles.Forsyth 
52*37da2899SCharles.Forsyth static struct {
53*37da2899SCharles.Forsyth 	int	rd;
54*37da2899SCharles.Forsyth 	int	wr;
55*37da2899SCharles.Forsyth 	Pointer	clicks[Nevent];
56*37da2899SCharles.Forsyth 	Rendez r;
57*37da2899SCharles.Forsyth 	int	full;
58*37da2899SCharles.Forsyth 	int	put;
59*37da2899SCharles.Forsyth 	int	get;
60*37da2899SCharles.Forsyth } ptrq;
61*37da2899SCharles.Forsyth 
62*37da2899SCharles.Forsyth /*
63*37da2899SCharles.Forsyth  * called by any source of pointer data
64*37da2899SCharles.Forsyth  */
65*37da2899SCharles.Forsyth void
mousetrack(int b,int x,int y,int isdelta)66*37da2899SCharles.Forsyth mousetrack(int b, int x, int y, int isdelta)
67*37da2899SCharles.Forsyth {
68*37da2899SCharles.Forsyth 	int lastb;
69*37da2899SCharles.Forsyth 	ulong msec;
70*37da2899SCharles.Forsyth 	Pointer e;
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth 	if(isdelta){
73*37da2899SCharles.Forsyth 		x += mouse.v.x;
74*37da2899SCharles.Forsyth 		y += mouse.v.y;
75*37da2899SCharles.Forsyth 	}
76*37da2899SCharles.Forsyth 	msec = osmillisec();
77*37da2899SCharles.Forsyth 	lastb = mouse.v.b;
78*37da2899SCharles.Forsyth 	mouse.v.x = x;
79*37da2899SCharles.Forsyth 	mouse.v.y = y;
80*37da2899SCharles.Forsyth 	mouse.v.b = b;
81*37da2899SCharles.Forsyth 	mouse.v.msec = msec;
82*37da2899SCharles.Forsyth 	if(!ptrq.full && lastb != b){
83*37da2899SCharles.Forsyth 		e = mouse.v;
84*37da2899SCharles.Forsyth 		ptrq.clicks[ptrq.wr] = e;
85*37da2899SCharles.Forsyth 		if(++ptrq.wr >= Nevent)
86*37da2899SCharles.Forsyth 			ptrq.wr = 0;
87*37da2899SCharles.Forsyth 		if(ptrq.wr == ptrq.rd)
88*37da2899SCharles.Forsyth 			ptrq.full = 1;
89*37da2899SCharles.Forsyth 	}
90*37da2899SCharles.Forsyth 	mouse.modify = 1;
91*37da2899SCharles.Forsyth 	ptrq.put++;
92*37da2899SCharles.Forsyth 	Wakeup(&ptrq.r);
93*37da2899SCharles.Forsyth /*	drawactive(1);	*/
94*37da2899SCharles.Forsyth /*	setpointer(x, y); */
95*37da2899SCharles.Forsyth }
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth static int
ptrqnotempty(void * x)98*37da2899SCharles.Forsyth ptrqnotempty(void *x)
99*37da2899SCharles.Forsyth {
100*37da2899SCharles.Forsyth 	USED(x);
101*37da2899SCharles.Forsyth 	return ptrq.full || ptrq.put != ptrq.get;
102*37da2899SCharles.Forsyth }
103*37da2899SCharles.Forsyth 
104*37da2899SCharles.Forsyth static Pointer
mouseconsume(void)105*37da2899SCharles.Forsyth mouseconsume(void)
106*37da2899SCharles.Forsyth {
107*37da2899SCharles.Forsyth 	Pointer e;
108*37da2899SCharles.Forsyth 
109*37da2899SCharles.Forsyth 	Sleep(&ptrq.r, ptrqnotempty, 0);
110*37da2899SCharles.Forsyth 	ptrq.full = 0;
111*37da2899SCharles.Forsyth 	ptrq.get = ptrq.put;
112*37da2899SCharles.Forsyth 	if(ptrq.rd != ptrq.wr){
113*37da2899SCharles.Forsyth 		e = ptrq.clicks[ptrq.rd];
114*37da2899SCharles.Forsyth 		if(++ptrq.rd >= Nevent)
115*37da2899SCharles.Forsyth 			ptrq.rd = 0;
116*37da2899SCharles.Forsyth 	}else
117*37da2899SCharles.Forsyth 		e = mouse.v;
118*37da2899SCharles.Forsyth 	return e;
119*37da2899SCharles.Forsyth }
120*37da2899SCharles.Forsyth 
121*37da2899SCharles.Forsyth Point
mousexy(void)122*37da2899SCharles.Forsyth mousexy(void)
123*37da2899SCharles.Forsyth {
124*37da2899SCharles.Forsyth 	return Pt(mouse.v.x, mouse.v.y);
125*37da2899SCharles.Forsyth }
126*37da2899SCharles.Forsyth 
127*37da2899SCharles.Forsyth 
128*37da2899SCharles.Forsyth static Chan*
pointerattach(char * spec)129*37da2899SCharles.Forsyth pointerattach(char* spec)
130*37da2899SCharles.Forsyth {
131*37da2899SCharles.Forsyth 	return devattach('m', spec);
132*37da2899SCharles.Forsyth }
133*37da2899SCharles.Forsyth 
134*37da2899SCharles.Forsyth static Walkqid*
pointerwalk(Chan * c,Chan * nc,char ** name,int nname)135*37da2899SCharles.Forsyth pointerwalk(Chan *c, Chan *nc, char **name, int nname)
136*37da2899SCharles.Forsyth {
137*37da2899SCharles.Forsyth 	Walkqid *wq;
138*37da2899SCharles.Forsyth 
139*37da2899SCharles.Forsyth 	wq = devwalk(c, nc, name, nname, pointertab, nelem(pointertab), devgen);
140*37da2899SCharles.Forsyth 	if(wq != nil && wq->clone != c && wq->clone != nil && (ulong)c->qid.path == Qpointer)
141*37da2899SCharles.Forsyth 		incref(&mouse.ref);	/* can this happen? */
142*37da2899SCharles.Forsyth 	return wq;
143*37da2899SCharles.Forsyth }
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth static int
pointerstat(Chan * c,uchar * db,int n)146*37da2899SCharles.Forsyth pointerstat(Chan* c, uchar *db, int n)
147*37da2899SCharles.Forsyth {
148*37da2899SCharles.Forsyth 	return devstat(c, db, n, pointertab, nelem(pointertab), devgen);
149*37da2899SCharles.Forsyth }
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth static Chan*
pointeropen(Chan * c,int omode)152*37da2899SCharles.Forsyth pointeropen(Chan* c, int omode)
153*37da2899SCharles.Forsyth {
154*37da2899SCharles.Forsyth 	c = devopen(c, omode, pointertab, nelem(pointertab), devgen);
155*37da2899SCharles.Forsyth 	if((ulong)c->qid.path == Qpointer){
156*37da2899SCharles.Forsyth 		if(waserror()){
157*37da2899SCharles.Forsyth 			c->flag &= ~COPEN;
158*37da2899SCharles.Forsyth 			nexterror();
159*37da2899SCharles.Forsyth 		}
160*37da2899SCharles.Forsyth 		if(!canqlock(&mouse.q))
161*37da2899SCharles.Forsyth 			error(Einuse);
162*37da2899SCharles.Forsyth 		if(incref(&mouse.ref) != 1){
163*37da2899SCharles.Forsyth 			qunlock(&mouse.q);
164*37da2899SCharles.Forsyth 			error(Einuse);
165*37da2899SCharles.Forsyth 		}
166*37da2899SCharles.Forsyth 		cursorenable();
167*37da2899SCharles.Forsyth 		qunlock(&mouse.q);
168*37da2899SCharles.Forsyth 		poperror();
169*37da2899SCharles.Forsyth 	}
170*37da2899SCharles.Forsyth 	return c;
171*37da2899SCharles.Forsyth }
172*37da2899SCharles.Forsyth 
173*37da2899SCharles.Forsyth static void
pointerclose(Chan * c)174*37da2899SCharles.Forsyth pointerclose(Chan* c)
175*37da2899SCharles.Forsyth {
176*37da2899SCharles.Forsyth 	if((c->flag & COPEN) == 0)
177*37da2899SCharles.Forsyth 		return;
178*37da2899SCharles.Forsyth 	switch((ulong)c->qid.path){
179*37da2899SCharles.Forsyth 	case Qpointer:
180*37da2899SCharles.Forsyth 		qlock(&mouse.q);
181*37da2899SCharles.Forsyth 		if(decref(&mouse.ref) == 0){
182*37da2899SCharles.Forsyth 			cursordisable();
183*37da2899SCharles.Forsyth 		}
184*37da2899SCharles.Forsyth 		qunlock(&mouse.q);
185*37da2899SCharles.Forsyth 		break;
186*37da2899SCharles.Forsyth 	}
187*37da2899SCharles.Forsyth }
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth static long
pointerread(Chan * c,void * a,long n,vlong off)190*37da2899SCharles.Forsyth pointerread(Chan* c, void* a, long n, vlong off)
191*37da2899SCharles.Forsyth {
192*37da2899SCharles.Forsyth 	Pointer mt;
193*37da2899SCharles.Forsyth 	char buf[1+4*12+1];
194*37da2899SCharles.Forsyth 	int l;
195*37da2899SCharles.Forsyth 
196*37da2899SCharles.Forsyth 	USED(&off);
197*37da2899SCharles.Forsyth 	switch((ulong)c->qid.path){
198*37da2899SCharles.Forsyth 	case Qdir:
199*37da2899SCharles.Forsyth 		return devdirread(c, a, n, pointertab, nelem(pointertab), devgen);
200*37da2899SCharles.Forsyth 	case Qpointer:
201*37da2899SCharles.Forsyth 		qlock(&mouse.q);
202*37da2899SCharles.Forsyth 		if(waserror()) {
203*37da2899SCharles.Forsyth 			qunlock(&mouse.q);
204*37da2899SCharles.Forsyth 			nexterror();
205*37da2899SCharles.Forsyth 		}
206*37da2899SCharles.Forsyth 		mt = mouseconsume();
207*37da2899SCharles.Forsyth 		poperror();
208*37da2899SCharles.Forsyth 		qunlock(&mouse.q);
209*37da2899SCharles.Forsyth 		l = snprint(buf, sizeof(buf), "m%11d %11d %11d %11lud ", mt.x, mt.y, mt.b, mt.msec);
210*37da2899SCharles.Forsyth 		if(l < n)
211*37da2899SCharles.Forsyth 			n = l;
212*37da2899SCharles.Forsyth 		memmove(a, buf, n);
213*37da2899SCharles.Forsyth 		break;
214*37da2899SCharles.Forsyth 	default:
215*37da2899SCharles.Forsyth 		n=0;
216*37da2899SCharles.Forsyth 		break;
217*37da2899SCharles.Forsyth 	}
218*37da2899SCharles.Forsyth 	return n;
219*37da2899SCharles.Forsyth }
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth static long
pointerwrite(Chan * c,void * va,long n,vlong off)222*37da2899SCharles.Forsyth pointerwrite(Chan* c, void* va, long n, vlong off)
223*37da2899SCharles.Forsyth {
224*37da2899SCharles.Forsyth 	char *a = va;
225*37da2899SCharles.Forsyth 	char buf[128];
226*37da2899SCharles.Forsyth 	int b, x, y;
227*37da2899SCharles.Forsyth 	Drawcursor cur;
228*37da2899SCharles.Forsyth 
229*37da2899SCharles.Forsyth 	USED(&off);
230*37da2899SCharles.Forsyth 	switch((ulong)c->qid.path){
231*37da2899SCharles.Forsyth 	case Qpointer:
232*37da2899SCharles.Forsyth 		if(n > sizeof buf-1)
233*37da2899SCharles.Forsyth 			n = sizeof buf -1;
234*37da2899SCharles.Forsyth 		memmove(buf, va, n);
235*37da2899SCharles.Forsyth 		buf[n] = 0;
236*37da2899SCharles.Forsyth 		x = strtoul(buf+1, &a, 0);
237*37da2899SCharles.Forsyth 		if(*a == 0)
238*37da2899SCharles.Forsyth 			error(Eshort);
239*37da2899SCharles.Forsyth 		y = strtoul(a, &a, 0);
240*37da2899SCharles.Forsyth 		if(*a != 0)
241*37da2899SCharles.Forsyth 			b = strtoul(a, 0, 0);
242*37da2899SCharles.Forsyth 		else
243*37da2899SCharles.Forsyth 			b = mouse.v.b;
244*37da2899SCharles.Forsyth 		/*mousetrack(b, x, y, msec);*/
245*37da2899SCharles.Forsyth 		setpointer(x, y);
246*37da2899SCharles.Forsyth 		USED(b);
247*37da2899SCharles.Forsyth 		break;
248*37da2899SCharles.Forsyth 	case Qcursor:
249*37da2899SCharles.Forsyth 		/* TO DO: perhaps interpret data as an Image */
250*37da2899SCharles.Forsyth 		/*
251*37da2899SCharles.Forsyth 		 *  hotx[4] hoty[4] dx[4] dy[4] clr[dx/8 * dy/2] set[dx/8 * dy/2]
252*37da2899SCharles.Forsyth 		 *  dx must be a multiple of 8; dy must be a multiple of 2.
253*37da2899SCharles.Forsyth 		 */
254*37da2899SCharles.Forsyth 		if(n == 0){
255*37da2899SCharles.Forsyth 			cur.data = nil;
256*37da2899SCharles.Forsyth 			drawcursor(&cur);
257*37da2899SCharles.Forsyth 			break;
258*37da2899SCharles.Forsyth 		}
259*37da2899SCharles.Forsyth 		if(n < 8)
260*37da2899SCharles.Forsyth 			error(Eshort);
261*37da2899SCharles.Forsyth 		cur.hotx = BGLONG((uchar*)va+0*4);
262*37da2899SCharles.Forsyth 		cur.hoty = BGLONG((uchar*)va+1*4);
263*37da2899SCharles.Forsyth 		cur.minx = 0;
264*37da2899SCharles.Forsyth 		cur.miny = 0;
265*37da2899SCharles.Forsyth 		cur.maxx = BGLONG((uchar*)va+2*4);
266*37da2899SCharles.Forsyth 		cur.maxy = BGLONG((uchar*)va+3*4);
267*37da2899SCharles.Forsyth 		if(cur.maxx%8 != 0 || cur.maxy%2 != 0 || n-4*4 != (cur.maxx/8 * cur.maxy))
268*37da2899SCharles.Forsyth 			error(Ebadarg);
269*37da2899SCharles.Forsyth 		cur.data = (uchar*)va + 4*4;
270*37da2899SCharles.Forsyth 		drawcursor(&cur);
271*37da2899SCharles.Forsyth 		break;
272*37da2899SCharles.Forsyth 	default:
273*37da2899SCharles.Forsyth 		error(Ebadusefd);
274*37da2899SCharles.Forsyth 	}
275*37da2899SCharles.Forsyth 	return n;
276*37da2899SCharles.Forsyth }
277*37da2899SCharles.Forsyth 
278*37da2899SCharles.Forsyth Dev pointerdevtab = {
279*37da2899SCharles.Forsyth 	'm',
280*37da2899SCharles.Forsyth 	"pointer",
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth 	devinit,
283*37da2899SCharles.Forsyth 	pointerattach,
284*37da2899SCharles.Forsyth 	pointerwalk,
285*37da2899SCharles.Forsyth 	pointerstat,
286*37da2899SCharles.Forsyth 	pointeropen,
287*37da2899SCharles.Forsyth 	devcreate,
288*37da2899SCharles.Forsyth 	pointerclose,
289*37da2899SCharles.Forsyth 	pointerread,
290*37da2899SCharles.Forsyth 	devbread,
291*37da2899SCharles.Forsyth 	pointerwrite,
292*37da2899SCharles.Forsyth 	devbwrite,
293*37da2899SCharles.Forsyth 	devremove,
294*37da2899SCharles.Forsyth 	devwstat,
295*37da2899SCharles.Forsyth };
296