This commit is contained in:
cinap_lenrek 2018-08-20 19:25:58 +02:00
commit f8f677b48e
9 changed files with 410 additions and 291 deletions

View file

@ -524,6 +524,7 @@ allocdimage(Memimage *i)
d->name = 0; d->name = 0;
d->vers = 0; d->vers = 0;
d->image = i; d->image = i;
d->dscreen = 0;
d->nfchar = 0; d->nfchar = 0;
d->fchar = 0; d->fchar = 0;
d->fromname = 0; d->fromname = 0;

View file

@ -13,7 +13,6 @@ enum{
Qcons, Qcons,
Qconsctl, Qconsctl,
Qsnarf, Qsnarf,
Qwinname,
}; };
static Dirtab consdir[]={ static Dirtab consdir[]={
@ -21,7 +20,6 @@ static Dirtab consdir[]={
"cons", {Qcons}, 0, 0660, "cons", {Qcons}, 0, 0660,
"consctl", {Qconsctl}, 0, 0220, "consctl", {Qconsctl}, 0, 0220,
"snarf", {Qsnarf}, 0, 0600, "snarf", {Qsnarf}, 0, 0600,
"winname", {Qwinname}, 0, 0000,
}; };
static Chan* static Chan*

View file

@ -14,6 +14,7 @@ enum
{ {
Qtopdir = 0, Qtopdir = 0,
Qnew, Qnew,
Qwinname,
Q3rd, Q3rd,
Q2nd, Q2nd,
Qcolormap, Qcolormap,
@ -35,6 +36,7 @@ enum
#define NHASH (1<<5) #define NHASH (1<<5)
#define HASHMASK (NHASH-1) #define HASHMASK (NHASH-1)
#define IOUNIT (64*1024)
typedef struct Client Client; typedef struct Client Client;
typedef struct Draw Draw; typedef struct Draw Draw;
@ -46,11 +48,8 @@ typedef struct Refresh Refresh;
typedef struct Refx Refx; typedef struct Refx Refx;
typedef struct DName DName; typedef struct DName DName;
ulong blanktime = 30; /* in minutes; a half hour */
struct Draw struct Draw
{ {
QLock;
int clientid; int clientid;
int nclient; int nclient;
Client** client; Client** client;
@ -58,9 +57,6 @@ struct Draw
DName* name; DName* name;
int vers; int vers;
int softscreen; int softscreen;
int blanked; /* screen turned off */
ulong blanktime; /* time of last operation */
ulong savemap[3*256];
}; };
struct Client struct Client
@ -70,6 +66,7 @@ struct Client
CScreen* cscreen; CScreen* cscreen;
Refresh* refresh; Refresh* refresh;
Rendez refrend; Rendez refrend;
QLock refq;
uchar* readdata; uchar* readdata;
int nreaddata; int nreaddata;
int busy; int busy;
@ -151,8 +148,13 @@ struct DScreen
}; };
static Draw sdraw; static Draw sdraw;
QLock drawlock;
static Memimage *screenimage; static Memimage *screenimage;
static Memdata screendata; static DImage* screendimage;
static char screenname[40];
static int screennameid;
static Rectangle flushrect; static Rectangle flushrect;
static int waste; static int waste;
static DScreen* dscreen; static DScreen* dscreen;
@ -161,6 +163,7 @@ extern void flushmemscreen(Rectangle);
void drawuninstall(Client*, int); void drawuninstall(Client*, int);
void drawfreedimage(DImage*); void drawfreedimage(DImage*);
Client* drawclientofpath(ulong); Client* drawclientofpath(ulong);
DImage* allocdimage(Memimage*);
static char Enodrawimage[] = "unknown id for draw image"; static char Enodrawimage[] = "unknown id for draw image";
static char Enodrawscreen[] = "unknown id for draw screen"; static char Enodrawscreen[] = "unknown id for draw screen";
@ -174,29 +177,28 @@ static char Ewriteoutside[] = "writeimage outside image";
static char Enotfont[] = "image not a font"; static char Enotfont[] = "image not a font";
static char Eindex[] = "character index out of range"; static char Eindex[] = "character index out of range";
static char Enoclient[] = "no such draw client"; static char Enoclient[] = "no such draw client";
static char Edepth[] = "image has bad depth";
static char Enameused[] = "image name in use"; static char Enameused[] = "image name in use";
static char Enoname[] = "no image with that name"; static char Enoname[] = "no image with that name";
static char Eoldname[] = "named image no longer valid"; static char Eoldname[] = "named image no longer valid";
static char Enamed[] = "image already has name"; static char Enamed[] = "image already has name";
static char Ewrongname[] = "wrong name for image"; static char Ewrongname[] = "wrong name for image";
void static void
drawlock(void) dlock(void)
{ {
qlock(&sdraw); qlock(&drawlock);
} }
void static int
drawunlock(void) candlock(void)
{ {
qunlock(&sdraw); return canqlock(&drawlock);
} }
int static void
candrawlock(void) dunlock(void)
{ {
return canqlock(&sdraw); qunlock(&drawlock);
} }
static int static int
@ -226,7 +228,7 @@ drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
devdir(c, q, up->genbuf, 0, eve, 0500, dp); devdir(c, q, up->genbuf, 0, eve, 0500, dp);
break; break;
default: default:
panic("drawwalk %#llux", c->qid.path); panic("drawwalk %llux", c->qid.path);
} }
return 1; return 1;
} }
@ -235,15 +237,17 @@ drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
* Top level directory contains the name of the device. * Top level directory contains the name of the device.
*/ */
t = QID(c->qid); t = QID(c->qid);
if(t == Qtopdir){ if(t == Qtopdir || t == Qwinname){
switch(s){ if(s == 1 || t == Qwinname){
case 0: mkqid(&q, Qwinname, 0, QTFILE);
devdir(c, q, "winname", 0, eve, 0444, dp);
}
else if(s == 0){
mkqid(&q, Q2nd, 0, QTDIR); mkqid(&q, Q2nd, 0, QTDIR);
devdir(c, q, "draw", 0, eve, 0555, dp); devdir(c, q, "draw", 0, eve, 0555, dp);
break;
default:
return -1;
} }
else
return -1;
return 1; return 1;
} }
@ -272,7 +276,7 @@ drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
/* /*
* Third level. * 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.vers = c->qid.vers;
q.type = QTFILE; q.type = QTFILE;
switch(s){ switch(s){
@ -320,14 +324,13 @@ drawrefreshscreen(DImage *l, Client *client)
static static
void void
drawrefresh(Memimage *l, Rectangle r, void *v) drawrefresh(Memimage*, Rectangle r, void *v)
{ {
Refx *x; Refx *x;
DImage *d; DImage *d;
Client *c; Client *c;
Refresh *ref; Refresh *ref;
USED(l);
if(v == 0) if(v == 0)
return; return;
x = v; x = v;
@ -353,9 +356,8 @@ addflush(Rectangle r)
int abb, ar, anbb; int abb, ar, anbb;
Rectangle nbb; Rectangle nbb;
if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r)) if(sdraw.softscreen==0 || screenimage == nil || !rectclip(&r, screenimage->r))
return; return;
if(flushrect.min.x >= flushrect.max.x){ if(flushrect.min.x >= flushrect.max.x){
flushrect = r; flushrect = r;
waste = 0; waste = 0;
@ -393,6 +395,7 @@ addflush(Rectangle r)
return; return;
} }
/* emit current state */ /* emit current state */
if(flushrect.min.x < flushrect.max.x)
flushmemscreen(flushrect); flushmemscreen(flushrect);
flushrect = r; flushrect = r;
waste = 0; waste = 0;
@ -409,8 +412,7 @@ dstflush(int dstid, Memimage *dst, Rectangle r)
addflush(r); // for VNC, see comments in addflush addflush(r); // for VNC, see comments in addflush
return; return;
} }
l = dst->layer; if(screenimage == nil || dst == nil || (l = dst->layer) == nil)
if(l == nil)
return; return;
do{ do{
if(l->screen->image->data != screenimage->data) if(l->screen->image->data != screenimage->data)
@ -421,10 +423,10 @@ dstflush(int dstid, Memimage *dst, Rectangle r)
addflush(r); addflush(r);
} }
static
void void
drawflush(void) drawflush(void)
{ {
if(screenimage && flushrect.min.x < flushrect.max.x)
flushmemscreen(flushrect); flushmemscreen(flushrect);
flushrect = Rect(10000, 10000, -10000, -10000); flushrect = Rect(10000, 10000, -10000, -10000);
} }
@ -517,22 +519,34 @@ drawlookupscreen(Client *client, int id, CScreen **cs)
return 0; return 0;
} }
Memimage* DImage*
drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen) allocdimage(Memimage *i)
{ {
DImage *d; DImage *d;
d = malloc(sizeof(DImage)); d = malloc(sizeof(DImage));
if(d == 0) if(d == 0)
return 0; return 0;
d->id = id;
d->ref = 1; d->ref = 1;
d->name = 0; d->name = 0;
d->vers = 0; d->vers = 0;
d->image = i; d->image = i;
d->dscreen = 0;
d->nfchar = 0; d->nfchar = 0;
d->fchar = 0; d->fchar = 0;
d->fromname = 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->dscreen = dscreen;
d->next = client->dimage[id&HASHMASK]; d->next = client->dimage[id&HASHMASK];
client->dimage[id&HASHMASK] = d; client->dimage[id&HASHMASK] = d;
@ -595,6 +609,7 @@ drawdelname(DName *name)
{ {
int i; int i;
free(name->name);
i = name-sdraw.name; i = name-sdraw.name;
memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName)); memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
sdraw.nname--; sdraw.nname--;
@ -656,12 +671,10 @@ drawfreedimage(DImage *dimage)
drawfreedimage(dimage->fromname); drawfreedimage(dimage->fromname);
goto Return; goto Return;
} }
if(dimage->image == screenimage) /* don't free the display */
goto Return;
ds = dimage->dscreen; ds = dimage->dscreen;
if(ds){ if(ds){
l = dimage->image; l = dimage->image;
if(l->data == screenimage->data) if(screenimage && l->data == screenimage->data)
addflush(l->layer->screenr); addflush(l->layer->screenr);
if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */ if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
free(l->layer->refreshptr); free(l->layer->refreshptr);
@ -856,11 +869,12 @@ drawpoint(Point *p, uchar *a)
} }
Point 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; FChar *fc;
Rectangle r; Rectangle r;
Point sp1; Point sp1;
static Memimage *tmp;
fc = &font->fchar[index]; fc = &font->fchar[index];
r.min.x = p.x+fc->left; r.min.x = p.x+fc->left;
@ -869,69 +883,143 @@ drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int ind
r.max.y = r.min.y+(fc->maxy-fc->miny); r.max.y = r.min.y+(fc->maxy-fc->miny);
sp1.x = sp->x+fc->left; sp1.x = sp->x+fc->left;
sp1.y = sp->y+fc->miny; sp1.y = sp->y+fc->miny;
/*
* 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); memdraw(dst, r, src, sp1, font->image, Pt(fc->minx, fc->miny), op);
}
p.x += fc->width; p.x += fc->width;
sp->x += fc->width; sp->x += fc->width;
return p; return p;
} }
static int static DImage*
initscreenimage(void) makescreenimage(void)
{ {
int width, depth; int width, depth;
ulong chan; ulong chan;
DImage *di;
Memdata *md;
Memimage *i;
Rectangle r; 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) if(screenimage != nil)
return 1; return 1;
screendata.base = nil; screendimage = makescreenimage();
screendata.bdata = attachscreen(&r, &chan, &depth, &width, &sdraw.softscreen); if(screendimage == nil)
if(screendata.bdata == nil)
{fprint(2, "bad bdata\n");
return 0; return 0;
} screenimage = screendimage->image;
screendata.ref = 1; // iprint("initscreenimage %p %p\n", screendimage, screenimage);
mouseresize();
screenimage = allocmemimaged(r, chan, &screendata);
if(screenimage == nil){
fprint(2, "bad memimaged: %r\n");
/* RSC: BUG: detach screen */
return 0;
}
screenimage->width = width;
screenimage->clipr = screenimage->r;
return 1; return 1;
} }
void void
deletescreenimage(void) deletescreenimage(void)
{ {
qlock(&sdraw); dlock();
/* RSC: BUG: detach screen */ if(screenimage){
if(screenimage) /* will be freed via screendimage; disable */
freememimage(screenimage); screenimage->clipr = ZR;
screenimage = nil; screenimage = nil;
qunlock(&sdraw); }
if(screendimage){
drawfreedimage(screendimage);
screendimage = nil;
}
dunlock();
} }
Chan* void
resetscreenimage(void)
{
dlock();
initscreenimage();
dunlock();
}
static Chan*
drawattach(char *spec) drawattach(char *spec)
{ {
qlock(&sdraw); dlock();
if(!initscreenimage()){ if(!initscreenimage()){
qunlock(&sdraw); dunlock();
error("no frame buffer"); error("no frame buffer");
} }
qunlock(&sdraw); dunlock();
return devattach('i', spec); return devattach('i', spec);
} }
Walkqid* static Walkqid*
drawwalk(Chan *c, Chan *nc, char **name, int nname) drawwalk(Chan *c, Chan *nc, char **name, int nname)
{ {
if(screendata.bdata == nil) if(screenimage == nil)
error("no frame buffer"); error("no frame buffer");
return devwalk(c, nc, name, nname, 0, 0, drawgen); return devwalk(c, nc, name, nname, 0, 0, drawgen);
} }
@ -946,13 +1034,17 @@ static Chan*
drawopen(Chan *c, int omode) drawopen(Chan *c, int omode)
{ {
Client *cl; Client *cl;
DName *dn;
DImage *di;
if(c->qid.type & QTDIR) if(c->qid.type & QTDIR){
return devopen(c, omode, 0, 0, drawgen); c = devopen(c, omode, 0, 0, drawgen);
c->iounit = IOUNIT;
}
qlock(&sdraw); dlock();
if(waserror()){ if(waserror()){
qunlock(&sdraw); dunlock();
nexterror(); nexterror();
} }
@ -964,6 +1056,9 @@ drawopen(Chan *c, int omode)
} }
switch(QID(c->qid)){ switch(QID(c->qid)){
case Qwinname:
break;
case Qnew: case Qnew:
break; break;
@ -973,9 +1068,22 @@ drawopen(Chan *c, int omode)
error(Einuse); error(Einuse);
cl->busy = 1; cl->busy = 1;
flushrect = Rect(10000, 10000, -10000, -10000); 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); incref(&cl->r);
break; break;
case Qcolormap: case Qcolormap:
case Qdata: case Qdata:
case Qrefresh: case Qrefresh:
@ -983,11 +1091,12 @@ drawopen(Chan *c, int omode)
incref(&cl->r); incref(&cl->r);
break; break;
} }
qunlock(&sdraw); dunlock();
poperror(); poperror();
c->mode = openmode(omode); c->mode = openmode(omode);
c->flag |= COPEN; c->flag |= COPEN;
c->offset = 0; c->offset = 0;
c->iounit = IOUNIT;
return c; return c;
} }
@ -999,11 +1108,11 @@ drawclose(Chan *c)
Client *cl; Client *cl;
Refresh *r; Refresh *r;
if(c->qid.type & QTDIR) if(QID(c->qid) < Qcolormap) /* Qtopdir, Qnew, Q3rd, Q2nd have no client */
return; return;
qlock(&sdraw); dlock();
if(waserror()){ if(waserror()){
qunlock(&sdraw); dunlock();
nexterror(); nexterror();
} }
@ -1036,7 +1145,7 @@ drawclose(Chan *c)
drawflush(); /* to erase visible, now dead windows */ drawflush(); /* to erase visible, now dead windows */
free(cl); free(cl);
} }
qunlock(&sdraw); dunlock();
poperror(); poperror();
} }
@ -1053,13 +1162,15 @@ drawread(Chan *c, void *a, long n, vlong off)
ulong offset = off; ulong offset = off;
char buf[16]; char buf[16];
USED(offset);
if(c->qid.type & QTDIR) if(c->qid.type & QTDIR)
return devdirread(c, a, n, 0, 0, drawgen); return devdirread(c, a, n, 0, 0, drawgen);
if(QID(c->qid) == Qwinname)
return readstr(off, a, n, screenname);
cl = drawclient(c); cl = drawclient(c);
qlock(&sdraw); dlock();
if(waserror()){ if(waserror()){
qunlock(&sdraw); dunlock();
nexterror(); nexterror();
} }
switch(QID(c->qid)){ switch(QID(c->qid)){
@ -1078,15 +1189,15 @@ drawread(Chan *c, void *a, long n, vlong off)
error(Enodrawimage); error(Enodrawimage);
i = di->image; 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, 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->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); i->clipr.min.x, i->clipr.min.y, i->clipr.max.x, i->clipr.max.y);
((char*)a)[n++] = ' ';
cl->infoid = -1; cl->infoid = -1;
break; break;
case Qcolormap: case Qcolormap:
drawactive(1); /* to restore map from backup */
p = malloc(4*12*256+1); p = malloc(4*12*256+1);
if(p == 0) if(p == 0)
error(Enomem); error(Enomem);
@ -1116,14 +1227,21 @@ drawread(Chan *c, void *a, long n, vlong off)
for(;;){ for(;;){
if(cl->refreshme || cl->refresh) if(cl->refreshme || cl->refresh)
break; break;
qunlock(&sdraw); dunlock();
if(waserror()){ if(waserror()){
qlock(&sdraw); /* restore lock for waserror() above */ dlock();
nexterror();
}
qlock(&cl->refq);
if(waserror()){
qunlock(&cl->refq);
nexterror(); nexterror();
} }
rendsleep(&cl->refrend, drawrefactive, cl); rendsleep(&cl->refrend, drawrefactive, cl);
poperror(); poperror();
qlock(&sdraw); qunlock(&cl->refq);
poperror();
dlock();
} }
p = a; p = a;
while(cl->refresh && n>=5*4){ while(cl->refresh && n>=5*4){
@ -1140,8 +1258,9 @@ drawread(Chan *c, void *a, long n, vlong off)
} }
cl->refreshme = 0; cl->refreshme = 0;
n = p-(uchar*)a; n = p-(uchar*)a;
break;
} }
qunlock(&sdraw); dunlock();
poperror(); poperror();
return n; return n;
} }
@ -1160,21 +1279,19 @@ drawwakeall(void)
} }
static long 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; char buf[128], *fields[4], *q;
Client *cl; Client *cl;
int i, m, red, green, blue, x; int i, m, red, green, blue, x;
ulong offset = off;
USED(offset);
if(c->qid.type & QTDIR) if(c->qid.type & QTDIR)
error(Eisdir); error(Eisdir);
cl = drawclient(c); cl = drawclient(c);
qlock(&sdraw); dlock();
if(waserror()){ if(waserror()){
drawwakeall(); drawwakeall();
qunlock(&sdraw); dunlock();
nexterror(); nexterror();
} }
switch(QID(c->qid)){ switch(QID(c->qid)){
@ -1185,7 +1302,6 @@ drawwrite(Chan *c, void *a, long n, vlong off)
break; break;
case Qcolormap: case Qcolormap:
drawactive(1); /* to restore map from backup */
m = n; m = n;
n = 0; n = 0;
while(m > 0){ while(m > 0){
@ -1200,7 +1316,7 @@ drawwrite(Chan *c, void *a, long n, vlong off)
a = (char*)a + i; a = (char*)a + i;
m -= i; m -= i;
*q = 0; *q = 0;
if(getfields(buf, fields, nelem(fields), 1, " ") != 4) if(tokenize(buf, fields, nelem(fields)) != 4)
error(Ebadarg); error(Ebadarg);
i = strtoul(fields[0], 0, 0); i = strtoul(fields[0], 0, 0);
red = strtoul(fields[1], 0, 0); red = strtoul(fields[1], 0, 0);
@ -1228,7 +1344,7 @@ drawwrite(Chan *c, void *a, long n, vlong off)
default: default:
error(Ebadusefd); error(Ebadusefd);
} }
qunlock(&sdraw); dunlock();
poperror(); poperror();
return n; return n;
} }
@ -1265,7 +1381,7 @@ printmesg(char *fmt, uchar *a, int plsprnt)
char *p, *q; char *p, *q;
int s; int s;
if(1||plsprnt==0){ if(1|| plsprnt==0){
SET(s,q,p); SET(s,q,p);
USED(fmt, a, buf, p, q, s); USED(fmt, a, buf, p, q, s);
return; return;
@ -1305,7 +1421,7 @@ printmesg(char *fmt, uchar *a, int plsprnt)
} }
*q++ = '\n'; *q++ = '\n';
*q = 0; *q = 0;
fprint(2, "%.*s", (int)(q-buf), buf); // iprint("%.*s", (int)(q-buf), buf);
} }
void void
@ -1317,7 +1433,7 @@ drawmesg(Client *client, void *av, int n)
ulong value, chan; ulong value, chan;
Rectangle r, clipr; Rectangle r, clipr;
Point p, q, *pp, sp; Point p, q, *pp, sp;
Memimage *i, *dst, *src, *mask; Memimage *i, *bg, *dst, *src, *mask;
Memimage *l, **lp; Memimage *l, **lp;
Memscreen *scrn; Memscreen *scrn;
DImage *font, *ll, *di, *ddst, *dsrc; DImage *font, *ll, *di, *ddst, *dsrc;
@ -1333,6 +1449,7 @@ drawmesg(Client *client, void *av, int n)
fmt = nil; fmt = nil;
if(waserror()){ if(waserror()){
if(fmt) printmesg(fmt, a, 1); if(fmt) printmesg(fmt, a, 1);
/* iprint("error: %s\n", up->errstr); */
nexterror(); nexterror();
} }
while((n-=m) > 0){ while((n-=m) > 0){
@ -1445,7 +1562,7 @@ drawmesg(Client *client, void *av, int n)
if(ddst == nil) if(ddst == nil)
error(Enodrawimage); error(Enodrawimage);
if(ddst->name) if(ddst->name)
error("can't change repl/clipr of shared image"); error("cannot change repl/clipr of shared image");
dst = ddst->image; dst = ddst->image;
if(a[5]) if(a[5])
dst->flags |= Frepl; dst->flags |= Frepl;
@ -1543,14 +1660,16 @@ drawmesg(Client *client, void *av, int n)
error(Eshortdraw); error(Eshortdraw);
dstid = BGLONG(a+1); dstid = BGLONG(a+1);
if(dstid == 0) if(dstid == 0)
error("can't use display as font"); error("cannot use display as font");
font = drawlookup(client, dstid, 1); font = drawlookup(client, dstid, 1);
if(font == 0) if(font == 0)
error(Enodrawimage); error(Enodrawimage);
if(font->image->layer) if(font->image->layer)
error("can't use window as font"); error("cannot use window as font");
free(font->fchar); /* should we complain if non-zero? */
ni = BGLONG(a+5); 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)); font->fchar = malloc(ni*sizeof(FChar));
if(font->fchar == 0) if(font->fchar == 0)
error("no memory for font"); error("no memory for font");
@ -1647,7 +1766,7 @@ drawmesg(Client *client, void *av, int n)
error(Edrawmem); error(Edrawmem);
di = drawlookup(client, dstid, 0); di = drawlookup(client, dstid, 0);
if(di == 0) if(di == 0)
error("draw: can't happen"); error("draw: cannot happen");
di->vers = dn->vers; di->vers = dn->vers;
di->name = smalloc(j+1); di->name = smalloc(j+1);
di->fromname = dn->dimage; di->fromname = dn->dimage;
@ -1748,7 +1867,7 @@ drawmesg(Client *client, void *av, int n)
if(pp == nil) if(pp == nil)
error(Enomem); error(Enomem);
doflush = 0; 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 */ doflush = 1; /* simplify test in loop */
ox = oy = 0; ox = oy = 0;
esize = 0; esize = 0;
@ -1803,8 +1922,6 @@ drawmesg(Client *client, void *av, int n)
if(n < m) if(n < m)
error(Eshortdraw); error(Eshortdraw);
i = drawimage(client, a+1); i = drawimage(client, a+1);
if(0 && i->layer)
error("readimage from window unimplemented");
drawrectangle(&r, a+5); drawrectangle(&r, a+5);
if(!rectinrect(r, i->r)) if(!rectinrect(r, i->r))
error(Ereadoutside); error(Ereadoutside);
@ -1814,7 +1931,7 @@ drawmesg(Client *client, void *av, int n)
client->readdata = mallocz(c, 0); client->readdata = mallocz(c, 0);
if(client->readdata == nil) if(client->readdata == nil)
error("readimage malloc failed"); error("readimage malloc failed");
client->nreaddata = unloadmemimage(i, r, client->readdata, c); client->nreaddata = memunload(i, r, client->readdata, c);
if(client->nreaddata < 0){ if(client->nreaddata < 0){
free(client->readdata); free(client->readdata);
client->readdata = nil; client->readdata = nil;
@ -1852,9 +1969,10 @@ drawmesg(Client *client, void *av, int n)
clipr = dst->clipr; clipr = dst->clipr;
dst->clipr = r; dst->clipr = r;
op = drawclientop(client); op = drawclientop(client);
bg = dst;
if(*a == 'x'){ if(*a == 'x'){
/* paint background */ /* paint background */
l = drawimage(client, a+47); bg = drawimage(client, a+47);
drawpoint(&q, a+51); drawpoint(&q, a+51);
r.min.x = p.x; r.min.x = p.x;
r.min.y = p.y-font->ascent; r.min.y = p.y-font->ascent;
@ -1870,7 +1988,7 @@ drawmesg(Client *client, void *av, int n)
r.max.x += font->fchar[ci].width; r.max.x += font->fchar[ci].width;
u += 2; u += 2;
} }
memdraw(dst, r, l, q, memopaque, ZP, op); memdraw(dst, r, bg, q, memopaque, ZP, op);
u -= 2*ni; u -= 2*ni;
} }
q = p; q = p;
@ -1880,7 +1998,7 @@ drawmesg(Client *client, void *av, int n)
dst->clipr = clipr; dst->clipr = clipr;
error(Eindex); error(Eindex);
} }
q = drawchar(dst, q, src, &sp, font, ci, op); q = drawchar(dst, bg, q, src, &sp, font, ci, op);
u += 2; u += 2;
} }
dst->clipr = clipr; dst->clipr = clipr;
@ -1938,7 +2056,7 @@ drawmesg(Client *client, void *av, int n)
memltofrontn(lp, nw); memltofrontn(lp, nw);
else else
memltorearn(lp, nw); 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++) for(j=0; j<nw; j++)
addflush(lp[j]->layer->screenr); addflush(lp[j]->layer->screenr);
ll = drawlookup(client, BGLONG(a+1+1+2), 1); ll = drawlookup(client, BGLONG(a+1+1+2), 1);
@ -2009,7 +2127,6 @@ drawcmap(void)
int num, den; int num, den;
int i, j; int i, j;
drawactive(1); /* to restore map from backup */
for(r=0,i=0; r!=4; r++) for(r=0,i=0; r!=4; r++)
for(v=0; v!=4; v++,i+=16){ for(v=0; v!=4; v++,i+=16){
for(g=0,j=v-r; g!=4; g++) for(g=0,j=v-r; g!=4; g++)
@ -2032,53 +2149,3 @@ drawcmap(void)
} }
} }
} }
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++;
}

