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
resize(Vnc * v,int first)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
eresized(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
mouseevent(Vnc * v,Mouse m)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
mousewarp(Point pt)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
initmouse(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
readmouse(Vnc * v)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 snarffd = -1;
173 static ulong snarfvers;
174
175 void
writesnarf(Vnc * v,long n)176 writesnarf(Vnc *v, long n)
177 {
178 uchar buf[8192];
179 long m;
180 Biobuf *b;
181
182 if((b = Bopen("/dev/snarf", OWRITE)) == nil){
183 vncgobble(v, n);
184 return;
185 }
186
187 while(n > 0){
188 m = n;
189 if(m > sizeof(buf))
190 m = sizeof(buf);
191 vncrdbytes(v, buf, m);
192 n -= m;
193
194 Bwrite(b, buf, m);
195 }
196 Bterm(b);
197 snarfvers++;
198 }
199
200 char *
getsnarf(int * sz)201 getsnarf(int *sz)
202 {
203 char *snarf, *p;
204 int n, c;
205
206 *sz =0;
207 n = 8192;
208 p = snarf = malloc(n);
209
210 seek(snarffd, 0, 0);
211 while ((c = read(snarffd, p, n)) > 0){
212 p += c;
213 n -= c;
214 *sz += c;
215 if (n == 0){
216 snarf = realloc(snarf, *sz + 8192);
217 n = 8192;
218 }
219 }
220 return snarf;
221 }
222
223 void
checksnarf(Vnc * v)224 checksnarf(Vnc *v)
225 {
226 Dir *dir;
227 char *snarf;
228 int len;
229
230 if(snarffd < 0){
231 snarffd = open("/dev/snarf", OREAD);
232 if(snarffd < 0)
233 sysfatal("can't open /dev/snarf: %r");
234 }
235
236 for(;;){
237 sleep(1000);
238
239 dir = dirstat("/dev/snarf");
240 if(dir == nil) /* this happens under old drawterm */
241 continue;
242 if(dir->qid.vers > snarfvers){
243 snarf = getsnarf(&len);
244
245 vnclock(v);
246 vncwrchar(v, MCCut);
247 vncwrbytes(v, "pad", 3);
248 vncwrlong(v, len);
249 vncwrbytes(v, snarf, len);
250 vncflush(v);
251 vncunlock(v);
252
253 free(snarf);
254
255 snarfvers = dir->qid.vers;
256 }
257 free(dir);
258 }
259 }
260