merge
This commit is contained in:
commit
f8f677b48e
9 changed files with 410 additions and 291 deletions
|
@ -524,6 +524,7 @@ allocdimage(Memimage *i)
|
|||
d->name = 0;
|
||||
d->vers = 0;
|
||||
d->image = i;
|
||||
d->dscreen = 0;
|
||||
d->nfchar = 0;
|
||||
d->fchar = 0;
|
||||
d->fromname = 0;
|
||||
|
|
|
@ -13,7 +13,6 @@ enum{
|
|||
Qcons,
|
||||
Qconsctl,
|
||||
Qsnarf,
|
||||
Qwinname,
|
||||
};
|
||||
|
||||
static Dirtab consdir[]={
|
||||
|
@ -21,7 +20,6 @@ static Dirtab consdir[]={
|
|||
"cons", {Qcons}, 0, 0660,
|
||||
"consctl", {Qconsctl}, 0, 0220,
|
||||
"snarf", {Qsnarf}, 0, 0600,
|
||||
"winname", {Qwinname}, 0, 0000,
|
||||
};
|
||||
|
||||
static Chan*
|
||||
|
|
|
@ -14,6 +14,7 @@ enum
|
|||
{
|
||||
Qtopdir = 0,
|
||||
Qnew,
|
||||
Qwinname,
|
||||
Q3rd,
|
||||
Q2nd,
|
||||
Qcolormap,
|
||||
|
@ -35,6 +36,7 @@ enum
|
|||
|
||||
#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 Refresh Refresh;
|
|||
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 @@ struct Client
|
|||
CScreen* cscreen;
|
||||
Refresh* refresh;
|
||||
Rendez refrend;
|
||||
QLock refq;
|
||||
uchar* readdata;
|
||||
int nreaddata;
|
||||
int busy;
|
||||
|
@ -95,10 +92,10 @@ struct Refx
|
|||
|
||||
struct DName
|
||||
{
|
||||
char *name;
|
||||
Client *client;
|
||||
char *name;
|
||||
Client *client;
|
||||
DImage* dimage;
|
||||
int vers;
|
||||
int vers;
|
||||
};
|
||||
|
||||
struct FChar
|
||||
|
@ -128,7 +125,7 @@ struct DImage
|
|||
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,16 +140,21 @@ struct DScreen
|
|||
int id;
|
||||
int public;
|
||||
int ref;
|
||||
DImage *dimage;
|
||||
DImage *dfill;
|
||||
DImage *dimage;
|
||||
DImage *dfill;
|
||||
Memscreen* screen;
|
||||
Client* owner;
|
||||
DScreen* next;
|
||||
};
|
||||
|
||||
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 @@ extern void flushmemscreen(Rectangle);
|
|||
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,29 +177,28 @@ static char Ewriteoutside[] = "writeimage outside image";
|
|||
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";
|
||||
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 @@ drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
|
|||
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 @@ drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
|
|||
* 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 @@ drawgen(Chan *c, Dirtab*, int, int s, Dir *dp)
|
|||
/*
|
||||
* 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,14 +324,13 @@ drawrefreshscreen(DImage *l, Client *client)
|
|||
|
||||
static
|
||||
void
|
||||
drawrefresh(Memimage *l, Rectangle r, void *v)
|
||||
drawrefresh(Memimage*, Rectangle r, void *v)
|
||||
{
|
||||
Refx *x;
|
||||
DImage *d;
|
||||
Client *c;
|
||||
Refresh *ref;
|
||||
|
||||
USED(l);
|
||||
if(v == 0)
|
||||
return;
|
||||
x = v;
|
||||
|
@ -353,9 +356,8 @@ addflush(Rectangle r)
|
|||
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 @@ addflush(Rectangle r)
|
|||
return;
|
||||
}
|
||||
/* emit current state */
|
||||
flushmemscreen(flushrect);
|
||||
if(flushrect.min.x < flushrect.max.x)
|
||||
flushmemscreen(flushrect);
|
||||
flushrect = r;
|
||||
waste = 0;
|
||||
}
|
||||
|
@ -409,8 +412,7 @@ dstflush(int dstid, Memimage *dst, Rectangle r)
|
|||
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 @@ dstflush(int dstid, Memimage *dst, Rectangle r)
|
|||
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,22 +519,34 @@ drawlookupscreen(Client *client, int id, CScreen **cs)
|
|||
return 0;
|
||||
}
|
||||
|
||||
Memimage*
|
||||
drawinstall(Client *client, int id, Memimage *i, DScreen *dscreen)
|
||||
DImage*
|
||||
allocdimage(Memimage *i)
|
||||
{
|
||||
DImage *d;
|
||||
|
||||
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 @@ drawdelname(DName *name)
|
|||
{
|
||||
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 *dimage)
|
|||
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 @@ drawpoint(Point *p, uchar *a)
|
|||
}
|
||||
|
||||
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 @@ drawchar(Memimage *dst, Point p, Memimage *src, Point *sp, DImage *font, int ind
|
|||
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;
|
||||
}
|
||||
screendata.ref = 1;
|
||||
|
||||
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;
|
||||
screenimage = screendimage->image;
|
||||
// iprint("initscreenimage %p %p\n", screendimage, screenimage);
|
||||
mouseresize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
deletescreenimage(void)
|
||||
{
|
||||
qlock(&sdraw);
|
||||
/* RSC: BUG: detach screen */
|
||||
if(screenimage)
|
||||
freememimage(screenimage);
|
||||
screenimage = nil;
|
||||
qunlock(&sdraw);
|
||||
dlock();
|
||||
if(screenimage){
|
||||
/* will be freed via screendimage; disable */
|
||||
screenimage->clipr = ZR;
|
||||
screenimage = nil;
|
||||
}
|
||||
if(screendimage){
|
||||
drawfreedimage(screendimage);
|
||||
screendimage = nil;
|
||||
}
|
||||
dunlock();
|
||||
}
|
||||
|
||||
Chan*
|
||||
void
|
||||
resetscreenimage(void)
|
||||
{
|
||||
dlock();
|
||||
initscreenimage();
|
||||
dunlock();
|
||||
}
|
||||
|
||||
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 @@ static Chan*
|
|||
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 @@ drawopen(Chan *c, int omode)
|
|||
}
|
||||
|
||||
switch(QID(c->qid)){
|
||||
case Qwinname:
|
||||
break;
|
||||
|
||||
case Qnew:
|
||||
break;
|
||||
|
||||
|
@ -973,9 +1068,22 @@ drawopen(Chan *c, int omode)
|
|||
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 @@ drawopen(Chan *c, int omode)
|
|||
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 @@ drawclose(Chan *c)
|
|||
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 @@ drawclose(Chan *c)
|
|||
drawflush(); /* to erase visible, now dead windows */
|
||||
free(cl);
|
||||
}
|
||||
qunlock(&sdraw);
|
||||
dunlock();
|
||||
poperror();
|
||||
}
|
||||
|
||||
|
@ -1053,13 +1162,15 @@ drawread(Chan *c, void *a, long n, vlong off)
|
|||
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 @@ drawread(Chan *c, void *a, long n, vlong off)
|
|||
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 @@ drawread(Chan *c, void *a, long n, vlong off)
|
|||
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 @@ drawread(Chan *c, void *a, long n, vlong off)
|
|||
}
|
||||
cl->refreshme = 0;
|
||||
n = p-(uchar*)a;
|
||||
break;
|
||||
}
|
||||
qunlock(&sdraw);
|
||||
dunlock();
|
||||
poperror();
|
||||
return n;
|
||||
}
|
||||
|
@ -1160,21 +1279,19 @@ drawwakeall(void)
|
|||
}
|
||||
|
||||
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 @@ drawwrite(Chan *c, void *a, long n, vlong off)
|
|||
break;
|
||||
|
||||
case Qcolormap:
|
||||
drawactive(1); /* to restore map from backup */
|
||||
m = n;
|
||||
n = 0;
|
||||
while(m > 0){
|
||||
|
@ -1200,7 +1316,7 @@ drawwrite(Chan *c, void *a, long n, vlong off)
|
|||
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 @@ drawwrite(Chan *c, void *a, long n, vlong off)
|
|||
default:
|
||||
error(Ebadusefd);
|
||||
}
|
||||
qunlock(&sdraw);
|
||||
dunlock();
|
||||
poperror();
|
||||
return n;
|
||||
}
|
||||
|
@ -1265,7 +1381,7 @@ printmesg(char *fmt, uchar *a, int plsprnt)
|
|||
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 @@ printmesg(char *fmt, uchar *a, int plsprnt)
|
|||
}
|
||||
*q++ = '\n';
|
||||
*q = 0;
|
||||
fprint(2, "%.*s", (int)(q-buf), buf);
|
||||
// iprint("%.*s", (int)(q-buf), buf);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1317,7 +1433,7 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawmesg(Client *client, void *av, int n)
|
|||
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 @@ drawcmap(void)
|
|||
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++)
|
||||
|
@ -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++;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ struct Mouseinfo
|
|||
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 @@ mouseread(Chan *c, void *va, long n, vlong off)
|
|||
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 @@ absmousetrack(int x, int y, int b, ulong msec)
|
|||
int
|
||||
mousechanged(void*)
|
||||
{
|
||||
return mouse.lastcounter != mouse.counter;
|
||||
return mouse.lastcounter != mouse.counter || mouse.resize != 0;
|
||||
}
|
||||
|
||||
Point
|
||||
|
@ -329,3 +334,13 @@ mousexy(void)
|
|||
{
|
||||
return mouse.xy;
|
||||
}
|
||||
|
||||
/*
|
||||
* notify reader that screen has been resized
|
||||
*/
|
||||
void
|
||||
mouseresize(void)
|
||||
{
|
||||
mouse.resize = 1;
|
||||
rendwakeup(&mouse.r);
|
||||
}
|
||||
|
|
|
@ -260,9 +260,12 @@ dorectangle(Vnc *v)
|
|||
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 @@ dorectangle(Vnc *v)
|
|||
vncrdrect(v);
|
||||
vncrdlong(v);
|
||||
}
|
||||
/* wet floor */
|
||||
case EncDesktopSize:
|
||||
vncsetdim(v, r);
|
||||
vncsetdim(v, v->screen[0].rect);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,10 +42,7 @@ static Cursor screencursor;
|
|||
void
|
||||
screeninit(int x, int y, char *chanstr)
|
||||
{
|
||||
Point p, q;
|
||||
char *greet;
|
||||
char buf[128];
|
||||
Memimage *grey;
|
||||
Rectangle r;
|
||||
int chan;
|
||||
|
||||
|
@ -78,31 +75,33 @@ screeninit(int x, int y, char *chanstr)
|
|||
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;
|
||||
curscol->clipr = gscreen->r;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 @@ screeninit(int x, int y, char *chanstr)
|
|||
|
||||
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 @@ scroll(void)
|
|||
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 @@ screenputs(char *s, int n)
|
|||
static int nrb;
|
||||
char *e;
|
||||
|
||||
drawlock();
|
||||
qlock(&drawlock);
|
||||
e = s + n;
|
||||
while(s < e){
|
||||
rb[nrb++] = *s++;
|
||||
|
@ -347,5 +342,5 @@ screenputs(char *s, int n)
|
|||
}
|
||||
}
|
||||
screenflush();
|
||||
drawunlock();
|
||||
qunlock(&drawlock);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ extern Memimage *gscreen;
|
|||
extern int cursorver;
|
||||
extern Point cursorpos;
|
||||
|
||||
void mouseresize(void);
|
||||
Point mousexy(void);
|
||||
void cursoron(void);
|
||||
void cursoroff(void);
|
||||
|
@ -19,16 +20,18 @@ void flushmemscreen(Rectangle r);
|
|||
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
|
||||
|
|
|
@ -571,7 +571,7 @@ vncaccept(Vncs *v)
|
|||
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 @@ vncaccept(Vncs *v)
|
|||
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 @@ setencoding(Vncs *v)
|
|||
v->canwarp = 1;
|
||||
continue;
|
||||
case EncDesktopSize:
|
||||
v->canresize |= 1;
|
||||
continue;
|
||||
case EncXDesktopSize:
|
||||
v->canresize |= 2;
|
||||
continue;
|
||||
}
|
||||
if(v->countrect != nil)
|
||||
|
@ -710,9 +715,10 @@ setencoding(Vncs *v)
|
|||
}
|
||||
|
||||
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,18 +761,40 @@ clientreadproc(Vncs *v)
|
|||
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 */
|
||||
|
@ -905,7 +933,7 @@ flushmemscreen(Rectangle r)
|
|||
{
|
||||
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 @@ mousewarpnote(Point p)
|
|||
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 @@ mousewarpnote(Point p)
|
|||
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 @@ updateimage(Vncs *v)
|
|||
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 @@ updateimage(Vncs *v)
|
|||
|
||||
if(docursor){
|
||||
addtorlist(&rlist, v->cursorr);
|
||||
if(!rectclip(&cr, gscreen->r))
|
||||
if(!rectclip(&cr, gscreen->clipr))
|
||||
cr.max = cr.min;
|
||||
addtorlist(&rlist, cr);
|
||||
}
|
||||
|
@ -996,15 +1041,7 @@ updateimage(Vncs *v)
|
|||
v->cursorr = cr;
|
||||
}
|
||||
|
||||
drawunlock();
|
||||
|
||||
ooffset = Boffset(&v->out);
|
||||
/* no more locks are held; talk to the client */
|
||||
|
||||
if(rlist.nrect == 0 && needwarp == 0){
|
||||
vnclock(v);
|
||||
return 0;
|
||||
}
|
||||
qunlock(&drawlock);
|
||||
|
||||
count = v->countrect;
|
||||
send = v->sendrect;
|
||||
|
@ -1014,16 +1051,45 @@ updateimage(Vncs *v)
|
|||
}
|
||||
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
t1 = nsec();
|
||||
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++)
|
||||
|
@ -1034,17 +1100,17 @@ updateimage(Vncs *v)
|
|||
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 @@ updatesnarf(Vncs *v)
|
|||
|
||||
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 @@ updatesnarf(Vncs *v)
|
|||
vncwrlong(v, len);
|
||||
vncwrbytes(v, buf, len);
|
||||
free(buf);
|
||||
vnclock(v);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1086,41 +1149,16 @@ updatesnarf(Vncs *v)
|
|||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,10 +22,11 @@ struct Vncs
|
|||
int (*sendrect)(Vncs*, Rectangle);
|
||||
int copyrect;
|
||||
int canwarp;
|
||||
int needwarp;
|
||||
int dowarp;
|
||||
Point warppt;
|
||||
|
||||
int updaterequest;
|
||||
ulong updatereq;
|
||||
|
||||
Rlist rlist;
|
||||
int ndead;
|
||||
int nproc;
|
||||
|
|
Loading…
Reference in a new issue