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