View file

@ -27,6 +27,7 @@ struct Mouseinfo
ulong lastcounter; /* value when /dev/mouse read */ ulong lastcounter; /* value when /dev/mouse read */
Rendez r; Rendez r;
Ref; Ref;
int resize;
int open; int open;
Mousestate queue[16]; /* circular buffer of click events */ Mousestate queue[16]; /* circular buffer of click events */
ulong ri; /* read index into queue */ ulong ri; /* read index into queue */
@ -195,6 +196,10 @@ mouseread(Chan *c, void *va, long n, vlong off)
m.xy.x, m.xy.y, m.buttons, m.msec); m.xy.x, m.xy.y, m.buttons, m.msec);
mouse.lastcounter = m.counter; mouse.lastcounter = m.counter;
if(mouse.resize){
mouse.resize = 0;
buf[0] = 'r';
}
if(n > 1+4*12) if(n > 1+4*12)
n = 1+4*12; n = 1+4*12;
@ -321,7 +326,7 @@ absmousetrack(int x, int y, int b, ulong msec)
int int
mousechanged(void*) mousechanged(void*)
{ {
return mouse.lastcounter != mouse.counter; return mouse.lastcounter != mouse.counter || mouse.resize != 0;
} }
Point Point
@ -329,3 +334,13 @@ mousexy(void)
{ {
return mouse.xy; return mouse.xy;
} }
/*
* notify reader that screen has been resized
*/
void
mouseresize(void)
{
mouse.resize = 1;
rendwakeup(&mouse.r);
}

