1*9a747e4fSDavid du Colombier #include "vnc.h" 2*9a747e4fSDavid du Colombier #include "vncv.h" 3*9a747e4fSDavid du Colombier #include <cursor.h> 4*9a747e4fSDavid du Colombier 5*9a747e4fSDavid du Colombier typedef struct Cursor Cursor; 6*9a747e4fSDavid du Colombier 7*9a747e4fSDavid du Colombier typedef struct Mouse Mouse; 8*9a747e4fSDavid du Colombier struct Mouse { 9*9a747e4fSDavid du Colombier int buttons; 10*9a747e4fSDavid du Colombier Point xy; 11*9a747e4fSDavid du Colombier }; 12*9a747e4fSDavid du Colombier 13*9a747e4fSDavid du Colombier static void 14*9a747e4fSDavid du Colombier resize(Vnc *v, int first) 15*9a747e4fSDavid du Colombier { 16*9a747e4fSDavid du Colombier int fd; 17*9a747e4fSDavid du Colombier Point d; 18*9a747e4fSDavid du Colombier 19*9a747e4fSDavid du Colombier d = addpt(v->dim, Pt(2*Borderwidth, 2*Borderwidth)); 20*9a747e4fSDavid du Colombier lockdisplay(display); 21*9a747e4fSDavid du Colombier 22*9a747e4fSDavid du Colombier if(getwindow(display, Refnone) < 0) 23*9a747e4fSDavid du Colombier sysfatal("internal error: can't get the window image"); 24*9a747e4fSDavid du Colombier 25*9a747e4fSDavid du Colombier /* 26*9a747e4fSDavid du Colombier * limit the window to at most the vnc server's size 27*9a747e4fSDavid du Colombier */ 28*9a747e4fSDavid du Colombier if(first || d.x < Dx(screen->r) || d.y < Dy(screen->r)){ 29*9a747e4fSDavid du Colombier fd = open("/dev/wctl", OWRITE); 30*9a747e4fSDavid du Colombier if(fd >= 0){ 31*9a747e4fSDavid du Colombier fprint(fd, "resize -dx %d -dy %d", d.x, d.y); 32*9a747e4fSDavid du Colombier close(fd); 33*9a747e4fSDavid du Colombier } 34*9a747e4fSDavid du Colombier } 35*9a747e4fSDavid du Colombier unlockdisplay(display); 36*9a747e4fSDavid du Colombier } 37*9a747e4fSDavid du Colombier 38*9a747e4fSDavid du Colombier static void 39*9a747e4fSDavid du Colombier eresized(void) 40*9a747e4fSDavid du Colombier { 41*9a747e4fSDavid du Colombier resize(vnc, 0); 42*9a747e4fSDavid du Colombier 43*9a747e4fSDavid du Colombier requestupdate(vnc, 0); 44*9a747e4fSDavid du Colombier } 45*9a747e4fSDavid du Colombier 46*9a747e4fSDavid du Colombier static Cursor dotcursor = { 47*9a747e4fSDavid du Colombier {-7, -7}, 48*9a747e4fSDavid du Colombier {0x00, 0x00, 49*9a747e4fSDavid du Colombier 0x00, 0x00, 50*9a747e4fSDavid du Colombier 0x00, 0x00, 51*9a747e4fSDavid du Colombier 0x00, 0x00, 52*9a747e4fSDavid du Colombier 0x03, 0xc0, 53*9a747e4fSDavid du Colombier 0x07, 0xe0, 54*9a747e4fSDavid du Colombier 0x0f, 0xf0, 55*9a747e4fSDavid du Colombier 0x0f, 0xf0, 56*9a747e4fSDavid du Colombier 0x0f, 0xf0, 57*9a747e4fSDavid du Colombier 0x07, 0xe0, 58*9a747e4fSDavid du Colombier 0x03, 0xc0, 59*9a747e4fSDavid du Colombier 0x00, 0x00, 60*9a747e4fSDavid du Colombier 0x00, 0x00, 61*9a747e4fSDavid du Colombier 0x00, 0x00, 62*9a747e4fSDavid du Colombier 0x00, 0x00, 63*9a747e4fSDavid du Colombier 0x00, 0x00, }, 64*9a747e4fSDavid du Colombier {0x00, 0x00, 65*9a747e4fSDavid du Colombier 0x00, 0x00, 66*9a747e4fSDavid du Colombier 0x00, 0x00, 67*9a747e4fSDavid du Colombier 0x00, 0x00, 68*9a747e4fSDavid du Colombier 0x00, 0x00, 69*9a747e4fSDavid du Colombier 0x03, 0xc0, 70*9a747e4fSDavid du Colombier 0x07, 0xe0, 71*9a747e4fSDavid du Colombier 0x07, 0xe0, 72*9a747e4fSDavid du Colombier 0x07, 0xe0, 73*9a747e4fSDavid du Colombier 0x03, 0xc0, 74*9a747e4fSDavid du Colombier 0x00, 0x00, 75*9a747e4fSDavid du Colombier 0x00, 0x00, 76*9a747e4fSDavid du Colombier 0x00, 0x00, 77*9a747e4fSDavid du Colombier 0x00, 0x00, 78*9a747e4fSDavid du Colombier 0x00, 0x00, 79*9a747e4fSDavid du Colombier 0x00, 0x00, } 80*9a747e4fSDavid du Colombier }; 81*9a747e4fSDavid du Colombier 82*9a747e4fSDavid du Colombier static void 83*9a747e4fSDavid du Colombier mouseevent(Vnc *v, Mouse m) 84*9a747e4fSDavid du Colombier { 85*9a747e4fSDavid du Colombier vnclock(v); 86*9a747e4fSDavid du Colombier vncwrchar(v, MMouse); 87*9a747e4fSDavid du Colombier vncwrchar(v, m.buttons); 88*9a747e4fSDavid du Colombier vncwrpoint(v, m.xy); 89*9a747e4fSDavid du Colombier vncflush(v); 90*9a747e4fSDavid du Colombier vncunlock(v); 91*9a747e4fSDavid du Colombier } 92*9a747e4fSDavid du Colombier 93*9a747e4fSDavid du Colombier void mousewarp(Point pt) 94*9a747e4fSDavid du Colombier { 95*9a747e4fSDavid du Colombier char buf[49]; 96*9a747e4fSDavid du Colombier 97*9a747e4fSDavid du Colombier pt = addpt(pt, screen->r.min); 98*9a747e4fSDavid du Colombier snprint(buf, sizeof buf, "m%11d %11d ", pt.x, pt.y); 99*9a747e4fSDavid du Colombier write(mousefd, buf, 25); 100*9a747e4fSDavid du Colombier } 101*9a747e4fSDavid du Colombier 102*9a747e4fSDavid du Colombier void initmouse(void) 103*9a747e4fSDavid du Colombier { 104*9a747e4fSDavid du Colombier char buf[1024]; 105*9a747e4fSDavid du Colombier 106*9a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%s/mouse", display->devdir); 107*9a747e4fSDavid du Colombier if((mousefd = open(buf, ORDWR)) < 0) 108*9a747e4fSDavid du Colombier sysfatal("open %s: %r", buf); 109*9a747e4fSDavid du Colombier } 110*9a747e4fSDavid du Colombier 111*9a747e4fSDavid du Colombier enum { 112*9a747e4fSDavid du Colombier EventSize = 1+4*12 113*9a747e4fSDavid du Colombier }; 114*9a747e4fSDavid du Colombier void 115*9a747e4fSDavid du Colombier readmouse(Vnc *v) 116*9a747e4fSDavid du Colombier { 117*9a747e4fSDavid du Colombier int cursorfd, len, n; 118*9a747e4fSDavid du Colombier char buf[10*EventSize], *start, *end; 119*9a747e4fSDavid du Colombier uchar curs[2*4+2*2*16]; 120*9a747e4fSDavid du Colombier Cursor *cs; 121*9a747e4fSDavid du Colombier Mouse m; 122*9a747e4fSDavid du Colombier 123*9a747e4fSDavid du Colombier cs = &dotcursor; 124*9a747e4fSDavid du Colombier 125*9a747e4fSDavid du Colombier snprint(buf, sizeof buf, "%s/cursor", display->devdir); 126*9a747e4fSDavid du Colombier if((cursorfd = open(buf, OWRITE)) < 0) 127*9a747e4fSDavid du Colombier sysfatal("open %s: %r", buf); 128*9a747e4fSDavid du Colombier 129*9a747e4fSDavid du Colombier BPLONG(curs+0*4, cs->offset.x); 130*9a747e4fSDavid du Colombier BPLONG(curs+1*4, cs->offset.y); 131*9a747e4fSDavid du Colombier memmove(curs+2*4, cs->clr, 2*2*16); 132*9a747e4fSDavid du Colombier write(cursorfd, curs, sizeof curs); 133*9a747e4fSDavid du Colombier 134*9a747e4fSDavid du Colombier resize(v, 1); 135*9a747e4fSDavid du Colombier requestupdate(vnc, 0); 136*9a747e4fSDavid du Colombier start = end = buf; 137*9a747e4fSDavid du Colombier len = 0; 138*9a747e4fSDavid du Colombier for(;;) { 139*9a747e4fSDavid du Colombier if((n = read(mousefd, end, sizeof(buf) - (end - buf))) < 0) 140*9a747e4fSDavid du Colombier sysfatal("read mouse failed"); 141*9a747e4fSDavid du Colombier 142*9a747e4fSDavid du Colombier len += n; 143*9a747e4fSDavid du Colombier end += n; 144*9a747e4fSDavid du Colombier while(len >= EventSize) { 145*9a747e4fSDavid du Colombier if(*start == 'm') { 146*9a747e4fSDavid du Colombier m.xy.x = atoi(start+1); 147*9a747e4fSDavid du Colombier m.xy.y = atoi(start+1+12); 148*9a747e4fSDavid du Colombier m.buttons = atoi(start+1+2*12) & 7; 149*9a747e4fSDavid du Colombier m.xy = subpt(m.xy, screen->r.min); 150*9a747e4fSDavid du Colombier if(ptinrect(m.xy, Rpt(ZP, v->dim))) 151*9a747e4fSDavid du Colombier mouseevent(v, m); 152*9a747e4fSDavid du Colombier } else 153*9a747e4fSDavid du Colombier eresized(); 154*9a747e4fSDavid du Colombier 155*9a747e4fSDavid du Colombier start += EventSize; 156*9a747e4fSDavid du Colombier len -= EventSize; 157*9a747e4fSDavid du Colombier } 158*9a747e4fSDavid du Colombier if(start - buf > sizeof(buf) - EventSize) { 159*9a747e4fSDavid du Colombier memmove(buf, start, len); 160*9a747e4fSDavid du Colombier start = buf; 161*9a747e4fSDavid du Colombier end = start+len; 162*9a747e4fSDavid du Colombier } 163*9a747e4fSDavid du Colombier } 164*9a747e4fSDavid du Colombier } 165*9a747e4fSDavid du Colombier 166*9a747e4fSDavid du Colombier static int snarffd = -1; 167*9a747e4fSDavid du Colombier static ulong snarf_vers; 168*9a747e4fSDavid du Colombier 169*9a747e4fSDavid du Colombier void 170*9a747e4fSDavid du Colombier writesnarf(Vnc *v, long n) 171*9a747e4fSDavid du Colombier { 172*9a747e4fSDavid du Colombier uchar buf[8192]; 173*9a747e4fSDavid du Colombier long m; 174*9a747e4fSDavid du Colombier Biobuf * fd; 175*9a747e4fSDavid du Colombier 176*9a747e4fSDavid du Colombier if( (fd = Bopen("/dev/snarf", OWRITE)) == nil ) { 177*9a747e4fSDavid du Colombier vncgobble(v, n); 178*9a747e4fSDavid du Colombier return; 179*9a747e4fSDavid du Colombier } 180*9a747e4fSDavid du Colombier 181*9a747e4fSDavid du Colombier while(n > 0) { 182*9a747e4fSDavid du Colombier m = n; 183*9a747e4fSDavid du Colombier if(m > sizeof(buf)) 184*9a747e4fSDavid du Colombier m = sizeof(buf); 185*9a747e4fSDavid du Colombier vncrdbytes(v, buf, m); 186*9a747e4fSDavid du Colombier n -= m; 187*9a747e4fSDavid du Colombier 188*9a747e4fSDavid du Colombier Bwrite(fd, buf, m); 189*9a747e4fSDavid du Colombier } 190*9a747e4fSDavid du Colombier Bterm(fd); 191*9a747e4fSDavid du Colombier snarf_vers++; 192*9a747e4fSDavid du Colombier } 193*9a747e4fSDavid du Colombier 194*9a747e4fSDavid du Colombier char * 195*9a747e4fSDavid du Colombier getsnarf(int * sz) 196*9a747e4fSDavid du Colombier { 197*9a747e4fSDavid du Colombier char * snarf, * p; 198*9a747e4fSDavid du Colombier int n, c; 199*9a747e4fSDavid du Colombier 200*9a747e4fSDavid du Colombier *sz =0; 201*9a747e4fSDavid du Colombier n = 8192; 202*9a747e4fSDavid du Colombier p = snarf = malloc(n); 203*9a747e4fSDavid du Colombier 204*9a747e4fSDavid du Colombier seek(snarffd, 0, 0); 205*9a747e4fSDavid du Colombier while ((c = read(snarffd, p, n)) > 0) { 206*9a747e4fSDavid du Colombier p += c; 207*9a747e4fSDavid du Colombier n -= c; 208*9a747e4fSDavid du Colombier *sz += c; 209*9a747e4fSDavid du Colombier if ( n == 0 ) { 210*9a747e4fSDavid du Colombier snarf = realloc(snarf, *sz + 8192); 211*9a747e4fSDavid du Colombier n = 8192; 212*9a747e4fSDavid du Colombier } 213*9a747e4fSDavid du Colombier } 214*9a747e4fSDavid du Colombier return snarf; 215*9a747e4fSDavid du Colombier } 216*9a747e4fSDavid du Colombier 217*9a747e4fSDavid du Colombier void 218*9a747e4fSDavid du Colombier checksnarf(Vnc *v) 219*9a747e4fSDavid du Colombier { 220*9a747e4fSDavid du Colombier Dir *dir; 221*9a747e4fSDavid du Colombier char *snarf; 222*9a747e4fSDavid du Colombier int len; 223*9a747e4fSDavid du Colombier 224*9a747e4fSDavid du Colombier if(snarffd < 0){ 225*9a747e4fSDavid du Colombier snarffd = open("/dev/snarf", OREAD); 226*9a747e4fSDavid du Colombier if(snarffd < 0) 227*9a747e4fSDavid du Colombier sysfatal("can't open /dev/snarf: %r"); 228*9a747e4fSDavid du Colombier } 229*9a747e4fSDavid du Colombier 230*9a747e4fSDavid du Colombier while(1) { 231*9a747e4fSDavid du Colombier sleep(1000); 232*9a747e4fSDavid du Colombier 233*9a747e4fSDavid du Colombier dir = dirstat("/dev/snarf"); 234*9a747e4fSDavid du Colombier if(dir == nil) /* this happens under old drawterm */ 235*9a747e4fSDavid du Colombier continue; 236*9a747e4fSDavid du Colombier if(dir->qid.vers > snarf_vers) { 237*9a747e4fSDavid du Colombier snarf = getsnarf(&len); 238*9a747e4fSDavid du Colombier 239*9a747e4fSDavid du Colombier vnclock(v); 240*9a747e4fSDavid du Colombier vncwrchar(v, MCCut); 241*9a747e4fSDavid du Colombier vncwrbytes(v, "pad", 3); 242*9a747e4fSDavid du Colombier vncwrlong(v, len); 243*9a747e4fSDavid du Colombier vncwrbytes(v, snarf, len); 244*9a747e4fSDavid du Colombier vncflush(v); 245*9a747e4fSDavid du Colombier vncunlock(v); 246*9a747e4fSDavid du Colombier 247*9a747e4fSDavid du Colombier free(snarf); 248*9a747e4fSDavid du Colombier 249*9a747e4fSDavid du Colombier snarf_vers = dir->qid.vers; 250*9a747e4fSDavid du Colombier } 251*9a747e4fSDavid du Colombier free(dir); 252*9a747e4fSDavid du Colombier } 253*9a747e4fSDavid du Colombier } 254