]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vnc/devmouse.c
vncs: shut up used and not set warning
[plan9front.git] / sys / src / cmd / vnc / devmouse.c
1 #include        <u.h>
2 #include        <libc.h>
3 #include        "compat.h"
4 #include        "error.h"
5
6 #define Image   IMAGE
7 #include        <draw.h>
8 #include        <memdraw.h>
9 #include        <cursor.h>
10 #include        "screen.h"
11
12 typedef struct Mouseinfo        Mouseinfo;
13 typedef struct Mousestate       Mousestate;
14
15 struct Mousestate
16 {
17         Point   xy;             /* mouse.xy */
18         int     buttons;        /* mouse.buttons */
19         ulong   counter;        /* increments every update */
20         ulong   msec;           /* time of last event */
21 };
22
23 struct Mouseinfo
24 {
25         Lock;
26         Mousestate;
27         ulong   lastcounter;    /* value when /dev/mouse read */
28         Rendez  r;
29         Ref;
30         int     resize;
31         int     open;
32         Mousestate      queue[16];      /* circular buffer of click events */
33         ulong   ri;             /* read index into queue */
34         ulong   wi;             /* write index into queue */
35 };
36
37 Mouseinfo       mouse;
38 Cursorinfo      cursor;
39 Cursor          curs;
40
41 void    Cursortocursor(Cursor*);
42 int     mousechanged(void*);
43
44 enum{
45         Qdir,
46         Qcursor,
47         Qmouse,
48         Qmousein,
49         Qmousectl,
50 };
51
52 static Dirtab mousedir[]={
53         ".",    {Qdir, 0, QTDIR},       0,                      DMDIR|0555,
54         "cursor",       {Qcursor},      0,                      0666,
55         "mouse",        {Qmouse},       0,                      0666,
56         "mousein",      {Qmousein},     0,                      0222,
57         "mousectl",     {Qmousectl},    0,                      0222,
58 };
59
60 Cursor  arrow = {
61         { -1, -1 },
62         { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
63           0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
64           0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
65           0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
66         },
67         { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
68           0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
69           0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
70           0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
71         },
72 };
73
74 extern Memimage* gscreen;
75 extern void mousewarpnote(Point);
76
77 static void
78 mousereset(void)
79 {
80         curs = arrow;
81         Cursortocursor(&arrow);
82 }
83
84 static void
85 mouseinit(void)
86 {
87         curs = arrow;
88         Cursortocursor(&arrow);
89         cursoron();
90 }
91
92 static Chan*
93 mouseattach(char *spec)
94 {
95         return devattach('m', spec);
96 }
97
98 static Walkqid*
99 mousewalk(Chan *c, Chan *nc, char **name, int nname)
100 {
101         return devwalk(c, nc, name, nname, mousedir, nelem(mousedir), devgen);
102 }
103
104 static int
105 mousestat(Chan *c, uchar *db, int n)
106 {
107         return devstat(c, db, n, mousedir, nelem(mousedir), devgen);
108 }
109
110 static Chan*
111 mouseopen(Chan *c, int omode)
112 {
113         int mode;
114
115         mode = openmode(omode);
116         switch((ulong)c->qid.path){
117         case Qdir:
118                 if(omode != OREAD)
119                         error(Eperm);
120                 break;
121         case Qmousein:
122         case Qmousectl:
123                 error(Egreg);
124                 break;
125         case Qmouse:
126                 if(_tas(&mouse.open) != 0)
127                         error(Einuse);
128                 mouse.lastcounter = mouse.counter;
129                 /* wet floor */
130         case Qcursor:
131                 incref(&mouse);
132         }
133         c->mode = mode;
134         c->flag |= COPEN;
135         c->offset = 0;
136         return c;
137 }
138
139 static void
140 mouseclose(Chan *c)
141 {
142         if((c->qid.type&QTDIR)!=0 || (c->flag&COPEN)==0)
143                 return;
144         switch((ulong)c->qid.path){
145         case Qmouse:
146                 mouse.open = 0;
147                 /* wet floor */
148         case Qcursor:
149                 if(decref(&mouse) != 0)
150                         return;
151                 cursoroff();
152                 curs = arrow;
153                 Cursortocursor(&arrow);
154                 cursoron();
155         }
156 }
157
158
159 static long
160 mouseread(Chan *c, void *va, long n, vlong off)
161 {
162         char buf[1+4*12+1];
163         uchar *p;
164         ulong offset = off;
165         Mousestate m;
166
167         p = va;
168         switch((ulong)c->qid.path){
169         case Qdir:
170                 return devdirread(c, va, n, mousedir, nelem(mousedir), devgen);
171
172         case Qcursor:
173                 if(offset != 0)
174                         return 0;
175                 if(n < 2*4+2*2*16)
176                         error(Eshort);
177                 n = 2*4+2*2*16;
178                 BPLONG(p+0, curs.offset.x);
179                 BPLONG(p+4, curs.offset.y);
180                 memmove(p+8, curs.clr, 2*16);
181                 memmove(p+40, curs.set, 2*16);
182                 return n;
183
184         case Qmouse:
185                 while(mousechanged(0) == 0)
186                         rendsleep(&mouse.r, mousechanged, 0);
187
188                 lock(&mouse);
189                 if(mouse.ri != mouse.wi)
190                         m = mouse.queue[mouse.ri++ % nelem(mouse.queue)];
191                 else
192                         m = mouse.Mousestate;
193                 unlock(&mouse);
194
195                 sprint(buf, "m%11d %11d %11d %11ld ",
196                         m.xy.x, m.xy.y, m.buttons, m.msec);
197
198                 mouse.lastcounter = m.counter;
199                 if(mouse.resize){
200                         mouse.resize = 0;
201                         buf[0] = 'r';
202                 }
203
204                 if(n > 1+4*12)
205                         n = 1+4*12;
206                 memmove(va, buf, n);
207                 return n;
208         }
209         return 0;
210 }
211
212 static long
213 mousewrite(Chan *c, void *va, long n, vlong)
214 {
215         char *p;
216         Point pt;
217         char buf[64];
218
219         p = va;
220         switch((ulong)c->qid.path){
221         case Qdir:
222                 error(Eisdir);
223
224         case Qcursor:
225                 cursoroff();
226                 if(n < 2*4+2*2*16){
227                         curs = arrow;
228                         Cursortocursor(&arrow);
229                 }else{
230                         n = 2*4+2*2*16;
231                         curs.offset.x = BGLONG(p+0);
232                         curs.offset.y = BGLONG(p+4);
233                         memmove(curs.clr, p+8, 2*16);
234                         memmove(curs.set, p+40, 2*16);
235                         Cursortocursor(&curs);
236                 }
237                 cursoron();
238                 return n;
239
240         case Qmouse:
241                 if(n > sizeof buf-1)
242                         n = sizeof buf -1;
243                 memmove(buf, va, n);
244                 buf[n] = 0;
245
246                 pt.x = strtol(buf+1, &p, 0);
247                 if(*p == 0)
248                         error(Eshort);
249                 pt.y = strtol(p, 0, 0);
250                 absmousetrack(pt.x, pt.y, mouse.buttons, nsec()/(1000*1000LL));
251                 mousewarpnote(pt);
252                 return n;
253         }
254
255         error(Egreg);
256         return -1;
257 }
258
259 Dev mousedevtab = {
260         'm',
261         "mouse",
262
263         mousereset,
264         mouseinit,
265         mouseattach,
266         mousewalk,
267         mousestat,
268         mouseopen,
269         devcreate,
270         mouseclose,
271         mouseread,
272         devbread,
273         mousewrite,
274         devbwrite,
275         devremove,
276         devwstat,
277 };
278
279 void
280 Cursortocursor(Cursor *c)
281 {
282         lock(&cursor);
283         memmove(&cursor.Cursor, c, sizeof(Cursor));
284         setcursor(c);
285         unlock(&cursor);
286 }
287
288 void
289 absmousetrack(int x, int y, int b, ulong msec)
290 {
291         int lastb;
292
293         if(gscreen==nil)
294                 return;
295
296         if(x < gscreen->clipr.min.x)
297                 x = gscreen->clipr.min.x;
298         if(x >= gscreen->clipr.max.x)
299                 x = gscreen->clipr.max.x-1;
300         if(y < gscreen->clipr.min.y)
301                 y = gscreen->clipr.min.y;
302         if(y >= gscreen->clipr.max.y)
303                 y = gscreen->clipr.max.y-1;
304
305
306         lock(&mouse);
307         mouse.xy = Pt(x, y);
308         lastb = mouse.buttons;
309         mouse.buttons = b;
310         mouse.msec = msec;
311         mouse.counter++;
312
313         /*
314          * if the queue fills, don't queue any more events until a
315          * reader polls the mouse.
316          */
317         if(b != lastb && (mouse.wi-mouse.ri) < nelem(mouse.queue))
318                 mouse.queue[mouse.wi++ % nelem(mouse.queue)] = mouse.Mousestate;
319         unlock(&mouse);
320
321         rendwakeup(&mouse.r);
322
323         cursoron();
324 }
325
326 int
327 mousechanged(void*)
328 {
329         return mouse.lastcounter != mouse.counter || mouse.resize != 0;
330 }
331
332 Point
333 mousexy(void)
334 {
335         return mouse.xy;
336 }
337
338 /*
339  * notify reader that screen has been resized
340  */
341 void
342 mouseresize(void)
343 {
344         mouse.resize = 1;
345         rendwakeup(&mouse.r);
346 }