ref: d2089f949edd71626e2391672b723aa2d9fbcb9b
parent: 670137bf0a75813df93d9b727ce70ddb099d11e1
author: cinap_lenrek <[email protected]>
date: Mon Aug 20 15:23:42 EDT 2018
vncs: support for desktop resize extension, update devdraw
--- a/sys/src/cmd/vnc/devcons.c
+++ b/sys/src/cmd/vnc/devcons.c
@@ -13,7 +13,6 @@
Qcons,
Qconsctl,
Qsnarf,
- Qwinname,
};
static Dirtab consdir[]={
@@ -21,7 +20,6 @@
"cons", {Qcons}, 0, 0660,
"consctl", {Qconsctl}, 0, 0220,
"snarf", {Qsnarf}, 0, 0600,
- "winname", {Qwinname}, 0, 0000,
};
static Chan*
--- a/sys/src/cmd/vnc/devdraw.c
+++ b/sys/src/cmd/vnc/devdraw.c
@@ -14,6 +14,7 @@
{
Qtopdir = 0,
Qnew,
+ Qwinname,
Q3rd,
Q2nd,
Qcolormap,
@@ -35,6 +36,7 @@
#define NHASH (1<<5)
#define HASHMASK (NHASH-1)
+#define IOUNIT (64*1024)
typedef struct Client Client;
typedef struct Draw Draw;
@@ -46,21 +48,15 @@
typedef struct Refx Refx;
typedef struct DName DName;
-ulong blanktime = 30; /* in minutes; a half hour */
-
struct Draw
{
- QLock;
int clientid;
int nclient;
Client** client;
int nname;
- DName* name;
+ DName* name;
int vers;
int softscreen;
- int blanked; /* screen turned off */
- ulong blanktime; /* time of last operation */
- ulong savemap[3*256];
};
struct Client
@@ -70,6 +66,7 @@
CScreen* cscreen;
Refresh* refresh;
Rendez refrend;
+ QLock refq;
uchar* readdata;
int nreaddata;
int busy;
@@ -95,10 +92,10 @@
struct DName
{
- char *name;
- Client *client;
+ char *name;
+ Client *client;
DImage* dimage;
- int vers;
+ int vers;
};
struct FChar
@@ -128,7 +125,7 @@
int nfchar;
FChar* fchar;
DScreen* dscreen; /* 0 if not a window */
- DImage* fromname; /* image this one is derived from, by name */
+ DImage* fromname; /* image this one is derived from, by name */
DImage* next;
};
@@ -143,8 +140,8 @@
int id;
int public;
int ref;
- DImage *dimage;
- DImage *dfill;
+ DImage *dimage;
+ DImage *dfill;
Memscreen* screen;
Client* owner;
DScreen* next;
@@ -151,8 +148,13 @@
};
static Draw sdraw;
+ QLock drawlock;
+
static Memimage *screenimage;
-static Memdata screendata;
+static DImage* screendimage;
+static char screenname[40];
+static int screennameid;
+
static Rectangle flushrect;
static int waste;
static DScreen* dscreen;
@@ -161,6 +163,7 @@
void drawuninstall(Client*, int);
void drawfreedimage(DImage*);
Client* drawclientofpath(ulong);
+ DImage* allocdimage(Memimage*);
static char Enodrawimage[] = "unknown id for draw image";
static char Enodrawscreen[] = "unknown id for draw screen";
@@ -174,7 +177,6 @@
static char Enotfont[] = "image not a font";
static char Eindex[] = "character index out of range";
static char Enoclient[] = "no such draw client";
-static char Edepth[] = "image has bad depth";
static char Enameused[] = "image name in use";
static char Enoname[] = "no image with that name";
static char Eoldname[] = "named image no longer valid";
@@ -181,22 +183,22 @@
static char Enamed[] = "image already has name";
static char Ewrongname[] = "wrong name for image";
-void
-drawlock(void)
+static void
+dlock(void)
{
- qlock(&sdraw);
+ qlock(&drawlock);
}
-void
-drawunlock(void)
+static int
+candlock(void)
{
- qunlock(&sdraw);
+ return canqlock(&drawlock);
}
-int
-candrawlock(void)
+static void
+dunlock(void)
{
- return canqlock(&sdraw);
+ qunlock(&drawlock);
}
static int
@@ -226,7 +228,7 @@
devdir(c, q, up->genbuf, 0, eve, 0500, dp);
break;
default:
- panic("drawwalk %#llux", c->qid.path);
+ panic("drawwalk %llux", c->qid.path);
}
return 1;
}
@@ -235,15 +237,17 @@
* Top level directory contains the name of the device.
*/
t = QID(c->qid);
- if(t == Qtopdir){
- switch(s){
- case 0:
+ if(t == Qtopdir || t == Qwinname){
+ if(s == 1 || t == Qwinname){
+ mkqid(&q, Qwinname, 0, QTFILE);
+ devdir(c, q, "winname", 0, eve, 0444, dp);
+ }
+ else if(s == 0){
mkqid(&q, Q2nd, 0, QTDIR);
devdir(c, q, "draw", 0, eve, 0555, dp);
- break;
- default:
- return -1;
}
+ else
+ return -1;
return 1;
}
@@ -272,7 +276,7 @@
/*
* Third level.
*/
- path = c->qid.path&~(((1<<QSHIFT)-1)); /* slot component */
+ path = c->qid.path&~((1<<QSHIFT)-1); /* slot component */
q.vers = c->qid.vers;
q.type = QTFILE;
switch(s){
@@ -320,7 +324,7 @@
static
void
-drawrefresh(Memimage *l, Rectangle r, void *v)
+drawrefresh(Memimage*, Rectangle r, void *v)
{
Refx *x;
DImage *d;
@@ -327,7 +331,6 @@
Client *c;
Refresh *ref;
- USED(l);
if(v == 0)
return;
x = v;
@@ -353,9 +356,8 @@
int abb, ar, anbb;
Rectangle nbb;
- if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
+ if(sdraw.softscreen==0 || screenimage == nil || !rectclip(&r, screenimage->r))
return;
-
if(flushrect.min.x >= flushrect.max.x){
flushrect = r;
waste = 0;
@@ -393,7 +395,8 @@
return;
}
/* emit current state */
- flushmemscreen(flushrect);
+ if(flushrect.min.x < flushrect.max.x)
+ flushmemscreen(flushrect);
flushrect = r;
waste = 0;
}
@@ -409,8 +412,7 @@
addflush(r); // for VNC, see comments in addflush
return;
}
- l = dst->layer;
- if(l == nil)
+ if(screenimage == nil || dst == nil || (l = dst->layer) == nil)
return;
do{
if(l->screen->image->data != screenimage->data)
@@ -421,11 +423,11 @@
addflush(r);
}
-static
void
drawflush(void)
{
- flushmemscreen(flushrect);
+ if(screenimage && flushrect.min.x < flushrect.max.x)
+ flushmemscreen(flushrect);
flushrect = Rect(10000, 10000, -10000, -10000);
}
@@ -517,8 +519,8 @@
return 0;
}
-Memimage*
-drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
+DImage*
+allocdimage(Memimage *i)
{
DImage *d;
@@ -525,14 +527,26 @@
d = malloc(sizeof(DImage));
if(d == 0)
return 0;
- d->id = id;
d->ref = 1;
d->name = 0;
d->vers = 0;
d->image = i;
+ d->dscreen = 0;
d->nfchar = 0;
d->fchar = 0;
d->fromname = 0;
+ return d;
+}
+
+Memimage*
+drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
+{
+ DImage *d;
+
+ d = allocdimage(i);
+ if(d == 0)
+ return 0;
+ d->id = id;
d->dscreen = dscreen;
d->next = client->dimage[id&HASHMASK];
client->dimage[id&HASHMASK] = d;
@@ -595,6 +609,7 @@
{
int i;
+ free(name->name);
i = name-sdraw.name;
memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
sdraw.nname--;
@@ -656,12 +671,10 @@
drawfreedimage(dimage->fromname);
goto Return;
}
- if(dimage->image == screenimage) /* don't free the display */
- goto Return;
ds = dimage->dscreen;
if(ds){
l = dimage->image;
- if(l->data == screenimage->data)
+ if(screenimage && l->data == screenimage->data)
addflush(l->layer->screenr);
if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
free(l->layer->refreshptr);
@@ -856,11 +869,12 @@
}
Point
-drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
+drawchar(Memimage *dst, Memimage *rdst, Point p, Memimage *src, Point *sp, DImage *font, int index, int op)
{
FChar *fc;
Rectangle r;
Point sp1;
+ static Memimage *tmp;
fc = &font->fchar[index];
r.min.x = p.x+fc->left;
@@ -869,69 +883,143 @@
r.max.y = r.min.y+(fc->maxy-fc->miny);
sp1.x = sp->x+fc->left;
sp1.y = sp->y+fc->miny;
- memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
+
+ /*
+ * If we're drawing greyscale fonts onto a VGA screen,
+ * it's very costly to read the screen memory to do the
+ * alpha blending inside memdraw. If this is really a stringbg,
+ * then rdst is the bg image (in main memory) which we can
+ * refer to for the underlying dst pixels instead of reading dst
+ * directly.
+ */
+ if(ishwimage(dst) && !ishwimage(rdst) && font->image->depth > 1){
+ if(tmp == nil || tmp->chan != dst->chan || Dx(tmp->r) < Dx(r) || Dy(tmp->r) < Dy(r)){
+ if(tmp)
+ freememimage(tmp);
+ tmp = allocmemimage(Rect(0,0,Dx(r),Dy(r)), dst->chan);
+ if(tmp == nil)
+ goto fallback;
+ }
+ memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), rdst, r.min, memopaque, ZP, S);
+ memdraw(tmp, Rect(0,0,Dx(r),Dy(r)), src, sp1, font->image, Pt(fc->minx, fc->miny), op);
+ memdraw(dst, r, tmp, ZP, memopaque, ZP, S);
+ }else{
+ fallback:
+ memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
+ }
+
p.x += fc->width;
sp->x += fc->width;
return p;
}
-static int
-initscreenimage(void)
+static DImage*
+makescreenimage(void)
{
int width, depth;
ulong chan;
+ DImage *di;
+ Memdata *md;
+ Memimage *i;
Rectangle r;
+ uchar *data;
+ if((data = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen)) == nil)
+ return nil;
+ if(sdraw.softscreen == 0xa110c){
+ /* hack: softscreen is memimage. */
+ md = *((Memdata**)(data - sizeof(ulong) - sizeof(Memdata*)));
+
+ assert(md->bdata == data);
+ assert(md->ref > 1);
+ assert(md->allocd);
+
+ if((i = allocmemimaged(r, chan, md)) == nil){
+ md->ref--;
+ return nil;
+ }
+ }else{
+ if((md = malloc(sizeof *md)) == nil)
+ return nil;
+ md->allocd = 1;
+ md->base = nil;
+ md->bdata = data;
+ md->ref = 1;
+ if((i = allocmemimaged(r, chan, md)) == nil){
+ free(md);
+ return nil;
+ }
+ }
+ i->width = width;
+ i->clipr = r;
+ di = allocdimage(i);
+ if(di == nil){
+ freememimage(i); /* frees md */
+ return nil;
+ }
+ if(!waserror()){
+ snprint(screenname, sizeof screenname, "noborder.screen.%d", ++screennameid);
+ drawaddname(nil, di, strlen(screenname), screenname);
+ poperror();
+ }
+ return di;
+}
+
+static int
+initscreenimage(void)
+{
if(screenimage != nil)
return 1;
- screendata.base = nil;
- screendata.bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen);
- if(screendata.bdata == nil)
-{fprint(2, "bad bdata\n");
+ screendimage = makescreenimage();
+ if(screendimage == nil)
return 0;
+ screenimage = screendimage->image;
+// iprint("initscreenimage %p %p\n", screendimage, screenimage);
+ mouseresize();
+ return 1;
}
- screendata.ref = 1;
- screenimage = allocmemimaged(r, chan, &screendata);
- if(screenimage == nil){
-fprint(2, "bad memimaged: %r\n");
- /* RSC: BUG: detach screen */
- return 0;
+void
+deletescreenimage(void)
+{
+ dlock();
+ if(screenimage){
+ /* will be freed via screendimage; disable */
+ screenimage->clipr = ZR;
+ screenimage = nil;
}
-
- screenimage->width = width;
- screenimage->clipr = screenimage->r;
- return 1;
+ if(screendimage){
+ drawfreedimage(screendimage);
+ screendimage = nil;
+ }
+ dunlock();
}
void
-deletescreenimage(void)
+resetscreenimage(void)
{
- qlock(&sdraw);
- /* RSC: BUG: detach screen */
- if(screenimage)
- freememimage(screenimage);
- screenimage = nil;
- qunlock(&sdraw);
+ dlock();
+ initscreenimage();
+ dunlock();
}
-Chan*
+static Chan*
drawattach(char *spec)
{
- qlock(&sdraw);
+ dlock();
if(!initscreenimage()){
- qunlock(&sdraw);
+ dunlock();
error("no frame buffer");
}
- qunlock(&sdraw);
+ dunlock();
return devattach('i', spec);
}
-Walkqid*
+static Walkqid*
drawwalk(Chan *c, Chan *nc, char **name, int nname)
{
- if(screendata.bdata == nil)
+ if(screenimage == nil)
error("no frame buffer");
return devwalk(c, nc, name, nname, 0, 0, drawgen);
}
@@ -946,13 +1034,17 @@
drawopen(Chan *c, int omode)
{
Client *cl;
+ DName *dn;
+ DImage *di;
- if(c->qid.type & QTDIR)
- return devopen(c, omode, 0, 0, drawgen);
+ if(c->qid.type & QTDIR){
+ c = devopen(c, omode, 0, 0, drawgen);
+ c->iounit = IOUNIT;
+ }
- qlock(&sdraw);
+ dlock();
if(waserror()){
- qunlock(&sdraw);
+ dunlock();
nexterror();
}
@@ -964,6 +1056,9 @@
}
switch(QID(c->qid)){
+ case Qwinname:
+ break;
+
case Qnew:
break;
@@ -973,9 +1068,22 @@
error(Einuse);
cl->busy = 1;
flushrect = Rect(10000, 10000, -10000, -10000);
- drawinstall(cl, 0, screenimage, 0);
+ dn = drawlookupname(strlen(screenname), screenname);
+ if(dn == 0)
+ error("draw: cannot happen 2");
+ if(drawinstall(cl, 0, dn->dimage->image, 0) == 0)
+ error(Edrawmem);
+ di = drawlookup(cl, 0, 0);
+ if(di == 0)
+ error("draw: cannot happen 1");
+ di->vers = dn->vers;
+ di->name = smalloc(strlen(screenname)+1);
+ strcpy(di->name, screenname);
+ di->fromname = dn->dimage;
+ di->fromname->ref++;
incref(&cl->r);
break;
+
case Qcolormap:
case Qdata:
case Qrefresh:
@@ -983,11 +1091,12 @@
incref(&cl->r);
break;
}
- qunlock(&sdraw);
+ dunlock();
poperror();
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
+ c->iounit = IOUNIT;
return c;
}
@@ -999,11 +1108,11 @@
Client *cl;
Refresh *r;
- if(c->qid.type & QTDIR)
+ if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */
return;
- qlock(&sdraw);
+ dlock();
if(waserror()){
- qunlock(&sdraw);
+ dunlock();
nexterror();
}
@@ -1036,7 +1145,7 @@
drawflush(); /* to erase visible, now dead windows */
free(cl);
}
- qunlock(&sdraw);
+ dunlock();
poperror();
}
@@ -1053,13 +1162,15 @@
ulong offset = off;
char buf[16];
- USED(offset);
if(c->qid.type & QTDIR)
return devdirread(c, a, n, 0, 0, drawgen);
+ if(QID(c->qid) == Qwinname)
+ return readstr(off, a, n, screenname);
+
cl = drawclient(c);
- qlock(&sdraw);
+ dlock();
if(waserror()){
- qunlock(&sdraw);
+ dunlock();
nexterror();
}
switch(QID(c->qid)){
@@ -1078,15 +1189,15 @@
error(Enodrawimage);
i = di->image;
}
- n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d ",
+ n = sprint(a, "%11d %11d %11s %11d %11d %11d %11d %11d %11d %11d %11d %11d",
cl->clientid, cl->infoid, chantostr(buf, i->chan), (i->flags&Frepl)==Frepl,
i->r.min.x, i->r.min.y, i->r.max.x, i->r.max.y,
i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
+ ((char*)a)[n++] = ' ';
cl->infoid = -1;
break;
case Qcolormap:
- drawactive(1); /* to restore map from backup */
p = malloc(4*12*256+1);
if(p == 0)
error(Enomem);
@@ -1116,14 +1227,21 @@
for(;;){
if(cl->refreshme || cl->refresh)
break;
- qunlock(&sdraw);
+ dunlock();
if(waserror()){
- qlock(&sdraw); /* restore lock for waserror() above */
+ dlock();
nexterror();
}
+ qlock(&cl->refq);
+ if(waserror()){
+ qunlock(&cl->refq);
+ nexterror();
+ }
rendsleep(&cl->refrend, drawrefactive, cl);
poperror();
- qlock(&sdraw);
+ qunlock(&cl->refq);
+ poperror();
+ dlock();
}
p = a;
while(cl->refresh && n>=5*4){
@@ -1140,8 +1258,9 @@
}
cl->refreshme = 0;
n = p-(uchar*)a;
+ break;
}
- qunlock(&sdraw);
+ dunlock();
poperror();
return n;
}
@@ -1160,21 +1279,19 @@
}
static long
-drawwrite(Chan *c, void *a, long n, vlong off)
+drawwrite(Chan *c, void *a, long n, vlong)
{
char buf[128], *fields[4], *q;
Client *cl;
int i, m, red, green, blue, x;
- ulong offset = off;
- USED(offset);
if(c->qid.type & QTDIR)
error(Eisdir);
cl = drawclient(c);
- qlock(&sdraw);
+ dlock();
if(waserror()){
drawwakeall();
- qunlock(&sdraw);
+ dunlock();
nexterror();
}
switch(QID(c->qid)){
@@ -1185,7 +1302,6 @@
break;
case Qcolormap:
- drawactive(1); /* to restore map from backup */
m = n;
n = 0;
while(m > 0){
@@ -1200,7 +1316,7 @@
a = (char*)a + i;
m -= i;
*q = 0;
- if(getfields(buf, fields, nelem(fields), 1, " ") != 4)
+ if(tokenize(buf, fields, nelem(fields)) != 4)
error(Ebadarg);
i = strtoul(fields[0], 0, 0);
red = strtoul(fields[1], 0, 0);
@@ -1228,7 +1344,7 @@
default:
error(Ebadusefd);
}
- qunlock(&sdraw);
+ dunlock();
poperror();
return n;
}
@@ -1265,7 +1381,7 @@
char *p, *q;
int s;
- if(1||plsprnt==0){
+ if(1|| plsprnt==0){
SET(s,q,p);
USED(fmt, a, buf, p, q, s);
return;
@@ -1305,7 +1421,7 @@
}
*q++ = '\n';
*q = 0;
- fprint(2, "%.*s", (int)(q-buf), buf);
+ // iprint("%.*s", (int)(q-buf), buf);
}
void
@@ -1317,7 +1433,7 @@
ulong value, chan;
Rectangle r, clipr;
Point p, q, *pp, sp;
- Memimage *i, *dst, *src, *mask;
+ Memimage *i, *bg, *dst, *src, *mask;
Memimage *l, **lp;
Memscreen *scrn;
DImage *font, *ll, *di, *ddst, *dsrc;
@@ -1333,6 +1449,7 @@
fmt = nil;
if(waserror()){
if(fmt) printmesg(fmt, a, 1);
+ /* iprint("error: %s\n", up->errstr); */
nexterror();
}
while((n-=m) > 0){
@@ -1445,7 +1562,7 @@
if(ddst == nil)
error(Enodrawimage);
if(ddst->name)
- error("can't change repl/clipr of shared image");
+ error("cannot change repl/clipr of shared image");
dst = ddst->image;
if(a[5])
dst->flags |= Frepl;
@@ -1543,14 +1660,16 @@
error(Eshortdraw);
dstid = BGLONG(a+1);
if(dstid == 0)
- error("can't use display as font");
+ error("cannot use display as font");
font = drawlookup(client, dstid, 1);
if(font == 0)
error(Enodrawimage);
if(font->image->layer)
- error("can't use window as font");
- free(font->fchar); /* should we complain if non-zero? */
+ error("cannot use window as font");
ni = BGLONG(a+5);
+ if(ni<=0 || ni>4096)
+ error("bad font size (4096 chars max)");
+ free(font->fchar); /* should we complain if non-zero? */
font->fchar = malloc(ni*sizeof(FChar));
if(font->fchar == 0)
error("no memory for font");
@@ -1647,7 +1766,7 @@
error(Edrawmem);
di = drawlookup(client, dstid, 0);
if(di == 0)
- error("draw: can't happen");
+ error("draw: cannot happen");
di->vers = dn->vers;
di->name = smalloc(j+1);
di->fromname = dn->dimage;
@@ -1748,7 +1867,7 @@
if(pp == nil)
error(Enomem);
doflush = 0;
- if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
+ if(dstid==0 || (screenimage && dst->layer && dst->layer->screen->image->data == screenimage->data))
doflush = 1; /* simplify test in loop */
ox = oy = 0;
esize = 0;
@@ -1803,8 +1922,6 @@
if(n < m)
error(Eshortdraw);
i = drawimage(client, a+1);
- if(0 && i->layer)
- error("readimage from window unimplemented");
drawrectangle(&r, a+5);
if(!rectinrect(r, i->r))
error(Ereadoutside);
@@ -1814,7 +1931,7 @@
client->readdata = mallocz(c, 0);
if(client->readdata == nil)
error("readimage malloc failed");
- client->nreaddata = unloadmemimage(i, r, client->readdata, c);
+ client->nreaddata = memunload(i, r, client->readdata, c);
if(client->nreaddata < 0){
free(client->readdata);
client->readdata = nil;
@@ -1852,9 +1969,10 @@
clipr = dst->clipr;
dst->clipr = r;
op = drawclientop(client);
+ bg = dst;
if(*a == 'x'){
/* paint background */
- l = drawimage(client, a+47);
+ bg = drawimage(client, a+47);
drawpoint(&q, a+51);
r.min.x = p.x;
r.min.y = p.y-font->ascent;
@@ -1870,7 +1988,7 @@
r.max.x += font->fchar[ci].width;
u += 2;
}
- memdraw(dst, r, l, q, memopaque, ZP, op);
+ memdraw(dst, r, bg, q, memopaque, ZP, op);
u -= 2*ni;
}
q = p;
@@ -1880,7 +1998,7 @@
dst->clipr = clipr;
error(Eindex);
}
- q = drawchar(dst, q, src, &sp, font, ci, op);
+ q = drawchar(dst, bg, q, src, &sp, font, ci, op);
u += 2;
}
dst->clipr = clipr;
@@ -1938,7 +2056,7 @@
memltofrontn(lp, nw);
else
memltorearn(lp, nw);
- if(lp[0]->layer->screen->image->data == screenimage->data)
+ if(screenimage && lp[0]->layer->screen->image->data == screenimage->data)
for(j=0; j<nw; j++)
addflush(lp[j]->layer->screenr);
ll = drawlookup(client, BGLONG(a+1+1+2), 1);
@@ -2009,7 +2127,6 @@
int num, den;
int i, j;
- drawactive(1); /* to restore map from backup */
for(r=0,i=0; r!=4; r++)
for(v=0; v!=4; v++,i+=16){
for(g=0,j=v-r; g!=4; g++)
@@ -2031,54 +2148,4 @@
cr*0x01010101, cg*0x01010101, cb*0x01010101);
}
}
-}
-
-void
-drawblankscreen(int blank)
-{
- int i, nc;
- ulong *p;
-
- if(blank == sdraw.blanked)
- return;
- if(!canqlock(&sdraw))
- return;
- if(!initscreenimage()){
- qunlock(&sdraw);
- return;
- }
- p = sdraw.savemap;
- nc = screenimage->depth > 8 ? 256 : 1<<screenimage->depth;
-
- /*
- * blankscreen uses the hardware to blank the screen
- * when possible. to help in cases when it is not possible,
- * we set the color map to be all black.
- */
- if(blank == 0){ /* turn screen on */
- for(i=0; i<nc; i++, p+=3)
- setcolor(i, p[0], p[1], p[2]);
- blankscreen(0);
- }else{ /* turn screen off */
- blankscreen(1);
- for(i=0; i<nc; i++, p+=3){
- getcolor(i, &p[0], &p[1], &p[2]);
- setcolor(i, 0, 0, 0);
- }
- }
- sdraw.blanked = blank;
- qunlock(&sdraw);
-}
-
-/*
- * record activity on screen, changing blanking as appropriate
- */
-void
-drawactive(int active)
-{
- if(active){
- drawblankscreen(0);
- sdraw.blanktime = 0;
- }else
- sdraw.blanktime++;
}
--- a/sys/src/cmd/vnc/devmouse.c
+++ b/sys/src/cmd/vnc/devmouse.c
@@ -27,6 +27,7 @@
ulong lastcounter; /* value when /dev/mouse read */
Rendez r;
Ref;
+ int resize;
int open;
Mousestate queue[16]; /* circular buffer of click events */
ulong ri; /* read index into queue */
@@ -195,6 +196,10 @@
m.xy.x, m.xy.y, m.buttons, m.msec);
mouse.lastcounter = m.counter;
+ if(mouse.resize){
+ mouse.resize = 0;
+ buf[0] = 'r';
+ }
if(n > 1+4*12)
n = 1+4*12;
@@ -321,7 +326,7 @@
int
mousechanged(void*)
{
- return mouse.lastcounter != mouse.counter;
+ return mouse.lastcounter != mouse.counter || mouse.resize != 0;
}
Point
@@ -328,4 +333,14 @@
mousexy(void)
{
return mouse.xy;
+}
+
+/*
+ * notify reader that screen has been resized
+ */
+void
+mouseresize(void)
+{
+ mouse.resize = 1;
+ rendwakeup(&mouse.r);
}
--- a/sys/src/cmd/vnc/draw.c
+++ b/sys/src/cmd/vnc/draw.c
@@ -260,9 +260,12 @@
case EncMouseWarp:
mousewarp(r.min);
return;
-
+ case EncDesktopSize:
+ v->canresize |= 1;
+ vncsetdim(v, r);
+ return;
case EncXDesktopSize:
- v->canresize = 1;
+ v->canresize |= 2;
n = vncrdlong(v)>>24;
if(n <= 0)
break;
@@ -274,9 +277,7 @@
vncrdrect(v);
vncrdlong(v);
}
- /* wet floor */
- case EncDesktopSize:
- vncsetdim(v, r);
+ vncsetdim(v, v->screen[0].rect);
return;
}
--- a/sys/src/cmd/vnc/screen.c
+++ b/sys/src/cmd/vnc/screen.c
@@ -42,10 +42,7 @@
void
screeninit(int x, int y, char *chanstr)
{
- Point p, q;
- char *greet;
char buf[128];
- Memimage *grey;
Rectangle r;
int chan;
@@ -78,16 +75,6 @@
error(buf);
}
- drawlock();
-
- /*
- * set up goo for screenputs
- */
- memdefont = getmemdefont();
-
- back = memwhite;
- conscol = memblack;
-
/* a lot of work to get a grey color */
curscol = allocmemimage(Rect(0,0,1,1), RGBA32);
curscol->flags |= Frepl;
@@ -94,15 +81,27 @@
curscol->clipr = gscreen->r;
memfillcolor(curscol, 0xff0000ff);
- memfillcolor(gscreen, 0x444488FF);
+ screenwin();
- w = memdefont->info[' '].width;
- h = memdefont->height;
+ setcursor(&arrow);
+}
- window.min = addpt(gscreen->r.min, Pt(20,20));
- window.max.x = window.min.x + Dx(gscreen->r)*3/4-40;
- window.max.y = window.min.y + Dy(gscreen->r)*3/4-100;
+void
+screenwin(void)
+{
+ Point p;
+ char *greet;
+ Memimage *grey;
+ qlock(&drawlock);
+ back = memwhite;
+ conscol = memblack;
+ memfillcolor(gscreen, 0x888844FF);
+
+ memdefont = getmemdefont();
+ h = memdefont->height;
+
+ window = insetrect(gscreen->clipr, 20);
memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S);
window = insetrect(window, 4);
memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
@@ -119,22 +118,18 @@
greet = " Plan 9 Console ";
p = addpt(window.min, Pt(10, 0));
- q = memsubfontwidth(memdefont, greet);
memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
window.min.y += h+6;
curpos = window.min;
window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
flushmemscreen(gscreen->r);
-
- drawunlock();
-
- setcursor(&arrow);
+ qunlock(&drawlock);
}
uchar*
attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
{
- *r = gscreen->r;
+ *r = gscreen->clipr;
*d = gscreen->depth;
*chan = gscreen->chan;
*width = gscreen->width;
@@ -263,7 +258,7 @@
memimagedraw(gscreen, r, gscreen, p, nil, p, S);
r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
- flushmemscreen(gscreen->r);
+ flushmemscreen(gscreen->clipr);
curpos.y -= o;
}
@@ -336,7 +331,7 @@
static int nrb;
char *e;
- drawlock();
+ qlock(&drawlock);
e = s + n;
while(s < e){
rb[nrb++] = *s++;
@@ -347,5 +342,5 @@
}
}
screenflush();
- drawunlock();
+ qunlock(&drawlock);
}
--- a/sys/src/cmd/vnc/screen.h
+++ b/sys/src/cmd/vnc/screen.h
@@ -11,6 +11,7 @@
extern int cursorver;
extern Point cursorpos;
+void mouseresize(void);
Point mousexy(void);
void cursoron(void);
void cursoroff(void);
@@ -19,16 +20,18 @@
Rectangle cursorrect(void);
void cursordraw(Memimage *dst, Rectangle r);
+extern QLock drawlock;
void drawactive(int);
-void drawlock(void);
-void drawunlock(void);
-int candrawlock(void);
void getcolor(ulong, ulong*, ulong*, ulong*);
int setcolor(ulong, ulong, ulong, ulong);
#define TK2SEC(x) 0
extern void blankscreen(int);
void screeninit(int x, int y, char *chanstr);
+void screenwin(void);
void absmousetrack(int x, int y, int b, ulong msec);
uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*);
+void deletescreenimage(void);
+void resetscreenimage(void);
void fsinit(char *mntpt, int x, int y, char *chanstr);
+#define ishwimage(i) 0
--- a/sys/src/cmd/vnc/vncs.c
+++ b/sys/src/cmd/vnc/vncs.c
@@ -571,7 +571,7 @@
if(!shared)
killclients(v);
- v->dim = rectsubpt(gscreen->r, gscreen->r.min);
+ v->dim = rectsubpt(gscreen->clipr, gscreen->clipr.min);
vncwrpoint(v, v->dim.max);
if(verbose)
fprint(2, "%V: send screen size %R\n", v, v->dim);
@@ -592,6 +592,8 @@
if(verbose)
fprint(2, "%V: handshaking done\n", v);
+ v->updatereq = 0;
+
switch(rfork(RFPROC|RFMEM)){
case -1:
fprint(2, "%V: cannot fork: %r; hanging up\n", v);
@@ -674,7 +676,10 @@
v->canwarp = 1;
continue;
case EncDesktopSize:
+ v->canresize |= 1;
+ continue;
case EncXDesktopSize:
+ v->canresize |= 2;
continue;
}
if(v->countrect != nil)
@@ -710,9 +715,10 @@
}
if(verbose)
- fprint(2, "Encoding with %s%s%s\n", v->encname,
+ fprint(2, "Encoding with %s%s%s%s\n", v->encname,
v->copyrect ? ", copyrect" : "",
- v->canwarp ? ", canwarp" : "");
+ v->canwarp ? ", canwarp" : "",
+ v->canresize ? ", resize" : "");
}
/*
@@ -755,20 +761,42 @@
case MFrameReq:
incremental = vncrdchar(v);
r = vncrdrect(v);
- if(incremental){
- vnclock(v);
- v->updaterequest = 1;
- vncunlock(v);
- }else{
- drawlock(); /* protects rlist */
- vnclock(v); /* protects updaterequest */
- v->updaterequest = 1;
+ if(!incremental){
+ qlock(&drawlock); /* protects rlist */
addtorlist(&v->rlist, r);
- vncunlock(v);
- drawunlock();
+ qunlock(&drawlock);
}
+ v->updatereq++;
break;
+ case MSetDesktopSize:
+ vncrdchar(v);
+ vncrdpoint(v); // desktop size
+ n = vncrdchar(v);
+ vncrdchar(v);
+ if(n == 0)
+ break;
+ vncrdlong(v); // id
+ r = vncrdrect(v);
+ vncrdlong(v); // flags
+ while(--n > 0){
+ vncrdlong(v);
+ vncrdrect(v);
+ vncrdlong(v);
+ }
+ qlock(&drawlock);
+ if(!rectclip(&r, gscreen->r)){
+ qunlock(&drawlock);
+ break;
+ }
+ gscreen->clipr = r;
+ qunlock(&drawlock);
+
+ screenwin();
+ deletescreenimage();
+ resetscreenimage();
+ break;
+
/* send keystroke */
case MKey:
keydown = vncrdchar(v);
@@ -905,7 +933,7 @@
{
Vncs *v;
- if(!rectclip(&r, gscreen->r))
+ if(!rectclip(&r, gscreen->clipr))
return;
qlock(&clients);
for(v=clients.head; v; v=v->next)
@@ -925,7 +953,7 @@
for(v=clients.head; v; v=v->next){
if(v->canwarp){
vnclock(v);
- v->needwarp = 1;
+ v->dowarp = 1;
v->warppt = p;
vncunlock(v);
}
@@ -940,7 +968,7 @@
static int
updateimage(Vncs *v)
{
- int i, ncount, nsend, docursor, needwarp;
+ int i, j, ncount, nsend, docursor, dowarp, doresize;
vlong ooffset;
Point warppt;
Rectangle cr;
@@ -949,20 +977,37 @@
int (*count)(Vncs*, Rectangle);
int (*send)(Vncs*, Rectangle);
- if(v->image == nil)
- return 0;
-
- /* warping info and unlock v so that updates can proceed */
- needwarp = v->canwarp && v->needwarp;
+ vnclock(v);
+ dowarp = v->canwarp && v->dowarp;
warppt = v->warppt;
- v->needwarp = 0;
+ v->dowarp = 0;
vncunlock(v);
/* copy the screen bits and then unlock the screen so updates can proceed */
- drawlock();
+ qlock(&drawlock);
rlist = v->rlist;
memset(&v->rlist, 0, sizeof v->rlist);
+ if(v->canresize && !eqrect(v->screen[0].rect, gscreen->clipr)){
+ v->screen[0].rect = gscreen->clipr;
+ v->dim = rectsubpt(gscreen->clipr, gscreen->clipr.min);
+ doresize = 1;
+ } else
+ doresize = 0;
+
+ if(doresize
+ || (v->image == nil && v->imagechan != 0)
+ || (v->image != nil && v->image->chan != v->imagechan)){
+ if(v->image)
+ freememimage(v->image);
+ v->image = allocmemimage(v->dim, v->imagechan);
+ if(v->image == nil){
+ fprint(2, "%V: allocmemimage: %r; hanging up\n", v);
+ qlock(&drawlock);
+ vnchungup(v);
+ }
+ }
+
/* if the cursor has moved or changed shape, we need to redraw its square */
lock(&cursor);
if(v->cursorver != cursorver || !eqpt(v->cursorpos, cursorpos)){
@@ -978,7 +1023,7 @@
if(docursor){
addtorlist(&rlist, v->cursorr);
- if(!rectclip(&cr, gscreen->r))
+ if(!rectclip(&cr, gscreen->clipr))
cr.max = cr.min;
addtorlist(&rlist, cr);
}
@@ -996,16 +1041,8 @@
v->cursorr = cr;
}
- drawunlock();
+ qunlock(&drawlock);
- ooffset = Boffset(&v->out);
- /* no more locks are held; talk to the client */
-
- if(rlist.nrect == 0 && needwarp == 0){
- vnclock(v);
- return 0;
- }
-
count = v->countrect;
send = v->sendrect;
if(count == nil || send == nil){
@@ -1014,17 +1051,46 @@
}
ncount = 0;
- for(i=0; i<rlist.nrect; i++)
- ncount += (*count)(v, rlist.rect[i]);
+ for(i=j=0; i<rlist.nrect; i++){
+ if(j < i)
+ rlist.rect[j] = rlist.rect[i];
+ if(rectclip(&rlist.rect[j], v->dim))
+ ncount += (*count)(v, rlist.rect[j++]);
+ }
+ rlist.nrect = j;
- if(verbose > 1)
- fprint(2, "sendupdate: rlist.nrect=%d, ncount=%d", rlist.nrect, ncount);
+ if(doresize == 0 && ncount == 0 && dowarp == 0)
+ return 0;
- t1 = nsec();
+ if(verbose > 1){
+ fprint(2, "sendupdate: rlist.nrect=%d, ncount=%d\n", rlist.nrect, ncount);
+ t1 = nsec();
+ ooffset = Boffset(&v->out);
+ }
+
+ if(doresize && v->canresize == 1){
+ doresize = 0;
+
+ vncwrchar(v, MFrameUpdate);
+ vncwrchar(v, 0);
+ vncwrshort(v, 1);
+ vncwrrect(v, v->dim);
+ vncwrlong(v, EncDesktopSize);
+ }
+
vncwrchar(v, MFrameUpdate);
vncwrchar(v, 0);
- vncwrshort(v, ncount+needwarp);
+ vncwrshort(v, doresize+ncount+dowarp);
+ if(doresize){
+ vncwrrect(v, gscreen->r);
+ vncwrlong(v, EncXDesktopSize);
+ vncwrlong(v, 1<<24);
+ vncwrlong(v, v->screen[0].id);
+ vncwrrect(v, v->screen[0].rect);
+ vncwrlong(v, v->screen[0].flags);
+ }
+
nsend = 0;
for(i=0; i<rlist.nrect; i++)
nsend += (*send)(v, rlist.rect[i]);
@@ -1034,17 +1100,17 @@
vnchungup(v);
}
- if(needwarp){
+ if(dowarp){
vncwrrect(v, Rect(warppt.x, warppt.y, warppt.x+1, warppt.y+1));
vncwrlong(v, EncMouseWarp);
}
- t1 = nsec() - t1;
- if(verbose > 1)
+ if(verbose > 1){
+ t1 = nsec() - t1;
fprint(2, " in %lldms, %lld bytes\n", t1/1000000, Boffset(&v->out) - ooffset);
+ }
freerlist(&rlist);
- vnclock(v);
return 1;
}
@@ -1059,13 +1125,11 @@
if(v->snarfvers == snarf.vers)
return;
- vncunlock(v);
qlock(&snarf);
len = snarf.n;
buf = malloc(len);
if(buf == nil){
qunlock(&snarf);
- vnclock(v);
return;
}
memmove(buf, snarf.buf, len);
@@ -1077,7 +1141,6 @@
vncwrlong(v, len);
vncwrbytes(v, buf, len);
free(buf);
- vnclock(v);
}
/*
@@ -1086,41 +1149,16 @@
static void
clientwriteproc(Vncs *v)
{
- char buf[32], buf2[32];
- int sent;
+ ulong last = 0;
vncname("write %V", v);
- for(;;){
- vnclock(v);
- if(v->ndead)
- break;
- if((v->image == nil && v->imagechan!=0)
- || (v->image && v->image->chan != v->imagechan)){
- if(v->image)
- freememimage(v->image);
- v->image = allocmemimage(v->dim, v->imagechan);
- if(v->image == nil){
- fprint(2, "%V: allocmemimage: %r; hanging up\n", v);
- vnchungup(v);
- }
- if(verbose)
- fprint(2, "%V: translating image from chan=%s to chan=%s\n",
- v, chantostr(buf, gscreen->chan), chantostr(buf2, v->imagechan));
- }
- sent = 0;
- if(v->updaterequest){
- v->updaterequest = 0;
- updatesnarf(v);
- sent = updateimage(v);
- if(!sent)
- v->updaterequest = 1;
- }
- vncunlock(v);
+ while(!v->ndead){
+ sleep(sleeptime);
+ updatesnarf(v);
+ if(v->updatereq != last && updateimage(v))
+ last++;
vncflush(v);
- if(!sent)
- sleep(sleeptime);
}
- vncunlock(v);
vnchungup(v);
}
--- a/sys/src/cmd/vnc/vncs.h
+++ b/sys/src/cmd/vnc/vncs.h
@@ -22,10 +22,11 @@
int (*sendrect)(Vncs*, Rectangle);
int copyrect;
int canwarp;
- int needwarp;
+ int dowarp;
Point warppt;
- int updaterequest;
+ ulong updatereq;
+
Rlist rlist;
int ndead;
int nproc;