12 typedef struct Mouseinfo Mouseinfo;
13 typedef struct Mousestate Mousestate;
17 Point xy; /* mouse.xy */
18 int buttons; /* mouse.buttons */
19 ulong counter; /* increments every update */
20 ulong msec; /* time of last event */
28 int track; /* dx & dy updated */
29 int redraw; /* update cursor on screen */
30 ulong lastcounter; /* value when /dev/mouse read */
37 Mousestate queue[16]; /* circular buffer of click events */
38 int ri; /* read index into queue */
39 int wi; /* write index into queue */
40 uchar qfull; /* queue is full */
48 void Cursortocursor(Cursor*);
49 int mousechanged(void*);
50 static void mouseclock(void);
60 static Dirtab mousedir[]={
61 ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
62 "cursor", {Qcursor}, 0, 0666,
63 "mouse", {Qmouse}, 0, 0666,
64 "mousein", {Qmousein}, 0, 0222,
65 "mousectl", {Qmousectl}, 0, 0222,
68 static uchar buttonmap[8] = {
69 0, 1, 2, 3, 4, 5, 6, 7,
73 extern Memimage* gscreen;
74 extern void mousewarpnote(Point);
80 Cursortocursor(&arrow);
90 mouseattach(char *spec)
92 return devattach('m', spec);
96 mousewalk(Chan *c, Chan *nc, char **name, int nname)
100 wq = devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
101 if(wq != nil && wq->clone != c && (wq->clone->qid.type&QTDIR)==0)
107 mousestat(Chan *c, uchar *db, int n)
109 return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
113 mouseopen(Chan *c, int omode)
115 switch((ulong)c->qid.path){
132 error(Egreg); /* dummy */
137 c->mode = openmode(omode);
144 mousecreate(Chan*, char*, int, ulong)
152 if((c->qid.type&QTDIR)==0 && (c->flag&COPEN)){
154 if(c->qid.path == Qmouse)
156 if(--mouse.ref == 0){
159 Cursortocursor(&arrow);
168 mouseread(Chan *c, void *va, long n, vlong off)
172 static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };
178 switch((ulong)c->qid.path){
180 return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
189 BPLONG(p+0, curs.offset.x);
190 BPLONG(p+4, curs.offset.y);
191 memmove(p+8, curs.clr, 2*16);
192 memmove(p+40, curs.set, 2*16);
197 while(mousechanged(0) == 0)
198 rendsleep(&mouse.r, mousechanged, 0);
203 * No lock of the indicies is necessary here, because ri is only
204 * updated by us, and there is only one mouse reader
205 * at a time. I suppose that more than one process
206 * could try to read the fd at one time, but such behavior
207 * is degenerate and already violates the calling
208 * conventions for sleep above.
210 if(mouse.ri != mouse.wi){
211 m = mouse.queue[mouse.ri];
212 if(++mouse.ri == nelem(mouse.queue))
217 m = mouse.Mousestate;
221 b = buttonmap[m.buttons&7];
222 /* put buttons 4 and 5 back in */
223 b |= m.buttons & (3<<3);
224 sprint(buf, "m%11d %11d %11d %11lud",
228 mouse.lastcounter = m.counter;
238 setbuttonmap(char* map)
240 int i, x, one, two, three;
242 one = two = three = 0;
243 for(i = 0; i < 3; i++){
251 else if(map[i] == '2'){
256 else if(map[i] == '3'){
267 memset(buttonmap, 0, 8);
268 for(i = 0; i < 8; i++){
281 mousewrite(Chan *c, void *va, long n, vlong)
288 switch((ulong)c->qid.path){
296 Cursortocursor(&arrow);
299 curs.offset.x = BGLONG(p+0);
300 curs.offset.y = BGLONG(p+4);
301 memmove(curs.clr, p+8, 2*16);
302 memmove(curs.set, p+40, 2*16);
303 Cursortocursor(&curs);
318 pt.x = strtoul(buf+1, &p, 0);
321 pt.y = strtoul(p, 0, 0);
323 if(ptinrect(pt, gscreen->r)){
324 mousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
356 Cursortocursor(Cursor *c)
359 memmove(&cursor.Cursor, c, sizeof(Cursor));
380 x = 6 + (mouse.acceleration>>2);
383 x = 9 + (mouse.acceleration>>1);
399 mouse.redraw = cursoron(0);
405 * called at interrupt level to update the structure and
406 * awaken any waiting procs.
409 mousetrack(int x, int y, int b, int msec)
413 lastb = mouse.buttons;
421 * if the queue fills, we discard the entire queue and don't
422 * queue any more events until a reader polls the mouse.
424 if(!mouse.qfull && lastb != b){ /* add to ring */
425 mouse.queue[mouse.wi] = mouse.Mousestate;
426 if(++mouse.wi == nelem(mouse.queue))
428 if(mouse.wi == mouse.ri)
431 rendwakeup(&mouse.r);
438 return mouse.lastcounter != mouse.counter;
448 mouseaccelerate(int x)
450 mouse.acceleration = x;
451 if(mouse.acceleration < 3)
454 mouse.maxacc = mouse.acceleration;