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