View file

@ -260,9 +260,12 @@ dorectangle(Vnc *v)
case EncMouseWarp: case EncMouseWarp:
mousewarp(r.min); mousewarp(r.min);
return; return;
case EncDesktopSize:
v->canresize |= 1;
vncsetdim(v, r);
return;
case EncXDesktopSize: case EncXDesktopSize:
v->canresize = 1; v->canresize |= 2;
n = vncrdlong(v)>>24; n = vncrdlong(v)>>24;
if(n <= 0) if(n <= 0)
break; break;
@ -274,9 +277,7 @@ dorectangle(Vnc *v)
vncrdrect(v); vncrdrect(v);
vncrdlong(v); vncrdlong(v);
} }
/* wet floor */ vncsetdim(v, v->screen[0].rect);
case EncDesktopSize:
vncsetdim(v, r);
return; return;
} }

View file

@ -42,10 +42,7 @@ static Cursor screencursor;
void void
screeninit(int x, int y, char *chanstr) screeninit(int x, int y, char *chanstr)
{ {
Point p, q;
char *greet;
char buf[128]; char buf[128];
Memimage *grey;
Rectangle r; Rectangle r;
int chan; int chan;
@ -78,31 +75,33 @@ screeninit(int x, int y, char *chanstr)
error(buf); error(buf);
} }
drawlock();
/*
* set up goo for screenputs
*/
memdefont = getmemdefont();
back = memwhite;
conscol = memblack;
/* a lot of work to get a grey color */ /* a lot of work to get a grey color */
curscol = allocmemimage(Rect(0,0,1,1), RGBA32); curscol = allocmemimage(Rect(0,0,1,1), RGBA32);
curscol->flags |= Frepl; curscol->flags |= Frepl;
curscol->clipr = gscreen->r; curscol->clipr = gscreen->r;
memfillcolor(curscol, 0xff0000ff); memfillcolor(curscol, 0xff0000ff);
memfillcolor(gscreen, 0x444488FF); screenwin();
w = memdefont->info[' '].width; setcursor(&arrow);
}
void
screenwin(void)
{
Point p;
char *greet;
Memimage *grey;
qlock(&drawlock);
back = memwhite;
conscol = memblack;
memfillcolor(gscreen, 0x888844FF);
memdefont = getmemdefont();
h = memdefont->height; h = memdefont->height;
window.min = addpt(gscreen->r.min, Pt(20,20)); window = insetrect(gscreen->clipr, 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;
memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S);
window = insetrect(window, 4); window = insetrect(window, 4);
memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
@ -119,22 +118,18 @@ screeninit(int x, int y, char *chanstr)
greet = " Plan 9 Console "; greet = " Plan 9 Console ";
p = addpt(window.min, Pt(10, 0)); p = addpt(window.min, Pt(10, 0));
q = memsubfontwidth(memdefont, greet);
memimagestring(gscreen, p, conscol, ZP, memdefont, greet); memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
window.min.y += h+6; window.min.y += h+6;
curpos = window.min; curpos = window.min;
window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
flushmemscreen(gscreen->r); flushmemscreen(gscreen->r);
qunlock(&drawlock);
drawunlock();
setcursor(&arrow);
} }
uchar* uchar*
attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen) attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen)
{ {
*r = gscreen->r; *r = gscreen->clipr;
*d = gscreen->depth; *d = gscreen->depth;
*chan = gscreen->chan; *chan = gscreen->chan;
*width = gscreen->width; *width = gscreen->width;
@ -263,7 +258,7 @@ scroll(void)
memimagedraw(gscreen, r, gscreen, p, nil, p, S); memimagedraw(gscreen, r, gscreen, p, nil, p, S);
r = Rpt(Pt(window.min.x, window.max.y-o), window.max); r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
memimagedraw(gscreen, r, back, ZP, nil, ZP, S); memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
flushmemscreen(gscreen->r); flushmemscreen(gscreen->clipr);
curpos.y -= o; curpos.y -= o;
} }
@ -336,7 +331,7 @@ screenputs(char *s, int n)
static int nrb; static int nrb;
char *e; char *e;
drawlock(); qlock(&drawlock);
e = s + n; e = s + n;
while(s < e){ while(s < e){
rb[nrb++] = *s++; rb[nrb++] = *s++;
@ -347,5 +342,5 @@ screenputs(char *s, int n)
} }
} }
screenflush(); screenflush();
drawunlock(); qunlock(&drawlock);
} }

