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 snarffd = -1; 173 static ulong snarfvers; 174 175 void 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 * 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 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