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