aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/devdraw/devdraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/devdraw/devdraw.c')
-rw-r--r--src/cmd/devdraw/devdraw.c340
1 files changed, 108 insertions, 232 deletions
diff --git a/src/cmd/devdraw/devdraw.c b/src/cmd/devdraw/devdraw.c
index 654ab4af..e83f6f07 100644
--- a/src/cmd/devdraw/devdraw.c
+++ b/src/cmd/devdraw/devdraw.c
@@ -8,154 +8,32 @@
#include <draw.h>
#include <memdraw.h>
#include <memlayer.h>
+#include <mouse.h>
+#include <cursor.h>
+#include <keyboard.h>
+#include <drawfcall.h>
#include "devdraw.h"
extern void _flushmemscreen(Rectangle);
-int forcedpi = 0;
-int displaydpi = 100;
-
-#define NHASH (1<<5)
-#define HASHMASK (NHASH-1)
-
-typedef struct Client Client;
-typedef struct Draw Draw;
-typedef struct DImage DImage;
-typedef struct DScreen DScreen;
-typedef struct CScreen CScreen;
-typedef struct FChar FChar;
-typedef struct Refresh Refresh;
-typedef struct Refx Refx;
-typedef struct DName DName;
-
-struct Draw
-{
- QLock lk;
- int clientid;
- int nclient;
- Client* client[1];
- int nname;
- DName* name;
- int vers;
- int softscreen;
-};
-
-struct Client
-{
- /*Ref r;*/
- DImage* dimage[NHASH];
- CScreen* cscreen;
- Refresh* refresh;
- Rendez refrend;
- uchar* readdata;
- int nreaddata;
- int busy;
- int clientid;
- int slot;
- int refreshme;
- int infoid;
- int op;
-};
-
-struct Refresh
-{
- DImage* dimage;
- Rectangle r;
- Refresh* next;
-};
-
-struct Refx
-{
- Client* client;
- DImage* dimage;
-};
-
-struct DName
-{
- char *name;
- Client *client;
- DImage* dimage;
- int vers;
-};
-
-struct FChar
-{
- int minx; /* left edge of bits */
- int maxx; /* right edge of bits */
- uchar miny; /* first non-zero scan-line */
- uchar maxy; /* last non-zero scan-line + 1 */
- schar left; /* offset of baseline */
- uchar width; /* width of baseline */
-};
-
-/*
- * Reference counts in DImages:
- * one per open by original client
- * one per screen image or fill
- * one per image derived from this one by name
- */
-struct DImage
-{
- int id;
- int ref;
- char *name;
- int vers;
- Memimage* image;
- int ascent;
- int nfchar;
- FChar* fchar;
- DScreen* dscreen; /* 0 if not a window */
- DImage* fromname; /* image this one is derived from, by name */
- DImage* next;
-};
-
-struct CScreen
-{
- DScreen* dscreen;
- CScreen* next;
-};
-
-struct DScreen
-{
- int id;
- int public;
- int ref;
- DImage *dimage;
- DImage *dfill;
- Memscreen* screen;
- Client* owner;
- DScreen* next;
-};
static Draw sdraw;
-static Client *client0;
-static Memimage *screenimage;
-static Rectangle flushrect;
-static int waste;
-static DScreen* dscreen;
+Client *client0;
static int drawuninstall(Client*, int);
static Memimage* drawinstall(Client*, int, Memimage*, DScreen*);
-static void drawfreedimage(DImage*);
+static void drawfreedimage(Client*, DImage*);
void
-_initdisplaymemimage(Memimage *m)
+_initdisplaymemimage(Client *c, Memimage *m)
{
- screenimage = m;
+ c->screenimage = m;
m->screenref = 1;
- client0 = mallocz(sizeof(Client), 1);
- if(client0 == nil){
- fprint(2, "initdraw: allocating client0: out of memory");
- abort();
- }
- client0->slot = 0;
- client0->clientid = ++sdraw.clientid;
- client0->op = SoverD;
- sdraw.client[0] = client0;
- sdraw.nclient = 1;
- sdraw.softscreen = 1;
+ c->slot = 0;
+ c->clientid = 1;
+ c->op = SoverD;
}
void
-_drawreplacescreenimage(Memimage *m)
+_drawreplacescreenimage(Client *c, Memimage *m)
{
/*
* Replace the screen image because the screen
@@ -171,14 +49,17 @@ _drawreplacescreenimage(Memimage *m)
*/
Memimage *om;
+ qlock(&c->inputlk);
qlock(&sdraw.lk);
- om = screenimage;
- screenimage = m;
+ om = c->screenimage;
+ c->screenimage = m;
m->screenref = 1;
+ c->mouse.resized = 1;
if(om && --om->screenref == 0){
_freememimage(om);
}
qunlock(&sdraw.lk);
+ qunlock(&c->inputlk);
}
static
@@ -222,57 +103,57 @@ drawrefresh(Memimage *m, Rectangle r, void *v)
}
static void
-addflush(Rectangle r)
+addflush(Client *c, Rectangle r)
{
int abb, ar, anbb;
Rectangle nbb;
- if(sdraw.softscreen==0 || !rectclip(&r, screenimage->r))
+ if(/*sdraw.softscreen==0 ||*/ !rectclip(&r, c->screenimage->r))
return;
- if(flushrect.min.x >= flushrect.max.x){
- flushrect = r;
- waste = 0;
+ if(c->flushrect.min.x >= c->flushrect.max.x){
+ c->flushrect = r;
+ c->waste = 0;
return;
}
- nbb = flushrect;
+ nbb = c->flushrect;
combinerect(&nbb, r);
ar = Dx(r)*Dy(r);
- abb = Dx(flushrect)*Dy(flushrect);
+ abb = Dx(c->flushrect)*Dy(c->flushrect);
anbb = Dx(nbb)*Dy(nbb);
/*
* Area of new waste is area of new bb minus area of old bb,
* less the area of the new segment, which we assume is not waste.
* This could be negative, but that's OK.
*/
- waste += anbb-abb - ar;
- if(waste < 0)
- waste = 0;
+ c->waste += anbb-abb - ar;
+ if(c->waste < 0)
+ c->waste = 0;
/*
* absorb if:
* total area is small
* waste is less than half total area
* rectangles touch
*/
- if(anbb<=1024 || waste*2<anbb || rectXrect(flushrect, r)){
- flushrect = nbb;
+ if(anbb<=1024 || c->waste*2<anbb || rectXrect(c->flushrect, r)){
+ c->flushrect = nbb;
return;
}
/* emit current state */
- if(flushrect.min.x < flushrect.max.x)
- _flushmemscreen(flushrect);
- flushrect = r;
- waste = 0;
+ if(c->flushrect.min.x < c->flushrect.max.x)
+ _flushmemscreen(c->flushrect);
+ c->flushrect = r;
+ c->waste = 0;
}
static
void
-dstflush(int dstid, Memimage *dst, Rectangle r)
+dstflush(Client *c, int dstid, Memimage *dst, Rectangle r)
{
Memlayer *l;
if(dstid == 0){
- combinerect(&flushrect, r);
+ combinerect(&c->flushrect, r);
return;
}
/* how can this happen? -rsc, dec 12 2002 */
@@ -284,21 +165,21 @@ dstflush(int dstid, Memimage *dst, Rectangle r)
if(l == nil)
return;
do{
- if(l->screen->image->data != screenimage->data)
+ if(l->screen->image->data != c->screenimage->data)
return;
r = rectaddpt(r, l->delta);
l = l->screen->image->layer;
}while(l);
- addflush(r);
+ addflush(c, r);
}
static
void
-drawflush(void)
+drawflush(Client *c)
{
- if(flushrect.min.x < flushrect.max.x)
- _flushmemscreen(flushrect);
- flushrect = Rect(10000, 10000, -10000, -10000);
+ if(c->flushrect.min.x < c->flushrect.max.x)
+ _flushmemscreen(c->flushrect);
+ c->flushrect = Rect(10000, 10000, -10000, -10000);
}
static
@@ -312,12 +193,12 @@ drawcmp(char *a, char *b, int n)
static
DName*
-drawlookupname(int n, char *str)
+drawlookupname(Client *client, int n, char *str)
{
DName *name, *ename;
- name = sdraw.name;
- ename = &name[sdraw.nname];
+ name = client->name;
+ ename = &name[client->nname];
for(; name<ename; name++)
if(drawcmp(name->name, str, n) == 0)
return name;
@@ -326,18 +207,18 @@ drawlookupname(int n, char *str)
static
int
-drawgoodname(DImage *d)
+drawgoodname(Client *client, DImage *d)
{
DName *n;
/* if window, validate the screen's own images */
if(d->dscreen)
- if(drawgoodname(d->dscreen->dimage) == 0
- || drawgoodname(d->dscreen->dfill) == 0)
+ if(drawgoodname(client, d->dscreen->dimage) == 0
+ || drawgoodname(client, d->dscreen->dfill) == 0)
return 0;
if(d->name == nil)
return 1;
- n = drawlookupname(strlen(d->name), d->name);
+ n = drawlookupname(client, strlen(d->name), d->name);
if(n==nil || n->vers!=d->vers)
return 0;
return 1;
@@ -356,7 +237,7 @@ drawlookup(Client *client, int id, int checkname)
* BUG: should error out but too hard.
* Return 0 instead.
*/
- if(checkname && !drawgoodname(d))
+ if(checkname && !drawgoodname(client, d))
return 0;
return d;
}
@@ -367,11 +248,11 @@ drawlookup(Client *client, int id, int checkname)
static
DScreen*
-drawlookupdscreen(int id)
+drawlookupdscreen(Client *c, int id)
{
DScreen *s;
- s = dscreen;
+ s = c->dscreen;
while(s){
if(s->id == id)
return s;
@@ -466,9 +347,9 @@ drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *df
d->id = id;
d->screen = s;
d->public = public;
- d->next = dscreen;
+ d->next = client->dscreen;
d->owner = client;
- dscreen = d;
+ client->dscreen = d;
}
c->dscreen = d;
d->ref++;
@@ -479,18 +360,18 @@ drawinstallscreen(Client *client, DScreen *d, int id, DImage *dimage, DImage *df
static
void
-drawdelname(DName *name)
+drawdelname(Client *client, DName *name)
{
int i;
- i = name-sdraw.name;
- memmove(name, name+1, (sdraw.nname-(i+1))*sizeof(DName));
- sdraw.nname--;
+ i = name-client->name;
+ memmove(name, name+1, (client->nname-(i+1))*sizeof(DName));
+ client->nname--;
}
static
void
-drawfreedscreen(DScreen *this)
+drawfreedscreen(Client *client, DScreen *this)
{
DScreen *ds, *next;
@@ -499,9 +380,9 @@ drawfreedscreen(DScreen *this)
fprint(2, "negative ref in drawfreedscreen\n");
if(this->ref > 0)
return;
- ds = dscreen;
+ ds = client->dscreen;
if(ds == this){
- dscreen = this->next;
+ client->dscreen = this->next;
goto Found;
}
while(next = ds->next){ /* assign = */
@@ -518,16 +399,16 @@ drawfreedscreen(DScreen *this)
Found:
if(this->dimage)
- drawfreedimage(this->dimage);
+ drawfreedimage(client, this->dimage);
if(this->dfill)
- drawfreedimage(this->dfill);
+ drawfreedimage(client, this->dfill);
free(this->screen);
free(this);
}
static
void
-drawfreedimage(DImage *dimage)
+drawfreedimage(Client *client, DImage *dimage)
{
int i;
Memimage *l;
@@ -540,13 +421,13 @@ drawfreedimage(DImage *dimage)
return;
/* any names? */
- for(i=0; i<sdraw.nname; )
- if(sdraw.name[i].dimage == dimage)
- drawdelname(sdraw.name+i);
+ for(i=0; i<client->nname; )
+ if(client->name[i].dimage == dimage)
+ drawdelname(client, client->name+i);
else
i++;
if(dimage->fromname){ /* acquired by name; owned by someone else*/
- drawfreedimage(dimage->fromname);
+ drawfreedimage(client, dimage->fromname);
goto Return;
}
ds = dimage->dscreen;
@@ -554,16 +435,16 @@ drawfreedimage(DImage *dimage)
dimage->dscreen = nil; /* paranoia */
dimage->image = nil;
if(ds){
- if(l->data == screenimage->data)
- addflush(l->layer->screenr);
+ if(l->data == client->screenimage->data)
+ addflush(client, l->layer->screenr);
if(l->layer->refreshfn == drawrefresh) /* else true owner will clean up */
free(l->layer->refreshptr);
l->layer->refreshptr = nil;
- if(drawgoodname(dimage))
+ if(drawgoodname(client, dimage))
memldelete(l);
else
memlfree(l);
- drawfreedscreen(ds);
+ drawfreedscreen(client, ds);
}else{
if(l->screenref==0)
freememimage(l);
@@ -584,14 +465,14 @@ drawuninstallscreen(Client *client, CScreen *this)
cs = client->cscreen;
if(cs == this){
client->cscreen = this->next;
- drawfreedscreen(this->dscreen);
+ drawfreedscreen(client, this->dscreen);
free(this);
return;
}
while(next = cs->next){ /* assign = */
if(next == this){
cs->next = this->next;
- drawfreedscreen(this->dscreen);
+ drawfreedscreen(client, this->dscreen);
free(this);
return;
}
@@ -608,7 +489,7 @@ drawuninstall(Client *client, int id)
for(l=&client->dimage[id&HASHMASK]; (d=*l) != nil; l=&d->next){
if(d->id == id){
*l = d->next;
- drawfreedimage(d);
+ drawfreedimage(client, d);
return 0;
}
}
@@ -622,14 +503,14 @@ drawaddname(Client *client, DImage *di, int n, char *str, char **err)
DName *name, *ename, *new, *t;
char *ns;
- name = sdraw.name;
- ename = &name[sdraw.nname];
+ name = client->name;
+ ename = &name[client->nname];
for(; name<ename; name++)
if(drawcmp(name->name, str, n) == 0){
*err = "image name in use";
return -1;
}
- t = mallocz((sdraw.nname+1)*sizeof(DName), 1);
+ t = mallocz((client->nname+1)*sizeof(DName), 1);
ns = malloc(n+1);
if(t == nil || ns == nil){
free(t);
@@ -637,16 +518,16 @@ drawaddname(Client *client, DImage *di, int n, char *str, char **err)
*err = "out of memory";
return -1;
}
- memmove(t, sdraw.name, sdraw.nname*sizeof(DName));
- free(sdraw.name);
- sdraw.name = t;
- new = &sdraw.name[sdraw.nname++];
+ memmove(t, client->name, client->nname*sizeof(DName));
+ free(client->name);
+ client->name = t;
+ new = &client->name[client->nname++];
new->name = ns;
memmove(new->name, str, n);
new->name[n] = 0;
new->dimage = di;
new->client = client;
- new->vers = ++sdraw.vers;
+ new->vers = ++client->namevers;
return 0;
}
@@ -738,12 +619,9 @@ drawcoord(uchar *p, uchar *maxp, int oldx, int *newx)
}
int
-_drawmsgread(void *a, int n)
+_drawmsgread(Client *cl, void *a, int n)
{
- Client *cl;
-
qlock(&sdraw.lk);
- cl = client0;
if(cl->readdata == nil){
werrstr("no draw data");
goto err;
@@ -765,14 +643,13 @@ err:
}
int
-_drawmsgwrite(void *v, int n)
+_drawmsgwrite(Client *client, void *v, int n)
{
char cbuf[40], *err, ibuf[12*12+1], *s;
int c, ci, doflush, dstid, e0, e1, esize, j, m;
int ni, nw, oesize, oldn, op, ox, oy, repl, scrnid, y;
uchar *a, refresh, *u;
u32int chan, value;
- Client *client;
CScreen *cs;
DImage *di, *ddst, *dsrc, *font, *ll;
DName *dn;
@@ -790,7 +667,6 @@ _drawmsgwrite(void *v, int n)
a = v;
m = 0;
oldn = n;
- client = client0;
while((n-=m) > 0){
a += m;
@@ -844,7 +720,7 @@ _drawmsgwrite(void *v, int n)
l = memlalloc(scrn, r, reffn, 0, value);
if(l == 0)
goto Edrawmem;
- addflush(l->layer->screenr);
+ addflush(client, l->layer->screenr);
l->clipr = clipr;
rectclip(&l->clipr, r);
if(drawinstall(client, dstid, l, dscrn) == 0){
@@ -891,7 +767,7 @@ _drawmsgwrite(void *v, int n)
dstid = BGLONG(a+1);
if(dstid == 0)
goto Ebadarg;
- if(drawlookupdscreen(dstid))
+ if(drawlookupdscreen(client, dstid))
goto Escreenexists;
ddst = drawlookup(client, BGLONG(a+5), 1);
dsrc = drawlookup(client, BGLONG(a+9), 1);
@@ -935,7 +811,7 @@ _drawmsgwrite(void *v, int n)
drawpoint(&q, a+37);
op = drawclientop(client);
memdraw(dst, r, src, p, mask, q, op);
- dstflush(dstid, dst, r);
+ dstflush(client, dstid, dst, r);
continue;
/* toggle debugging: 'D' val[1] */
@@ -984,7 +860,7 @@ _drawmsgwrite(void *v, int n)
memarc(dst, p, e0, e1, c, src, sp, ox, oy, op);
}else
memellipse(dst, p, e0, e1, c, src, sp, op);
- dstflush(dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
+ dstflush(client, dstid, dst, Rect(p.x-e0-j, p.y-e1-j, p.x+e0+j+1, p.y+e1+j+1));
continue;
/* free: 'f' id[4] */
@@ -1049,7 +925,7 @@ _drawmsgwrite(void *v, int n)
goto Eshortdraw;
if(drawlookup(client, 0, 0))
goto Eimageexists;
- drawinstall(client, 0, screenimage, 0);
+ drawinstall(client, 0, client->screenimage, 0);
client->infoid = 0;
continue;
@@ -1061,7 +937,7 @@ _drawmsgwrite(void *v, int n)
if(client->infoid < 0)
goto Enodrawimage;
if(client->infoid == 0){
- i = screenimage;
+ i = client->screenimage;
if(i == nil)
goto Enodrawimage;
}else{
@@ -1102,10 +978,10 @@ _drawmsgwrite(void *v, int n)
err = "unknown query";
goto error;
case 'd': /* dpi */
- if(forcedpi)
- fmtprint(&fmt, "%11d ", forcedpi);
+ if(client->forcedpi)
+ fmtprint(&fmt, "%11d ", client->forcedpi);
else
- fmtprint(&fmt, "%11d ", displaydpi);
+ fmtprint(&fmt, "%11d ", client->displaydpi);
break;
}
}
@@ -1169,7 +1045,7 @@ _drawmsgwrite(void *v, int n)
if(dstid==0 || dst->layer!=nil){
/* BUG: this is terribly inefficient: update maximal containing rect*/
r = memlinebbox(p, q, e0, e1, j);
- dstflush(dstid, dst, insetrect(r, -(1+1+j)));
+ dstflush(client, dstid, dst, insetrect(r, -(1+1+j)));
}
continue;
@@ -1198,7 +1074,7 @@ _drawmsgwrite(void *v, int n)
dstid = BGLONG(a+1);
if(drawlookup(client, dstid, 0))
goto Eimageexists;
- dn = drawlookupname(j, (char*)a+6);
+ dn = drawlookupname(client, j, (char*)a+6);
if(dn == nil)
goto Enoname;
s = malloc(j+1);
@@ -1239,12 +1115,12 @@ _drawmsgwrite(void *v, int n)
if(drawaddname(client, di, j, (char*)a+7, &err) < 0)
goto error;
else{
- dn = drawlookupname(j, (char*)a+7);
+ dn = drawlookupname(client, j, (char*)a+7);
if(dn == nil)
goto Enoname;
if(dn->dimage != di)
goto Ewrongname;
- drawdelname(dn);
+ drawdelname(client, dn);
}
continue;
@@ -1266,8 +1142,8 @@ _drawmsgwrite(void *v, int n)
goto error;
}
if(ni > 0){
- addflush(r);
- addflush(dst->layer->screenr);
+ addflush(client, r);
+ addflush(client, dst->layer->screenr);
ll = drawlookup(client, BGLONG(a+1), 1);
drawrefreshscreen(ll, client);
}
@@ -1316,7 +1192,7 @@ _drawmsgwrite(void *v, int n)
if(pp == nil)
goto Enomem;
doflush = 0;
- if(dstid==0 || (dst->layer && dst->layer->screen->image->data == screenimage->data))
+ if(dstid==0 || (dst->layer && dst->layer->screen->image->data == client->screenimage->data))
doflush = 1; /* simplify test in loop */
ox = oy = 0;
esize = 0;
@@ -1353,12 +1229,12 @@ _drawmsgwrite(void *v, int n)
combinerect(&r, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
}
if(rectclip(&r, dst->clipr)) /* should perhaps be an arg to dstflush */
- dstflush(dstid, dst, r);
+ dstflush(client, dstid, dst, r);
}
pp[y] = p;
}
if(y == 1)
- dstflush(dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
+ dstflush(client, dstid, dst, Rect(p.x-esize, p.y-esize, p.x+esize+1, p.y+esize+1));
op = drawclientop(client);
if(*a == 'p')
mempoly(dst, pp, ni, e0, e1, j, src, sp, op);
@@ -1462,7 +1338,7 @@ _drawmsgwrite(void *v, int n)
}
dst->clipr = clipr;
p.y -= font->ascent;
- dstflush(dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
+ dstflush(client, dstid, dst, Rect(p.x, p.y, q.x, p.y+Dy(font->image->r)));
continue;
/* use public screen: 'S' id[4] chan[4] */
@@ -1473,7 +1349,7 @@ _drawmsgwrite(void *v, int n)
dstid = BGLONG(a+1);
if(dstid == 0)
goto Ebadarg;
- dscrn = drawlookupdscreen(dstid);
+ dscrn = drawlookupdscreen(client, dstid);
if(dscrn==0 || (dscrn->public==0 && dscrn->owner!=client))
goto Enodrawscreen;
if(dscrn->screen->image->chan != BGLONG(a+5)){
@@ -1522,9 +1398,9 @@ _drawmsgwrite(void *v, int n)
memltofrontn(lp, nw);
else
memltorearn(lp, nw);
- if(lp[0]->layer->screen->image->data == screenimage->data)
+ if(lp[0]->layer->screen->image->data == client->screenimage->data)
for(j=0; j<nw; j++)
- addflush(lp[j]->layer->screenr);
+ addflush(client, lp[j]->layer->screenr);
free(lp);
ll = drawlookup(client, BGLONG(a+1+1+2), 1);
drawrefreshscreen(ll, client);
@@ -1533,7 +1409,7 @@ _drawmsgwrite(void *v, int n)
/* visible: 'v' */
case 'v':
m = 1;
- drawflush();
+ drawflush(client);
continue;
/* write: 'y' id[4] R[4*4] data[x*1] */
@@ -1555,7 +1431,7 @@ _drawmsgwrite(void *v, int n)
err = "bad writeimage call";
goto error;
}
- dstflush(dstid, dst, r);
+ dstflush(client, dstid, dst, r);
m += y;
continue;
}