9front - general discussion about 9front
 help / color / mirror / Atom feed
* [9front] [PATCH] vncv: implement autoscaling with -a flag
@ 2023-09-30  1:29 Romano
  2024-01-02  7:42 ` mkf9
  2024-01-03  0:37 ` igor
  0 siblings, 2 replies; 4+ messages in thread
From: Romano @ 2023-09-30  1:29 UTC (permalink / raw)
  To: 9front


for large remote framebuffers, only the upper left-hand corner
of the screen is ever visible. Autoscaling, while slow, at least
makes all the screen visible. There is a noticeable lag while the
scaling occurs, but vncv as-is isn't a paragon of speed. While in
the code, update documentation for this feature.
---
diff a125c800817a8356de8580da78b7d9bd0ef95090 db2177614df64fa9ccf3dae30cdf24df1ce0a0be
--- 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,14 @@
 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 the remote framebuffer to the size of the
+local screen window.
 .B -c
 when connecting to 8-bit displays, request
 .B r4g4b4
@@ -166,7 +170,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
@@ -198,7 +205,7 @@
 .SH "SEE ALSO
 .B http://www.uk.research.att.com/vnc
 .SH BUGS
-If the remote frame buffer is larger than the local screen,
+Autoscaling is only implemented for raw encoding. When not in use, if the remote frame buffer is larger than the local screen then
 only the upper left corner can be accessed.
 .PP
 .I Vncs
--- 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* */ 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9front] [PATCH] vncv: implement autoscaling with -a flag
  2023-09-30  1:29 [9front] [PATCH] vncv: implement autoscaling with -a flag Romano
@ 2024-01-02  7:42 ` mkf9
  2024-01-03  0:37 ` igor
  1 sibling, 0 replies; 4+ messages in thread
From: mkf9 @ 2024-01-02  7:42 UTC (permalink / raw)
  To: 9front

Romano wrote:
> 
> for large remote framebuffers, only the upper left-hand corner
> of the screen is ever visible. Autoscaling, while slow, at least
> makes all the screen visible. There is a noticeable lag while the
> scaling occurs, but vncv as-is isn't a paragon of speed. While in
> the code, update documentation for this feature.
nice. :)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9front] [PATCH] vncv: implement autoscaling with -a flag
  2023-09-30  1:29 [9front] [PATCH] vncv: implement autoscaling with -a flag Romano
  2024-01-02  7:42 ` mkf9
@ 2024-01-03  0:37 ` igor
  2024-01-12  4:24   ` unobe
  1 sibling, 1 reply; 4+ messages in thread
From: igor @ 2024-01-03  0:37 UTC (permalink / raw)
  To: 9front; +Cc: igor

[-- Attachment #1: Type: text/plain, Size: 1006 bytes --]

Quoth Romano <unobe@cpan.org>:
> for large remote framebuffers, only the upper left-hand corner
> of the screen is ever visible. Autoscaling, while slow, at least
> makes all the screen visible. There is a noticeable lag while the
> scaling occurs, but vncv as-is isn't a paragon of speed. While in
> the code, update documentation for this feature.
[…]

Thanks!  I tested it connecting to OSX Sonoma and indeed, with
autoscaling the full screen is visible for large remote frame buffers.

Without autoscaling only the upper left-hand corner is visible.

Apart from some tweaks to your man page modifications (see attached
patch) the diff looks good to me.

With the option to enable autoscaling the task of reducing the
resolution on the remote machine in case it is too large for the local
window is much simplified.

Unless there is any objection I would like to merge the attached patch
aimed at improving usability of vncv by the end of this week.

Please let me know if you disagree.

Cheers,
Igor

[-- Attachment #2: vncv-autoscale.patch --]
[-- Type: text/plain, Size: 5327 bytes --]

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* */ 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9front] [PATCH] vncv: implement autoscaling with -a flag
  2024-01-03  0:37 ` igor
@ 2024-01-12  4:24   ` unobe
  0 siblings, 0 replies; 4+ messages in thread
From: unobe @ 2024-01-12  4:24 UTC (permalink / raw)
  To: 9front

Thanks for committing, Igor.

Quoth igor@9lab.org:
> Quoth Romano <unobe@cpan.org>:
> > for large remote framebuffers, only the upper left-hand corner
> > of the screen is ever visible. Autoscaling, while slow, at least
> > makes all the screen visible. There is a noticeable lag while the
> > scaling occurs, but vncv as-is isn't a paragon of speed. While in
> > the code, update documentation for this feature.
> […]
> 
> Thanks!  I tested it connecting to OSX Sonoma and indeed, with
> autoscaling the full screen is visible for large remote frame buffers.
> 
> Without autoscaling only the upper left-hand corner is visible.
> 
> Apart from some tweaks to your man page modifications (see attached
> patch) the diff looks good to me.
> 
> With the option to enable autoscaling the task of reducing the
> resolution on the remote machine in case it is too large for the local
> window is much simplified.
> 
> Unless there is any objection I would like to merge the attached patch
> aimed at improving usability of vncv by the end of this week.
> 
> Please let me know if you disagree.
> 
> Cheers,
> Igor
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-01-12  4:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-30  1:29 [9front] [PATCH] vncv: implement autoscaling with -a flag Romano
2024-01-02  7:42 ` mkf9
2024-01-03  0:37 ` igor
2024-01-12  4:24   ` unobe

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).