summaryrefslogtreecommitdiff
path: root/sys/src/cmd/vnc/devdraw.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2018-08-20 19:23:42 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2018-08-20 19:23:42 +0200
commitd2089f949edd71626e2391672b723aa2d9fbcb9b (patch)
tree0709ec4e1abfb8805f08ceb24587f6a8e84fddf6 /sys/src/cmd/vnc/devdraw.c
parent670137bf0a75813df93d9b727ce70ddb099d11e1 (diff)
vncs: support for desktop resize extension, update devdraw
Diffstat (limited to 'sys/src/cmd/vnc/devdraw.c')
-rw-r--r--sys/src/cmd/vnc/devdraw.c411
1 files changed, 239 insertions, 172 deletions
diff --git a/sys/src/cmd/vnc/devdraw.c b/sys/src/cmd/vnc/devdraw.c
index ba42fff0f..e8ec1dddf 100644
--- a/sys/src/cmd/vnc/devdraw.c
+++ b/sys/src/cmd/vnc/devdraw.c
@@ -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;
+ 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 @@ 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()){
+ dlock();
+ nexterror();
+ }
+ qlock(&cl->refq);
if(waserror()){
- qlock(&sdraw); /* restore lock for waserror() above */
+ 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++;
-}