diff e33798c7e0333e6b8c39be76c7b143834d81b81e uncommitted --- a/sys/man/1/vnc +++ b/sys/man/1/vnc @@ -44,7 +44,7 @@ .PP .B vncv [ -.B -cstv +.B -acstv ] [ .B -e @@ -146,10 +146,13 @@ provides access to remote display .IB host : n \fR. It resizes its window to be the smaller of the -remote frame buffer size and the local screen. +remote frame buffer size and the local screen +when not using the autoscaling option. .PP The options are: .TP +.B -a +autoscale remote frame buffer to local screen window size. .B -c when connecting to 8-bit displays, request .B r4g4b4 @@ -166,7 +169,10 @@ .B corre .B hextile .B rre -.BR raw . +.B raw +.B mousewarp +.B desktopsize +.BR xdesktopsize . The encodings should be given as a single space-separated argument (quoted when using the shell). .TP @@ -199,7 +205,8 @@ .B http://www.uk.research.att.com/vnc .SH BUGS If the remote frame buffer is larger than the local screen, -only the upper left corner can be accessed. +and autoscaling is disabled, only the upper left corner can be accessed. +Autoscaling is only implemented for raw encoding. .PP .I Vncs and --- a/sys/src/cmd/vnc/draw.c +++ b/sys/src/cmd/vnc/draw.c @@ -20,8 +20,18 @@ static int vpixb; static int pixb; static void (*pixcp)(uchar*, uchar*); +static double scalex; +static double scaley; static void +vncsetscale(Vnc *v) +{ + scalex = (v->dim.max.x - v->dim.min.x) / (double)(screen->r.max.x - screen->r.min.x); + scaley = (v->dim.max.y - v->dim.min.y) / (double)(screen->r.max.y - screen->r.min.y); + if(verbose > 1) fprint(2, "scaling %fx%f\n", scalex, scaley); +} + +static void vncsetdim(Vnc *v, Rectangle dim) { v->dim = rectsubpt(dim, dim.min); @@ -79,7 +89,7 @@ lockdisplay(display); flushimage(display, 1); - r = rectsubpt(screen->r, screen->r.min); + r = autoscale ? v->dim : rectsubpt(screen->r, screen->r.min); unlockdisplay(display); vnclock(v); if(incremental == 0 && (v->canresize&2)!=0 && !eqrect(r, v->dim)){ @@ -94,7 +104,7 @@ } else rectclip(&r, v->dim); vncwrchar(v, MFrameReq); - vncwrchar(v, incremental); + vncwrchar(v, autoscale ? 0 : incremental); vncwrrect(v, r); vncflush(v); vncunlock(v); @@ -167,7 +177,8 @@ static void loadbuf(Vnc *v, Rectangle r, int stride) { - int off, y; + int off; + double x, y, endy; if(cvtpixels){ y = r.min.y; @@ -185,6 +196,12 @@ off += stride; } } + if(autoscale){ + endy = off/(double)stride; + for(y = 0; y < endy; y += scaley) + for(x = 0; x < stride; x+=scalex) + memmove(&pixbuf[(int)(y/scaley)*stride+(int)(x/scalex)/pixb*pixb], &pixbuf[(int)(y)*stride+(int)(x/pixb)*pixb], pixb); + } } static Rectangle @@ -286,12 +303,15 @@ if(!rectinrect(r, v->dim)) sysfatal("bad rectangle from server: %R not in %R", r, v->dim); - maxr = rectsubpt(r, r.min); + maxr = autoscale ? rectsubpt(v->dim, v->dim.min) : rectsubpt( r, r.min ); + maxr.max.x = Dx(maxr); maxr.min.x = 0; + maxr.max.y = Dy(maxr); maxr.min.y = 0; stride = maxr.max.x * pixb; + if(verbose > 2) fprint(2, "maxr.max.x %d; maxr.max.y %d; maxr.min.x %d; maxr.min.y %d, pixb: %d, stride: %ld, type: %lx\n", maxr.max.x, maxr.max.y, maxr.min.x, maxr.min.y, pixb, stride, type); switch(type){ default: - sysfatal("bad rectangle encoding from server"); + sysfatal("bad rectangle encoding from server: %lx", type); break; case EncRaw: loadbuf(v, maxr, stride); @@ -399,6 +419,8 @@ sysfatal("bad message from server: %x", type); break; case MFrameUpdate: + if(autoscale) + vncsetscale(v); vncrdchar(v); n = vncrdshort(v); while(n-- > 0) --- a/sys/src/cmd/vnc/vncv.c +++ b/sys/src/cmd/vnc/vncv.c @@ -4,6 +4,7 @@ char* charset = "utf-8"; char* encodings = "copyrect hextile corre rre raw mousewarp desktopsize xdesktopsize"; +int autoscale; int bpp12; int shared; int verbose; @@ -74,7 +75,7 @@ void usage(void) { - fprint(2, "usage: vncv [-e encodings] [-k keypattern] [-l charset] [-csv] host[:n]\n"); + fprint(2, "usage: vncv [-acstv] [-e encodings] [-l charset] [-k keypattern] host[:n]\n"); exits("usage"); } @@ -87,6 +88,9 @@ keypattern = nil; shared = 0; ARGBEGIN{ + case 'a': + autoscale = 1; + break; case 'c': bpp12 = 1; break; --- a/sys/src/cmd/vnc/vncv.h +++ b/sys/src/cmd/vnc/vncv.h @@ -13,6 +13,7 @@ /* vncv.c */ extern char *charset; extern char *encodings; +extern int autoscale; extern int bpp12; extern Vnc* vnc; extern int mousefd; --- a/sys/src/cmd/vnc/wsys.c +++ b/sys/src/cmd/vnc/wsys.c @@ -48,7 +48,7 @@ if(getwindow(display, Refnone) < 0) sysfatal("internal error: can't get the window image"); if((vnc->canresize&2) == 0) - adjustwin(vnc, first); + adjustwin(vnc, !autoscale && first); unlockdisplay(display); requestupdate(vnc, 0); } @@ -154,8 +154,12 @@ if(*start == 'm'){ m.xy.x = atoi(start+1); m.xy.y = atoi(start+1+12); - m.buttons = atoi(start+1+2*12) & 0x1F; m.xy = subpt(m.xy, screen->r.min); + if(autoscale){ + m.xy.x *= (v->dim.max.x - v->dim.min.x) / (double)(screen->r.max.x - screen->r.min.x); + m.xy.y *= (v->dim.max.y - v->dim.min.y) / (double)(screen->r.max.y - screen->r.min.y); + } + m.buttons = atoi(start+1+2*12) & 0x1F; if(ptinrect(m.xy, v->dim)){ mouseevent(v, m); /* send wheel button *release* */