View file

@ -11,6 +11,7 @@ extern Memimage *gscreen;
extern int cursorver; extern int cursorver;
extern Point cursorpos; extern Point cursorpos;
void mouseresize(void);
Point mousexy(void); Point mousexy(void);
void cursoron(void); void cursoron(void);
void cursoroff(void); void cursoroff(void);
@ -19,16 +20,18 @@ void flushmemscreen(Rectangle r);
Rectangle cursorrect(void); Rectangle cursorrect(void);
void cursordraw(Memimage *dst, Rectangle r); void cursordraw(Memimage *dst, Rectangle r);
extern QLock drawlock;
void drawactive(int); void drawactive(int);
void drawlock(void);
void drawunlock(void);
int candrawlock(void);
void getcolor(ulong, ulong*, ulong*, ulong*); void getcolor(ulong, ulong*, ulong*, ulong*);
int setcolor(ulong, ulong, ulong, ulong); int setcolor(ulong, ulong, ulong, ulong);
#define TK2SEC(x) 0 #define TK2SEC(x) 0
extern void blankscreen(int); extern void blankscreen(int);
void screeninit(int x, int y, char *chanstr); void screeninit(int x, int y, char *chanstr);
void screenwin(void);
void absmousetrack(int x, int y, int b, ulong msec); void absmousetrack(int x, int y, int b, ulong msec);
uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*); uchar *attachscreen(Rectangle*, ulong*, int*, int*, int*);
void deletescreenimage(void);
void resetscreenimage(void);
void fsinit(char *mntpt, int x, int y, char *chanstr); void fsinit(char *mntpt, int x, int y, char *chanstr);
#define ishwimage(i) 0

