ref: 36abc45f2895ebc6b02f746586e814349581579b
parent: da5c0bada7be9dd82ca1f63e621670143597d3bb
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sun Jul 29 22:21:28 EDT 2018
vncv: implement extended DesktopSize extension, cleanup
--- a/sys/src/cmd/vnc/draw.c
+++ b/sys/src/cmd/vnc/draw.c
@@ -11,6 +11,8 @@
"raw", EncRaw,
"rre", EncRre,
"mousewarp", EncMouseWarp,
+ "desktopsize", EncDesktopSize,
+ "xdesktopsize", EncXDesktopSize,
};
static uchar *pixbuf;
@@ -20,6 +22,16 @@
static void (*pixcp)(uchar*, uchar*);
static void
+vncsetdim(Vnc *v, Rectangle dim)
+{
+ v->dim = rectsubpt(dim, dim.min);
+ linebuf = realloc(linebuf, v->dim.max.x * vpixb);
+ pixbuf = realloc(pixbuf, v->dim.max.x * pixb * v->dim.max.y);
+ if(linebuf == nil || pixbuf == nil)
+ sysfatal("can't allocate pix decompression storage");
+}
+
+static void
vncrdcolor(Vnc *v, uchar *color)
{
vncrdbytes(v, color, vpixb);
@@ -31,8 +43,8 @@
void
sendencodings(Vnc *v)
{
- char *f[10];
- int enc[10], nenc, i, j, nf;
+ char *f[16];
+ int enc[16], nenc, i, j, nf;
nf = tokenize(encodings, f, nelem(f));
nenc = 0;
@@ -60,21 +72,27 @@
void
requestupdate(Vnc *v, int incremental)
{
- int x, y;
+ Rectangle r;
lockdisplay(display);
flushimage(display, 1);
- x = Dx(screen->r);
- y = Dy(screen->r);
+ r = rectsubpt(screen->r, screen->r.min);
unlockdisplay(display);
- if(x > v->dim.x)
- x = v->dim.x;
- if(y > v->dim.y)
- y = v->dim.y;
vnclock(v);
+ if(incremental == 0 && v->canresize && !eqrect(r, v->dim)){
+ vncwrchar(v, MSetDesktopSize);
+ vncwrchar(v, 0);
+ vncwrpoint(v, r.max);
+ vncwrchar(v, 1);
+ vncwrchar(v, 0);
+ vncwrlong(v, v->screen[0].id);
+ vncwrrect(v, r);
+ vncwrlong(v, v->screen[0].flags);
+ } else
+ rectclip(&r, v->dim);
vncwrchar(v, MFrameReq);
vncwrchar(v, incremental);
- vncwrrect(v, Rpt(ZP, Pt(x, y)));
+ vncwrrect(v, r);
vncflush(v);
vncunlock(v);
}
@@ -237,16 +255,42 @@
Rectangle r, subr, maxr;
r = vncrdrect(v);
- if(!rectinrect(r, Rpt(ZP, v->dim)))
- sysfatal("bad rectangle from server: %R not in %R", r, Rpt(ZP, v->dim));
- stride = Dx(r) * pixb;
type = vncrdlong(v);
switch(type){
+ case EncMouseWarp:
+ mousewarp(r.min);
+ return;
+
+ case EncXDesktopSize:
+ v->canresize = 1;
+ n = vncrdlong(v)>>24;
+ if(n <= 0)
+ break;
+ v->screen[0].id = vncrdlong(v);
+ v->screen[0].rect = vncrdrect(v);
+ v->screen[0].flags = vncrdlong(v);
+ while(--n > 0){
+ vncrdlong(v);
+ vncrdrect(v);
+ vncrdlong(v);
+ }
+ /* wet floor */
+ case EncDesktopSize:
+ vncsetdim(v, r);
+ return;
+ }
+
+ if(!rectinrect(r, v->dim))
+ sysfatal("bad rectangle from server: %R not in %R", r, v->dim);
+ maxr = rectsubpt(r, r.min);
+ stride = maxr.max.x * pixb;
+
+ switch(type){
default:
sysfatal("bad rectangle encoding from server");
break;
case EncRaw:
- loadbuf(v, Rpt(ZP, Pt(Dx(r), Dy(r))), stride);
+ loadbuf(v, maxr, stride);
updatescreen(r);
break;
@@ -261,7 +305,6 @@
case EncRre:
case EncCorre:
- maxr = Rpt(ZP, Pt(Dx(r), Dy(r)));
n = vncrdlong(v);
vncrdcolor(v, (uchar*)&color);
fillrect(maxr, stride, (uchar*)&color);
@@ -282,10 +325,6 @@
dohextile(v, r, stride);
updatescreen(r);
break;
-
- case EncMouseWarp:
- mousewarp(r.min);
- break;
}
}
@@ -348,10 +387,7 @@
default:
sysfatal("can't handle your screen: bad depth %d", pixb);
}
- linebuf = malloc(v->dim.x * vpixb);
- pixbuf = malloc(v->dim.x * pixb * v->dim.y);
- if(linebuf == nil || pixbuf == nil)
- sysfatal("can't allocate pix decompression storage");
+ vncsetdim(v, v->dim);
for(;;){
type = vncrdchar(v);
switch(type){
--- a/sys/src/cmd/vnc/vnc.h
+++ b/sys/src/cmd/vnc/vnc.h
@@ -31,9 +31,16 @@
Biobuf in;
Biobuf out;
- Point dim;
+ Rectangle dim;
Pixfmt;
char *name; /* client only */
+
+ int canresize;
+ struct {
+ ulong id;
+ Rectangle rect;
+ ulong flags;
+ } screen[1];
};
enum {
@@ -63,6 +70,7 @@
MKey,
MMouse,
MCCut,
+ MSetDesktopSize = 251,
/* image encoding methods */
EncRaw = 0,
@@ -75,6 +83,9 @@
EncZHextile = 8,
EncMouseWarp = 9,
+ EncDesktopSize = -223,
+ EncXDesktopSize = -308,
+
/* paramaters for hextile encoding */
HextileDim = 16,
HextileRaw = 1,
@@ -131,4 +142,4 @@
extern void vnchungup(Vnc*);
extern int verbose;
-extern char* serveraddr;
\ No newline at end of file
+extern char* serveraddr;
--- a/sys/src/cmd/vnc/vncs.c
+++ b/sys/src/cmd/vnc/vncs.c
@@ -21,29 +21,6 @@
nil
};
-static char *msgname[] = {
- [MPixFmt] = "MPixFmt",
- [MFixCmap] = "MFixCmap",
- [MSetEnc] = "MSetEnc",
- [MFrameReq] = "MFrameReq",
- [MKey] = "MKey",
- [MMouse] = "MMouse",
- [MCCut] = "MCCut",
-};
-
-static char *encname[] = {
- [EncRaw] = "raw",
- [EncCopyRect] = "copy rect",
- [EncRre] = "rre",
- [EncCorre] = "corre",
- [EncHextile] = "hextile",
- [EncZlib] = "zlib",
- [EncTight] = "zlibtight",
- [EncZHextile] = "zhextile",
- [EncMouseWarp] = "mousewarp",
-
-};
-
/*
* list head. used to hold the list, the lock, dim, and pixelfmt
*/
@@ -594,10 +571,10 @@
if(!shared)
killclients(v);
- v->dim = (Point){Dx(gscreen->r), Dy(gscreen->r)};
- vncwrpoint(v, v->dim);
+ v->dim = rectsubpt(screen->r, screen->r.min);
+ vncwrpoint(v, v->dim.max);
if(verbose)
- fprint(2, "%V: send screen size %P (rect %R)\n", v, v->dim, gscreen->r);
+ fprint(2, "%V: send screen size %R\n", v, v->dim);
v->bpp = gscreen->depth;
v->depth = gscreen->depth;
@@ -696,6 +673,9 @@
case EncMouseWarp:
v->canwarp = 1;
continue;
+ case EncDesktopSize:
+ case EncXDesktopSize:
+ continue;
}
if(v->countrect != nil)
continue;
@@ -1118,7 +1098,7 @@
|| (v->image && v->image->chan != v->imagechan)){
if(v->image)
freememimage(v->image);
- v->image = allocmemimage(Rpt(ZP, v->dim), v->imagechan);
+ v->image = allocmemimage(v->dim, v->imagechan);
if(v->image == nil){
fprint(2, "%V: allocmemimage: %r; hanging up\n", v);
vnchungup(v);
--- a/sys/src/cmd/vnc/vncv.c
+++ b/sys/src/cmd/vnc/vncv.c
@@ -3,7 +3,7 @@
#include <libsec.h>
char* charset = "utf-8";
-char* encodings = "copyrect hextile corre rre raw mousewarp";
+char* encodings = "copyrect hextile corre rre raw mousewarp desktopsize xdesktopsize";
int bpp12;
int shared;
int verbose;
@@ -77,7 +77,6 @@
{
int p, dfd, cfd, shared;
char *keypattern, *label;
- Point d;
keypattern = nil;
shared = 0;
@@ -140,10 +139,6 @@
display->locking = 1;
unlockdisplay(display);
- d = addpt(vnc->dim, Pt(2*Borderwidth, 2*Borderwidth));
- if(verbose)
- fprint(2, "screen size %P, desktop size %P\n", display->image->r.max, d);
-
choosecolor(vnc);
sendencodings(vnc);
initmouse();
@@ -197,7 +192,7 @@
{
vncwrchar(v, shared);
vncflush(v);
- v->dim = vncrdpoint(v);
+ v->dim = Rpt(ZP, vncrdpoint(v));
v->Pixfmt = vncrdpixfmt(v);
v->name = vncrdstring(v);
return 0;
--- a/sys/src/cmd/vnc/wsys.c
+++ b/sys/src/cmd/vnc/wsys.c
@@ -16,20 +16,20 @@
int fd;
Point d;
- d = addpt(v->dim, Pt(2*Borderwidth, 2*Borderwidth));
lockdisplay(display);
-
if(getwindow(display, Refnone) < 0)
sysfatal("internal error: can't get the window image");
-
- /*
- * limit the window to at most the vnc server's size
- */
- if(first || d.x < Dx(screen->r) || d.y < Dy(screen->r)){
- fd = open("/dev/wctl", OWRITE);
- if(fd >= 0){
- fprint(fd, "resize -dx %d -dy %d", d.x, d.y);
- close(fd);
+ if(!v->canresize){
+ /*
+ * limit the window to at most the vnc server's size
+ */
+ d = addpt(v->dim.max, Pt(2*Borderwidth, 2*Borderwidth));
+ if(first || d.x < Dx(screen->r) || d.y < Dy(screen->r)){
+ fd = open("/dev/wctl", OWRITE);
+ if(fd >= 0){
+ fprint(fd, "resize -dx %d -dy %d", d.x, d.y);
+ close(fd);
+ }
}
}
unlockdisplay(display);
@@ -39,7 +39,6 @@
eresized(void)
{
resize(vnc, 0);
-
requestupdate(vnc, 0);
}
@@ -147,7 +146,7 @@
m.xy.y = atoi(start+1+12);
m.buttons = atoi(start+1+2*12) & 0x1F;
m.xy = subpt(m.xy, screen->r.min);
- if(ptinrect(m.xy, Rpt(ZP, v->dim))){
+ if(ptinrect(m.xy, v->dim)){
mouseevent(v, m);
/* send wheel button *release* */
if ((m.buttons & 0x7) != m.buttons) {