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