summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Böhm <igor@9lab.org>2024-01-08 01:27:43 +0000
committerIgor Böhm <igor@9lab.org>2024-01-08 01:27:43 +0000
commit4d69aacea023546a7150d92e147e531c38de822f (patch)
tree7f5e33b1944611755f47f263e0bfbf35b2130e03
parent1efad2d8fb4fc964198e30b483492f0465627f7d (diff)
vncv: implement autoscaling via -a flag (thanks unobe)
Add vncv option '-a' to autoscale remote frame buffer to local screen window size; useful when remote frame buffer is larger than the local screen. If the remote frame buffer is larger than the local screen, and autoscaling is disabled, only the upper left corner is accessible.
-rw-r--r--sys/man/1/vnc16
-rw-r--r--sys/src/cmd/vnc/draw.c32
-rw-r--r--sys/src/cmd/vnc/vncv.c6
-rw-r--r--sys/src/cmd/vnc/vncv.h1
-rw-r--r--sys/src/cmd/vnc/wsys.c8
5 files changed, 51 insertions, 12 deletions
diff --git a/sys/man/1/vnc b/sys/man/1/vnc
index 7ba8b1b49..5942eaa93 100644
--- a/sys/man/1/vnc
+++ b/sys/man/1/vnc
@@ -44,7 +44,7 @@ vncs, vncv \- remote frame buffer server and viewer for Virtual Network Computin
.PP
.B vncv
[
-.B -cstv
+.B -acstv
]
[
.B -e
@@ -146,10 +146,14 @@ kills the VNC server running on display
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.
+.TP
.B -c
when connecting to 8-bit displays, request
.B r4g4b4
@@ -166,7 +170,10 @@ The default (and full) set is
.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 +206,8 @@ print verbose output to standard error.
.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
diff --git a/sys/src/cmd/vnc/draw.c b/sys/src/cmd/vnc/draw.c
index 61b2c1760..ed4a7f169 100644
--- a/sys/src/cmd/vnc/draw.c
+++ b/sys/src/cmd/vnc/draw.c
@@ -20,6 +20,16 @@ static uchar *linebuf;
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)
@@ -79,7 +89,7 @@ requestupdate(Vnc *v, int incremental)
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 @@ requestupdate(Vnc *v, int incremental)
} 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 @@ fillrect(Rectangle r, int stride, uchar *color)
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 @@ loadbuf(Vnc *v, Rectangle r, int stride)
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 @@ dorectangle(Vnc *v)
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 @@ readfromserver(Vnc *v)
sysfatal("bad message from server: %x", type);
break;
case MFrameUpdate:
+ if(autoscale)
+ vncsetscale(v);
vncrdchar(v);
n = vncrdshort(v);
while(n-- > 0)
diff --git a/sys/src/cmd/vnc/vncv.c b/sys/src/cmd/vnc/vncv.c
index 8633f9a2d..cea20a5bd 100644
--- 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 @@ vnchungup(Vnc*)
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 @@ main(int argc, char **argv)
keypattern = nil;
shared = 0;
ARGBEGIN{
+ case 'a':
+ autoscale = 1;
+ break;
case 'c':
bpp12 = 1;
break;
diff --git a/sys/src/cmd/vnc/vncv.h b/sys/src/cmd/vnc/vncv.h
index 564ef0b9c..e979b94a2 100644
--- a/sys/src/cmd/vnc/vncv.h
+++ b/sys/src/cmd/vnc/vncv.h
@@ -13,6 +13,7 @@ extern uchar zero[];
/* vncv.c */
extern char *charset;
extern char *encodings;
+extern int autoscale;
extern int bpp12;
extern Vnc* vnc;
extern int mousefd;
diff --git a/sys/src/cmd/vnc/wsys.c b/sys/src/cmd/vnc/wsys.c
index d4b13b655..984f91f6b 100644
--- a/sys/src/cmd/vnc/wsys.c
+++ b/sys/src/cmd/vnc/wsys.c
@@ -48,7 +48,7 @@ resized(int first)
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 @@ readmouse(Vnc *v)
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* */