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