View file

@ -571,7 +571,7 @@ vncaccept(Vncs *v)
if(!shared) if(!shared)
killclients(v); killclients(v);
v->dim = rectsubpt(gscreen->r, gscreen->r.min); v->dim = rectsubpt(gscreen->clipr, gscreen->clipr.min);
vncwrpoint(v, v->dim.max); vncwrpoint(v, v->dim.max);
if(verbose) if(verbose)
fprint(2, "%V: send screen size %R\n", v, v->dim); fprint(2, "%V: send screen size %R\n", v, v->dim);
@ -592,6 +592,8 @@ vncaccept(Vncs *v)
if(verbose) if(verbose)
fprint(2, "%V: handshaking done\n", v); fprint(2, "%V: handshaking done\n", v);
v->updatereq = 0;
switch(rfork(RFPROC|RFMEM)){ switch(rfork(RFPROC|RFMEM)){
case -1: case -1:
fprint(2, "%V: cannot fork: %r; hanging up\n", v); fprint(2, "%V: cannot fork: %r; hanging up\n", v);
@ -674,7 +676,10 @@ setencoding(Vncs *v)
v->canwarp = 1; v->canwarp = 1;
continue; continue;
case EncDesktopSize: case EncDesktopSize:
v->canresize |= 1;
continue;
case EncXDesktopSize: case EncXDesktopSize:
v->canresize |= 2;
continue; continue;
} }
if(v->countrect != nil) if(v->countrect != nil)
@ -710,9 +715,10 @@ setencoding(Vncs *v)
} }
if(verbose) 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->copyrect ? ", copyrect" : "",
v->canwarp ? ", canwarp" : ""); v->canwarp ? ", canwarp" : "",
v->canresize ? ", resize" : "");
} }
/* /*
@ -755,18 +761,40 @@ clientreadproc(Vncs *v)
case MFrameReq: case MFrameReq:
incremental = vncrdchar(v); incremental = vncrdchar(v);
r = vncrdrect(v); r = vncrdrect(v);
if(incremental){ if(!incremental){
vnclock(v); qlock(&drawlock); /* protects rlist */
v->updaterequest = 1;
vncunlock(v);
}else{
drawlock(); /* protects rlist */
vnclock(v); /* protects updaterequest */
v->updaterequest = 1;
addtorlist(&v->rlist, r); addtorlist(&v->rlist, r);
vncunlock(v); qunlock(&drawlock);
drawunlock();
} }
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; break;
/* send keystroke */ /* send keystroke */
@ -905,7 +933,7 @@ flushmemscreen(Rectangle r)
{ {
Vncs *v; Vncs *v;
if(!rectclip(&r, gscreen->r)) if(!rectclip(&r, gscreen->clipr))
return; return;
qlock(&clients); qlock(&clients);
for(v=clients.head; v; v=v->next) for(v=clients.head; v; v=v->next)
@ -925,7 +953,7 @@ mousewarpnote(Point p)
for(v=clients.head; v; v=v->next){ for(v=clients.head; v; v=v->next){
if(v->canwarp){ if(v->canwarp){
vnclock(v); vnclock(v);
v->needwarp = 1; v->dowarp = 1;
v->warppt = p; v->warppt = p;
vncunlock(v); vncunlock(v);
} }
@ -940,7 +968,7 @@ mousewarpnote(Point p)
static int static int
updateimage(Vncs *v) updateimage(Vncs *v)
{ {
int i, ncount, nsend, docursor, needwarp; int i, j, ncount, nsend, docursor, dowarp, doresize;
vlong ooffset; vlong ooffset;
Point warppt; Point warppt;
Rectangle cr; Rectangle cr;
@ -949,20 +977,37 @@ updateimage(Vncs *v)
int (*count)(Vncs*, Rectangle); int (*count)(Vncs*, Rectangle);
int (*send)(Vncs*, Rectangle); int (*send)(Vncs*, Rectangle);
if(v->image == nil) vnclock(v);
return 0; dowarp = v->canwarp && v->dowarp;
/* warping info and unlock v so that updates can proceed */
needwarp = v->canwarp && v->needwarp;
warppt = v->warppt; warppt = v->warppt;
v->needwarp = 0; v->dowarp = 0;
vncunlock(v); vncunlock(v);
/* copy the screen bits and then unlock the screen so updates can proceed */ /* copy the screen bits and then unlock the screen so updates can proceed */
drawlock(); qlock(&drawlock);
rlist = v->rlist; rlist = v->rlist;
memset(&v->rlist, 0, sizeof 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 */ /* if the cursor has moved or changed shape, we need to redraw its square */
lock(&cursor); lock(&cursor);
if(v->cursorver != cursorver || !eqpt(v->cursorpos, cursorpos)){ if(v->cursorver != cursorver || !eqpt(v->cursorpos, cursorpos)){
@ -978,7 +1023,7 @@ updateimage(Vncs *v)
if(docursor){ if(docursor){
addtorlist(&rlist, v->cursorr); addtorlist(&rlist, v->cursorr);
if(!rectclip(&cr, gscreen->r)) if(!rectclip(&cr, gscreen->clipr))
cr.max = cr.min; cr.max = cr.min;
addtorlist(&rlist, cr); addtorlist(&rlist, cr);
} }
@ -996,15 +1041,7 @@ updateimage(Vncs *v)
v->cursorr = cr; 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; count = v->countrect;
send = v->sendrect; send = v->sendrect;
@ -1014,16 +1051,45 @@ updateimage(Vncs *v)
} }
ncount = 0; ncount = 0;
for(i=0; i<rlist.nrect; i++) for(i=j=0; i<rlist.nrect; i++){
ncount += (*count)(v, rlist.rect[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) if(doresize == 0 && ncount == 0 && dowarp == 0)
fprint(2, "sendupdate: rlist.nrect=%d, ncount=%d", rlist.nrect, ncount); return 0;
if(verbose > 1){
fprint(2, "sendupdate: rlist.nrect=%d, ncount=%d\n", rlist.nrect, ncount);
t1 = nsec(); t1 = nsec();
ooffset = Boffset(&v->out);
}
if(doresize && v->canresize == 1){
doresize = 0;
vncwrchar(v, MFrameUpdate); vncwrchar(v, MFrameUpdate);
vncwrchar(v, 0); vncwrchar(v, 0);
vncwrshort(v, ncount+needwarp); vncwrshort(v, 1);
vncwrrect(v, v->dim);
vncwrlong(v, EncDesktopSize);
}
vncwrchar(v, MFrameUpdate);
vncwrchar(v, 0);
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; nsend = 0;
for(i=0; i<rlist.nrect; i++) for(i=0; i<rlist.nrect; i++)
@ -1034,17 +1100,17 @@ updateimage(Vncs *v)
vnchungup(v); vnchungup(v);
} }
if(needwarp){ if(dowarp){
vncwrrect(v, Rect(warppt.x, warppt.y, warppt.x+1, warppt.y+1)); vncwrrect(v, Rect(warppt.x, warppt.y, warppt.x+1, warppt.y+1));
vncwrlong(v, EncMouseWarp); vncwrlong(v, EncMouseWarp);
} }
if(verbose > 1){
t1 = nsec() - t1; t1 = nsec() - t1;
if(verbose > 1)
fprint(2, " in %lldms, %lld bytes\n", t1/1000000, Boffset(&v->out) - ooffset); fprint(2, " in %lldms, %lld bytes\n", t1/1000000, Boffset(&v->out) - ooffset);
}
freerlist(&rlist); freerlist(&rlist);
vnclock(v);
return 1; return 1;
} }
@ -1059,13 +1125,11 @@ updatesnarf(Vncs *v)
if(v->snarfvers == snarf.vers) if(v->snarfvers == snarf.vers)
return; return;
vncunlock(v);
qlock(&snarf); qlock(&snarf);
len = snarf.n; len = snarf.n;
buf = malloc(len); buf = malloc(len);
if(buf == nil){ if(buf == nil){
qunlock(&snarf); qunlock(&snarf);
vnclock(v);
return; return;
} }
memmove(buf, snarf.buf, len); memmove(buf, snarf.buf, len);
@ -1077,7 +1141,6 @@ updatesnarf(Vncs *v)
vncwrlong(v, len); vncwrlong(v, len);
vncwrbytes(v, buf, len); vncwrbytes(v, buf, len);
free(buf); free(buf);
vnclock(v);
} }
/* /*
@ -1086,41 +1149,16 @@ updatesnarf(Vncs *v)
static void static void
clientwriteproc(Vncs *v) clientwriteproc(Vncs *v)
{ {
char buf[32], buf2[32]; ulong last = 0;
int sent;
vncname("write %V", v); vncname("write %V", v);
for(;;){ while(!v->ndead){
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);
vncflush(v);
if(!sent)
sleep(sleeptime); sleep(sleeptime);
updatesnarf(v);
if(v->updatereq != last && updateimage(v))
last++;
vncflush(v);
} }
vncunlock(v);
vnchungup(v); vnchungup(v);
} }

View file

@ -22,10 +22,11 @@ struct Vncs
int (*sendrect)(Vncs*, Rectangle); int (*sendrect)(Vncs*, Rectangle);
int copyrect; int copyrect;
int canwarp; int canwarp;
int needwarp; int dowarp;
Point warppt; Point warppt;
int updaterequest; ulong updatereq;
Rlist rlist; Rlist rlist;
int ndead; int ndead;
int nproc; int nproc;