]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/vnc/wsys.c
vncv: pick an auth type that we support
[plan9front.git] / sys / src / cmd / vnc / wsys.c
1 #include "vnc.h"
2 #include "vncv.h"
3 #include <cursor.h>
4
5 typedef struct Cursor Cursor;
6
7 typedef struct Mouse Mouse;
8 struct Mouse {
9         int buttons;
10         Point xy;
11 };
12
13 void
14 adjustwin(Vnc *v, int force)
15 {
16         int fd;
17         Point d;
18
19         if(force)
20                 d = v->dim.max;
21         else {
22                 /*
23                  * limit the window to at most the vnc server's size
24                  */
25                 d = subpt(screen->r.max, screen->r.min);
26                 if(d.x > v->dim.max.x){
27                         d.x = v->dim.max.x;
28                         force = 1;
29                 }
30                 if(d.y > v->dim.max.y){
31                         d.y = v->dim.max.y;
32                         force = 1;
33                 }
34         }
35         if(force) {
36                 fd = open("/dev/wctl", OWRITE);
37                 if(fd >= 0){
38                         fprint(fd, "resize -dx %d -dy %d", d.x+2*Borderwidth, d.y+2*Borderwidth);
39                         close(fd);
40                 }
41         }
42 }
43
44 static void
45 resized(int first)
46 {
47         lockdisplay(display);
48         if(getwindow(display, Refnone) < 0)
49                 sysfatal("internal error: can't get the window image");
50         if((vnc->canresize&2) == 0)
51                 adjustwin(vnc, first);
52         unlockdisplay(display);
53         requestupdate(vnc, 0);
54 }
55
56 static Cursor dotcursor = {
57         {-7, -7},
58         {0x00, 0x00,
59          0x00, 0x00,
60          0x00, 0x00,
61          0x00, 0x00, 
62          0x03, 0xc0,
63          0x07, 0xe0,
64          0x0f, 0xf0, 
65          0x0f, 0xf0,
66          0x0f, 0xf0,
67          0x07, 0xe0,
68          0x03, 0xc0,
69          0x00, 0x00, 
70          0x00, 0x00,
71          0x00, 0x00,
72          0x00, 0x00,
73          0x00, 0x00, },
74         {0x00, 0x00,
75          0x00, 0x00,
76          0x00, 0x00,
77          0x00, 0x00, 
78          0x00, 0x00,
79          0x03, 0xc0,
80          0x07, 0xe0, 
81          0x07, 0xe0,
82          0x07, 0xe0,
83          0x03, 0xc0,
84          0x00, 0x00,
85          0x00, 0x00, 
86          0x00, 0x00,
87          0x00, 0x00,
88          0x00, 0x00,
89          0x00, 0x00, }
90 };
91
92 static void
93 mouseevent(Vnc *v, Mouse m)
94 {
95         vnclock(v);
96         vncwrchar(v, MMouse);
97         vncwrchar(v, m.buttons);
98         vncwrpoint(v, m.xy);
99         vncflush(v);
100         vncunlock(v);
101 }
102
103 void
104 mousewarp(Point pt)
105 {
106         pt = addpt(pt, screen->r.min);
107         if(fprint(mousefd, "m%d %d", pt.x, pt.y) < 0)
108                 fprint(2, "mousefd write: %r\n");
109 }
110
111 void
112 initmouse(void)
113 {
114         char buf[1024];
115
116         snprint(buf, sizeof buf, "%s/mouse", display->devdir);
117         if((mousefd = open(buf, ORDWR)) < 0)
118                 sysfatal("open %s: %r", buf);
119 }
120
121 enum {
122         EventSize = 1+4*12
123 };
124 void
125 readmouse(Vnc *v)
126 {
127         int cursorfd, len, n;
128         char buf[10*EventSize], *start, *end;
129         uchar curs[2*4+2*2*16];
130         Cursor *cs;
131         Mouse m;
132
133         cs = &dotcursor;
134
135         snprint(buf, sizeof buf, "%s/cursor", display->devdir);
136         if((cursorfd = open(buf, OWRITE)) < 0)
137                 sysfatal("open %s: %r", buf);
138
139         BPLONG(curs+0*4, cs->offset.x);
140         BPLONG(curs+1*4, cs->offset.y);
141         memmove(curs+2*4, cs->clr, 2*2*16);
142         write(cursorfd, curs, sizeof curs);
143
144         resized(1);
145         start = end = buf;
146         len = 0;
147         for(;;){
148                 if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0)
149                         sysfatal("read mouse failed");
150
151                 len += n;
152                 end += n;
153                 while(len >= EventSize){
154                         if(*start == 'm'){
155                                 m.xy.x = atoi(start+1);
156                                 m.xy.y = atoi(start+1+12);
157                                 m.buttons = atoi(start+1+2*12) & 0x1F;
158                                 m.xy = subpt(m.xy, screen->r.min);
159                                 if(ptinrect(m.xy, v->dim)){
160                                         mouseevent(v, m);
161                                         /* send wheel button *release* */ 
162                                         if ((m.buttons & 0x7) != m.buttons) {
163                                                 m.buttons &= 0x7;
164                                                 mouseevent(v, m);
165                                         }
166                                 }
167                         } else
168                                 resized(0);
169                         start += EventSize;
170                         len -= EventSize;
171                 }
172                 if(start - buf > sizeof(buf) - EventSize){
173                         memmove(buf, start, len);
174                         start = buf;
175                         end = start+len;
176                 }
177         }
178 }
179
180 static int
181 tcs(int fd0, int fd1)
182 {
183         int pfd[2];
184
185         if(strcmp(charset, "utf-8") == 0)
186                 goto Dup;
187         if(pipe(pfd) < 0)
188                 goto Dup;
189         switch(rfork(RFPROC|RFFDG|RFMEM)){
190         case -1:
191                 close(pfd[0]);
192                 close(pfd[1]);
193                 goto Dup;
194         case 0:
195                 if(fd0 < 0){
196                         dup(pfd[0], 0);
197                         dup(fd1, 1);
198                         close(fd1);     
199                 } else {
200                         dup(pfd[0], 1);
201                         dup(fd0, 0);
202                         close(fd0);     
203                 }
204                 close(pfd[0]);
205                 close(pfd[1]);
206                 execl("/bin/tcs", "tcs", fd0 < 0 ? "-f" : "-t", charset, nil);
207                 execl("/bin/cat", "cat", nil);
208                 _exits(0);
209         }
210         close(pfd[0]);
211         return pfd[1];
212 Dup:
213         return dup(fd0 < 0 ? fd1 : fd0, -1);
214 }
215
216 static int snarffd = -1;
217 static ulong snarfvers;
218
219 static int
220 gotsnarf(void)
221 {
222         Dir *dir;
223         int ret;
224
225         if(snarffd < 0 || (dir = dirfstat(snarffd)) == nil)
226                 return 0;
227
228         ret = dir->qid.vers != snarfvers;
229         snarfvers = dir->qid.vers;
230         free(dir);
231
232         return ret;
233 }
234
235 void 
236 writesnarf(Vnc *v, long n)
237 {
238         uchar buf[8192];
239         int fd, sfd;
240         long m;
241
242         vnclock(v);
243         fd = -1;
244         if((sfd = create("/dev/snarf", OWRITE, 0666)) >= 0){
245                 fd = tcs(-1, sfd);
246                 close(sfd);
247         }
248         if(fd < 0)
249                 vncgobble(v, n);
250         else {
251                 while(n > 0){
252                         m = n;
253                         if(m > sizeof(buf))
254                                 m = sizeof(buf);
255                         vncrdbytes(v, buf, m);
256                         n -= m;
257                         write(fd, buf, m);
258                 }
259                 close(fd);
260                 waitpid();
261         }
262         gotsnarf();
263         vncunlock(v);
264 }
265
266 char *
267 getsnarf(int *sz)
268 {
269         char *snarf, *p;
270         int fd, n, c;
271
272         *sz =0;
273         n = 8192;
274         p = snarf = malloc(n);
275
276         seek(snarffd, 0, 0);
277         if((fd = tcs(snarffd, -1)) >= 0){
278                 while((c = read(fd, p, n)) > 0){
279                         p += c;
280                         n -= c;
281                         *sz += c;
282                         if (n == 0){
283                                 snarf = realloc(snarf, *sz + 8192);
284                                 p = snarf + *sz;
285                                 n = 8192;
286                         }
287                 }
288                 close(fd);
289                 waitpid();
290         }
291         return snarf;
292 }
293
294 void
295 checksnarf(Vnc *v)
296 {
297         char *snarf;
298         int len;
299
300         if(snarffd < 0){
301                 snarffd = open("/dev/snarf", OREAD);
302                 if(snarffd < 0)
303                         sysfatal("can't open /dev/snarf: %r");
304         }
305
306         for(;;){
307                 sleep(1000);
308
309                 vnclock(v);
310                 if(gotsnarf()){
311                         snarf = getsnarf(&len);
312
313                         vncwrchar(v, MCCut);
314                         vncwrbytes(v, "pad", 3);
315                         vncwrlong(v, len);
316                         vncwrbytes(v, snarf, len);
317                         vncflush(v);
318
319                         free(snarf);
320                 }
321                 vncunlock(v);
322         }
323 }