devdraw: move Client into devdraw.h and move global state in

This commit is contained in:
Russ Cox 2020-01-08 20:28:17 -05:00
parent 933b98054f
commit 88ed92aa40
11 changed files with 470 additions and 465 deletions

View file

@ -216,7 +216,6 @@ extern Memdrawparam* _memimagedrawsetup(Memimage*,
Rectangle, Memimage*, Point, Memimage*, Rectangle, Memimage*, Point, Memimage*,
Point, int); Point, int);
extern void _memimagedraw(Memdrawparam*); extern void _memimagedraw(Memdrawparam*);
extern void _drawreplacescreenimage(Memimage*);
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View file

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

View file

@ -1,10 +1,167 @@
int _drawmsgread(void*, int);
int _drawmsgwrite(void*, int); #define NHASH (1<<5)
void _initdisplaymemimage(Memimage*); #define HASHMASK (NHASH-1)
typedef struct Kbdbuf Kbdbuf;
typedef struct Mousebuf Mousebuf;
typedef struct Tagbuf Tagbuf;
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;
};
struct Kbdbuf
{
Rune r[256];
int ri;
int wi;
int stall;
int alting;
};
struct Mousebuf
{
Mouse m[256];
Mouse last;
int ri;
int wi;
int stall;
int resized;
};
struct Tagbuf
{
int t[256];
int ri;
int wi;
};
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;
int displaydpi;
int forcedpi;
int waste;
Rectangle flushrect;
Memimage *screenimage;
DScreen* dscreen;
int nname;
DName* name;
int namevers;
int rfd;
int wfd;
QLock inputlk;
Kbdbuf kbd;
Mousebuf mouse;
Tagbuf kbdtags;
Tagbuf mousetags;
Rectangle mouserect;
};
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;
};
int _drawmsgread(Client*, void*, int);
int _drawmsgwrite(Client*, void*, int);
void _initdisplaymemimage(Client*, Memimage*);
void _drawreplacescreenimage(Client*, Memimage*);
int _latin1(Rune*, int); int _latin1(Rune*, int);
int parsewinsize(char*, Rectangle*, int*); int parsewinsize(char*, Rectangle*, int*);
int mouseswap(int); int mouseswap(int);
void abortcompose(void); void abortcompose(Client*);
extern int displaydpi; extern Client *client0;
extern int forcedpi;

View file

@ -1,6 +1,6 @@
#define setcursor dsetcursor #define setcursor dsetcursor
Memimage *attachscreen(char*, char*); Memimage *attachscreen(Client*, char*, char*);
void setmouse(Point); void setmouse(Point);
void setcursor(Cursor*, Cursor2*); void setcursor(Cursor*, Cursor2*);
void setlabel(char*); void setlabel(char*);
@ -8,17 +8,12 @@ char* getsnarf(void);
void putsnarf(char*); void putsnarf(char*);
void topwin(void); void topwin(void);
void mousetrack(int, int, int, uint); void mousetrack(Client*, int, int, int, uint);
void keystroke(int); void keystroke(Client*, int);
void kicklabel(char*); void kicklabel(char*);
void servep9p(void); void servep9p(Client*);
void zlock(void);
void zunlock(void);
void resizeimg(void); void resizeimg(Client*);
Rectangle mouserect;
int mouseresized;
void resizewindow(Rectangle); void resizewindow(Rectangle);

View file

@ -15,10 +15,13 @@
#include <thread.h> #include <thread.h>
#include <draw.h> #include <draw.h>
#include <memdraw.h> #include <memdraw.h>
#include <keyboard.h> #include <memlayer.h>
#include <mouse.h>
#include <cursor.h> #include <cursor.h>
#include "mac-screen.h" #include <keyboard.h>
#include <drawfcall.h>
#include "devdraw.h" #include "devdraw.h"
#include "mac-screen.h"
#include "bigarrow.h" #include "bigarrow.h"
#include "glendapng.h" #include "glendapng.h"
@ -31,7 +34,7 @@ AUTOFRAMEWORK(QuartzCore)
static void setprocname(const char*); static void setprocname(const char*);
static uint keycvt(uint); static uint keycvt(uint);
static uint msec(void); static uint msec(void);
static Memimage* initimg(void); static Memimage* initimg(Client*);
void void
usage(void) usage(void)
@ -48,6 +51,7 @@ usage(void)
+ (void)callsetcursor:(NSValue *)v; + (void)callsetcursor:(NSValue *)v;
@end @end
@interface DevDrawView : NSView<NSTextInputClient> @interface DevDrawView : NSView<NSTextInputClient>
@property (nonatomic) Client *client;
- (void)clearInput; - (void)clearInput;
- (void)getmouse:(NSEvent *)e; - (void)getmouse:(NSEvent *)e;
- (void)sendmouse:(NSUInteger)b; - (void)sendmouse:(NSUInteger)b;
@ -96,6 +100,13 @@ threadmain(int argc, char **argv)
usage(); usage();
}ARGEND }ARGEND
client0 = mallocz(sizeof(Client), 1);
client0->displaydpi = 100;
if(client0 == nil){
fprint(2, "initdraw: allocating client0: out of memory");
abort();
}
setprocname(argv0); setprocname(argv0);
@autoreleasepool{ @autoreleasepool{
@ -113,7 +124,9 @@ callservep9p(void *v)
{ {
USED(v); USED(v);
servep9p(); client0->rfd = 3;
client0->wfd = 4;
servep9p(client0);
[NSApp terminate:myApp]; [NSApp terminate:myApp];
} }
@ -167,6 +180,7 @@ callservep9p(void *v)
[win setDelegate:myApp]; [win setDelegate:myApp];
myContent = [DevDrawView new]; myContent = [DevDrawView new];
myContent.client = client0;
[win setContentView:myContent]; [win setContentView:myContent];
[myContent setWantsLayer:YES]; [myContent setWantsLayer:YES];
[myContent setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay]; [myContent setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay];
@ -353,7 +367,7 @@ struct Cursors {
- (void)windowDidResize:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification
{ {
if(![myContent inLiveResize] && img) { if(![myContent inLiveResize] && img) {
resizeimg(); resizeimg(myContent.client);
} }
} }
@ -463,7 +477,7 @@ struct Cursors {
b |= 4; b |= 4;
[self sendmouse:b]; [self sendmouse:b];
}else if(m & ~omod & NSEventModifierFlagOption) }else if(m & ~omod & NSEventModifierFlagOption)
keystroke(Kalt); keystroke(self.client, Kalt);
omod = m; omod = m;
} }
@ -520,7 +534,7 @@ struct Cursors {
if(b == 1){ if(b == 1){
m = [e modifierFlags]; m = [e modifierFlags];
if(m & NSEventModifierFlagOption){ if(m & NSEventModifierFlagOption){
abortcompose(); abortcompose(self.client);
b = 2; b = 2;
}else }else
if(m & NSEventModifierFlagCommand) if(m & NSEventModifierFlagCommand)
@ -535,9 +549,9 @@ struct Cursors {
p = [self.window convertPointToBacking: p = [self.window convertPointToBacking:
[self.window mouseLocationOutsideOfEventStream]]; [self.window mouseLocationOutsideOfEventStream]];
p.y = Dy(mouserect) - p.y; p.y = Dy(self.client->mouserect) - p.y;
// LOG(@"(%g, %g) <- sendmouse(%d)", p.x, p.y, (uint)b); // LOG(@"(%g, %g) <- sendmouse(%d)", p.x, p.y, (uint)b);
mousetrack(p.x, p.y, b, msec()); mousetrack(self.client, p.x, p.y, b, msec());
if(b && _lastInputRect.size.width && _lastInputRect.size.height) if(b && _lastInputRect.size.width && _lastInputRect.size.height)
[self resetLastInputRect]; [self resetLastInputRect];
} }
@ -551,14 +565,14 @@ struct Cursors {
{ {
[super viewDidEndLiveResize]; [super viewDidEndLiveResize];
if(img) if(img)
resizeimg(); resizeimg(self.client);
} }
- (void)viewDidChangeBackingProperties - (void)viewDidChangeBackingProperties
{ {
[super viewDidChangeBackingProperties]; [super viewDidChangeBackingProperties];
if(img) if(img)
resizeimg(); resizeimg(self.client);
} }
// conforms to protocol NSTextInputClient // conforms to protocol NSTextInputClient
@ -617,24 +631,24 @@ struct Cursors {
LOG(@"text length %ld", _tmpText.length); LOG(@"text length %ld", _tmpText.length);
for(i = 0; i <= _tmpText.length; ++i){ for(i = 0; i <= _tmpText.length; ++i){
if(i == _markedRange.location) if(i == _markedRange.location)
keystroke('['); keystroke(self.client, '[');
if(_selectedRange.length){ if(_selectedRange.length){
if(i == _selectedRange.location) if(i == _selectedRange.location)
keystroke('{'); keystroke(self.client, '{');
if(i == NSMaxRange(_selectedRange)) if(i == NSMaxRange(_selectedRange))
keystroke('}'); keystroke(self.client, '}');
} }
if(i == NSMaxRange(_markedRange)) if(i == NSMaxRange(_markedRange))
keystroke(']'); keystroke(self.client, ']');
if(i < _tmpText.length) if(i < _tmpText.length)
keystroke([_tmpText characterAtIndex:i]); keystroke(self.client, [_tmpText characterAtIndex:i]);
} }
int l; int l;
l = 1 + _tmpText.length - NSMaxRange(_selectedRange) l = 1 + _tmpText.length - NSMaxRange(_selectedRange)
+ (_selectedRange.length > 0); + (_selectedRange.length > 0);
LOG(@"move left %d", l); LOG(@"move left %d", l);
for(i = 0; i < l; ++i) for(i = 0; i < l; ++i)
keystroke(Kleft); keystroke(self.client, Kleft);
} }
LOG(@"text: \"%@\" (%ld,%ld) (%ld,%ld)", _tmpText, LOG(@"text: \"%@\" (%ld,%ld) (%ld,%ld)", _tmpText,
@ -649,7 +663,7 @@ struct Cursors {
LOG(@"unmarkText"); LOG(@"unmarkText");
len = [_tmpText length]; len = [_tmpText length];
//for(i = 0; i < len; ++i) //for(i = 0; i < len; ++i)
// keystroke([_tmpText characterAtIndex:i]); // keystroke(self.client, [_tmpText characterAtIndex:i]);
[_tmpText deleteCharactersInRange:NSMakeRange(0, len)]; [_tmpText deleteCharactersInRange:NSMakeRange(0, len)];
_markedRange = NSMakeRange(NSNotFound, 0); _markedRange = NSMakeRange(NSNotFound, 0);
_selectedRange = NSMakeRange(0, 0); _selectedRange = NSMakeRange(0, 0);
@ -691,7 +705,7 @@ struct Cursors {
len = [s length]; len = [s length];
for(i = 0; i < len; ++i) for(i = 0; i < len; ++i)
keystroke([s characterAtIndex:i]); keystroke(self.client, [s characterAtIndex:i]);
[_tmpText deleteCharactersInRange:NSMakeRange(0, _tmpText.length)]; [_tmpText deleteCharactersInRange:NSMakeRange(0, _tmpText.length)];
_markedRange = NSMakeRange(NSNotFound, 0); _markedRange = NSMakeRange(NSNotFound, 0);
_selectedRange = NSMakeRange(0, 0); _selectedRange = NSMakeRange(0, 0);
@ -731,7 +745,7 @@ struct Cursors {
k += Kcmd; k += Kcmd;
} }
if(k>0) if(k>0)
keystroke(k); keystroke(self.client, k);
} }
// Helper for managing input rect approximately // Helper for managing input rect approximately
@ -762,11 +776,11 @@ struct Cursors {
+ (_selectedRange.length > 0); + (_selectedRange.length > 0);
LOG(@"move right %d", l); LOG(@"move right %d", l);
for(i = 0; i < l; ++i) for(i = 0; i < l; ++i)
keystroke(Kright); keystroke(self.client, Kright);
l = _tmpText.length+2+2*(_selectedRange.length > 0); l = _tmpText.length+2+2*(_selectedRange.length > 0);
LOG(@"backspace %d", l); LOG(@"backspace %d", l);
for(uint i = 0; i < l; ++i) for(uint i = 0; i < l; ++i)
keystroke(Kbs); keystroke(self.client, Kbs);
} }
} }
@ -915,7 +929,7 @@ keycvt(uint code)
} }
Memimage* Memimage*
attachscreen(char *label, char *winsize) attachscreen(Client *c, char *label, char *winsize)
{ {
LOG(@"attachscreen(%s, %s)", label, winsize); LOG(@"attachscreen(%s, %s)", label, winsize);
[AppDelegate [AppDelegate
@ -924,12 +938,12 @@ attachscreen(char *label, char *winsize)
waitUntilDone:YES]; waitUntilDone:YES];
kicklabel(label); kicklabel(label);
setcursor(nil, nil); setcursor(nil, nil);
mouseresized = 0; c->mouse.resized = 0;
return initimg(); return initimg(c);
} }
static Memimage* static Memimage*
initimg(void) initimg(Client *c)
{ {
@autoreleasepool{ @autoreleasepool{
CGFloat scale; CGFloat scale;
@ -937,11 +951,11 @@ initimg(void)
MTLTextureDescriptor *textureDesc; MTLTextureDescriptor *textureDesc;
size = [myContent convertSizeToBacking:[myContent bounds].size]; size = [myContent convertSizeToBacking:[myContent bounds].size];
mouserect = Rect(0, 0, size.width, size.height); c->mouserect = Rect(0, 0, size.width, size.height);
LOG(@"initimg %.0f %.0f", size.width, size.height); LOG(@"initimg %.0f %.0f", size.width, size.height);
img = allocmemimage(mouserect, XRGB32); img = allocmemimage(c->mouserect, XRGB32);
if(img == nil) if(img == nil)
panic("allocmemimage: %r"); panic("allocmemimage: %r");
if(img->data == nil) if(img->data == nil)
@ -966,7 +980,7 @@ initimg(void)
// This formula gives us 220 for retina, 110 otherwise. // This formula gives us 220 for retina, 110 otherwise.
// That's not quite right but it's close to correct. // That's not quite right but it's close to correct.
// https://en.wikipedia.org/wiki/Retina_display#Models // https://en.wikipedia.org/wiki/Retina_display#Models
displaydpi = scale * 110; c->displaydpi = scale * 110;
} }
LOG(@"initimg return"); LOG(@"initimg return");
@ -1109,13 +1123,9 @@ topwin(void)
} }
void void
resizeimg(void) resizeimg(Client *c)
{ {
zlock(); _drawreplacescreenimage(c, initimg(c));
_drawreplacescreenimage(initimg());
mouseresized = 1;
zunlock();
[myContent sendmouse:0]; [myContent sendmouse:0];
} }

View file

@ -7,70 +7,23 @@
#include <thread.h> #include <thread.h>
#include <draw.h> #include <draw.h>
#include <memdraw.h> #include <memdraw.h>
#include <memlayer.h>
#include <keyboard.h> #include <keyboard.h>
#include <mouse.h> #include <mouse.h>
#include <cursor.h> #include <cursor.h>
#include <drawfcall.h> #include <drawfcall.h>
#include "mac-screen.h"
#include "devdraw.h" #include "devdraw.h"
#include "mac-screen.h"
typedef struct Kbdbuf Kbdbuf; void runmsg(Client*, Wsysmsg*);
typedef struct Mousebuf Mousebuf; void replymsg(Client*, Wsysmsg*);
typedef struct Fdbuf Fdbuf; void matchkbd(Client*);
typedef struct Tagbuf Tagbuf; void matchmouse(Client*);
struct Kbdbuf
{
Rune r[256];
int ri;
int wi;
int stall;
};
struct Mousebuf
{
Mouse m[256];
Mouse last;
int ri;
int wi;
int stall;
};
struct Tagbuf
{
int t[256];
int ri;
int wi;
};
Kbdbuf kbd;
Mousebuf mouse;
Tagbuf kbdtags;
Tagbuf mousetags;
void runmsg(Wsysmsg*);
void replymsg(Wsysmsg*);
void matchkbd(void);
void matchmouse(void);
QLock lk;
void
zlock(void)
{
qlock(&lk);
}
void
zunlock(void)
{
qunlock(&lk);
}
int trace = 0; int trace = 0;
void void
servep9p(void) servep9p(Client *c)
{ {
uchar buf[4], *mbuf; uchar buf[4], *mbuf;
int nmbuf, n, nn; int nmbuf, n, nn;
@ -80,7 +33,7 @@ servep9p(void)
mbuf = nil; mbuf = nil;
nmbuf = 0; nmbuf = 0;
while((n = read(3, buf, 4)) == 4){ while((n = read(c->rfd, buf, 4)) == 4){
GET(buf, n); GET(buf, n);
if(n > nmbuf){ if(n > nmbuf){
free(mbuf); free(mbuf);
@ -90,7 +43,7 @@ servep9p(void)
nmbuf = n; nmbuf = n;
} }
memmove(mbuf, buf, 4); memmove(mbuf, buf, 4);
nn = readn(3, mbuf+4, n-4); nn = readn(c->rfd, mbuf+4, n-4);
if(nn != n-4) if(nn != n-4)
sysfatal("eof during message"); sysfatal("eof during message");
@ -98,19 +51,19 @@ servep9p(void)
if(convM2W(mbuf, nn+4, &m) <= 0) if(convM2W(mbuf, nn+4, &m) <= 0)
sysfatal("cannot convert message"); sysfatal("cannot convert message");
if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m); if(trace) fprint(2, "%ud [%d] <- %W\n", nsec()/1000000, threadid(), &m);
runmsg(&m); runmsg(c, &m);
} }
} }
void void
replyerror(Wsysmsg *m) replyerror(Client *c, Wsysmsg *m)
{ {
char err[256]; char err[256];
rerrstr(err, sizeof err); rerrstr(err, sizeof err);
m->type = Rerror; m->type = Rerror;
m->error = err; m->error = err;
replymsg(m); replymsg(c, m);
} }
/* /*
@ -118,7 +71,7 @@ replyerror(Wsysmsg *m)
* Might queue for later (kbd, mouse read) * Might queue for later (kbd, mouse read)
*/ */
void void
runmsg(Wsysmsg *m) runmsg(Client *c, Wsysmsg *m)
{ {
static uchar buf[65536]; static uchar buf[65536];
int n; int n;
@ -127,38 +80,38 @@ runmsg(Wsysmsg *m)
switch(m->type){ switch(m->type){
case Tinit: case Tinit:
memimageinit(); memimageinit();
i = attachscreen(m->label, m->winsize); i = attachscreen(c, m->label, m->winsize);
_initdisplaymemimage(i); _initdisplaymemimage(c, i);
replymsg(m); replymsg(c, m);
break; break;
case Trdmouse: case Trdmouse:
zlock(); qlock(&c->inputlk);
mousetags.t[mousetags.wi++] = m->tag; c->mousetags.t[c->mousetags.wi++] = m->tag;
if(mousetags.wi == nelem(mousetags.t)) if(c->mousetags.wi == nelem(c->mousetags.t))
mousetags.wi = 0; c->mousetags.wi = 0;
if(mousetags.wi == mousetags.ri) if(c->mousetags.wi == c->mousetags.ri)
sysfatal("too many queued mouse reads"); sysfatal("too many queued mouse reads");
mouse.stall = 0; c->mouse.stall = 0;
matchmouse(); matchmouse(c);
zunlock(); qunlock(&c->inputlk);
break; break;
case Trdkbd: case Trdkbd:
zlock(); qlock(&c->inputlk);
kbdtags.t[kbdtags.wi++] = m->tag; c->kbdtags.t[c->kbdtags.wi++] = m->tag;
if(kbdtags.wi == nelem(kbdtags.t)) if(c->kbdtags.wi == nelem(c->kbdtags.t))
kbdtags.wi = 0; c->kbdtags.wi = 0;
if(kbdtags.wi == kbdtags.ri) if(c->kbdtags.wi == c->kbdtags.ri)
sysfatal("too many queued keyboard reads"); sysfatal("too many queued keyboard reads");
kbd.stall = 0; c->kbd.stall = 0;
matchkbd(); matchkbd(c);
zunlock(); qunlock(&c->inputlk);
break; break;
case Tmoveto: case Tmoveto:
setmouse(m->mouse.xy); setmouse(m->mouse.xy);
replymsg(m); replymsg(c, m);
break; break;
case Tcursor: case Tcursor:
@ -166,7 +119,7 @@ runmsg(Wsysmsg *m)
setcursor(nil, nil); setcursor(nil, nil);
else else
setcursor(&m->cursor, nil); setcursor(&m->cursor, nil);
replymsg(m); replymsg(c, m);
break; break;
case Tcursor2: case Tcursor2:
@ -174,63 +127,63 @@ runmsg(Wsysmsg *m)
setcursor(nil, nil); setcursor(nil, nil);
else else
setcursor(&m->cursor, &m->cursor2); setcursor(&m->cursor, &m->cursor2);
replymsg(m); replymsg(c, m);
break; break;
case Tbouncemouse: case Tbouncemouse:
// _xbouncemouse(&m->mouse); // _xbouncemouse(&m->mouse);
replymsg(m); replymsg(c, m);
break; break;
case Tlabel: case Tlabel:
kicklabel(m->label); kicklabel(m->label);
replymsg(m); replymsg(c, m);
break; break;
case Trdsnarf: case Trdsnarf:
m->snarf = getsnarf(); m->snarf = getsnarf();
replymsg(m); replymsg(c, m);
free(m->snarf); free(m->snarf);
break; break;
case Twrsnarf: case Twrsnarf:
putsnarf(m->snarf); putsnarf(m->snarf);
replymsg(m); replymsg(c, m);
break; break;
case Trddraw: case Trddraw:
zlock(); qlock(&c->inputlk);
n = m->count; n = m->count;
if(n > sizeof buf) if(n > sizeof buf)
n = sizeof buf; n = sizeof buf;
n = _drawmsgread(buf, n); n = _drawmsgread(c, buf, n);
if(n < 0) if(n < 0)
replyerror(m); replyerror(c, m);
else{ else{
m->count = n; m->count = n;
m->data = buf; m->data = buf;
replymsg(m); replymsg(c, m);
} }
zunlock(); qunlock(&c->inputlk);
break; break;
case Twrdraw: case Twrdraw:
zlock(); qlock(&c->inputlk);
if(_drawmsgwrite(m->data, m->count) < 0) if(_drawmsgwrite(c, m->data, m->count) < 0)
replyerror(m); replyerror(c, m);
else else
replymsg(m); replymsg(c, m);
zunlock(); qunlock(&c->inputlk);
break; break;
case Ttop: case Ttop:
topwin(); topwin();
replymsg(m); replymsg(c, m);
break; break;
case Tresize: case Tresize:
resizewindow(m->rect); resizewindow(m->rect);
replymsg(m); replymsg(c, m);
break; break;
} }
} }
@ -240,7 +193,7 @@ runmsg(Wsysmsg *m)
*/ */
QLock replylock; QLock replylock;
void void
replymsg(Wsysmsg *m) replymsg(Client *c, Wsysmsg *m)
{ {
int n; int n;
static uchar *mbuf; static uchar *mbuf;
@ -263,7 +216,7 @@ replymsg(Wsysmsg *m)
nmbuf = n; nmbuf = n;
} }
convW2M(m, mbuf, n); convW2M(m, mbuf, n);
if(write(4, mbuf, n) != n) if(write(c->wfd, mbuf, n) != n)
sysfatal("write: %r"); sysfatal("write: %r");
qunlock(&replylock); qunlock(&replylock);
} }
@ -272,21 +225,21 @@ replymsg(Wsysmsg *m)
* Match queued kbd reads with queued kbd characters. * Match queued kbd reads with queued kbd characters.
*/ */
void void
matchkbd(void) matchkbd(Client *c)
{ {
Wsysmsg m; Wsysmsg m;
if(kbd.stall) if(c->kbd.stall)
return; return;
while(kbd.ri != kbd.wi && kbdtags.ri != kbdtags.wi){ while(c->kbd.ri != c->kbd.wi && c->kbdtags.ri != c->kbdtags.wi){
m.type = Rrdkbd; m.type = Rrdkbd;
m.tag = kbdtags.t[kbdtags.ri++]; m.tag = c->kbdtags.t[c->kbdtags.ri++];
if(kbdtags.ri == nelem(kbdtags.t)) if(c->kbdtags.ri == nelem(c->kbdtags.t))
kbdtags.ri = 0; c->kbdtags.ri = 0;
m.rune = kbd.r[kbd.ri++]; m.rune = c->kbd.r[c->kbd.ri++];
if(kbd.ri == nelem(kbd.r)) if(c->kbd.ri == nelem(c->kbd.r))
kbd.ri = 0; c->kbd.ri = 0;
replymsg(&m); replymsg(c, &m);
} }
} }
@ -294,131 +247,129 @@ matchkbd(void)
* Match queued mouse reads with queued mouse events. * Match queued mouse reads with queued mouse events.
*/ */
void void
matchmouse(void) matchmouse(Client *c)
{ {
Wsysmsg m; Wsysmsg m;
while(mouse.ri != mouse.wi && mousetags.ri != mousetags.wi){ while(c->mouse.ri != c->mouse.wi && c->mousetags.ri != c->mousetags.wi){
m.type = Rrdmouse; m.type = Rrdmouse;
m.tag = mousetags.t[mousetags.ri++]; m.tag = c->mousetags.t[c->mousetags.ri++];
if(mousetags.ri == nelem(mousetags.t)) if(c->mousetags.ri == nelem(c->mousetags.t))
mousetags.ri = 0; c->mousetags.ri = 0;
m.mouse = mouse.m[mouse.ri]; m.mouse = c->mouse.m[c->mouse.ri];
m.resized = mouseresized; m.resized = c->mouse.resized;
mouseresized = 0; c->mouse.resized = 0;
/* /*
if(m.resized) if(m.resized)
fprint(2, "sending resize\n"); fprint(2, "sending resize\n");
*/ */
mouse.ri++; c->mouse.ri++;
if(mouse.ri == nelem(mouse.m)) if(c->mouse.ri == nelem(c->mouse.m))
mouse.ri = 0; c->mouse.ri = 0;
replymsg(&m); replymsg(c, &m);
} }
} }
void void
mousetrack(int x, int y, int b, uint ms) mousetrack(Client *c, int x, int y, int b, uint ms)
{ {
Mouse *m; Mouse *m;
if(x < mouserect.min.x) if(x < c->mouserect.min.x)
x = mouserect.min.x; x = c->mouserect.min.x;
if(x > mouserect.max.x) if(x > c->mouserect.max.x)
x = mouserect.max.x; x = c->mouserect.max.x;
if(y < mouserect.min.y) if(y < c->mouserect.min.y)
y = mouserect.min.y; y = c->mouserect.min.y;
if(y > mouserect.max.y) if(y > c->mouserect.max.y)
y = mouserect.max.y; y = c->mouserect.max.y;
zlock(); qlock(&c->inputlk);
// If reader has stopped reading, don't bother. // If reader has stopped reading, don't bother.
// If reader is completely caught up, definitely queue. // If reader is completely caught up, definitely queue.
// Otherwise, queue only button change events. // Otherwise, queue only button change events.
if(!mouse.stall) if(!c->mouse.stall)
if(mouse.wi == mouse.ri || mouse.last.buttons != b){ if(c->mouse.wi == c->mouse.ri || c->mouse.last.buttons != b){
m = &mouse.last; m = &c->mouse.last;
m->xy.x = x; m->xy.x = x;
m->xy.y = y; m->xy.y = y;
m->buttons = b; m->buttons = b;
m->msec = ms; m->msec = ms;
mouse.m[mouse.wi] = *m; c->mouse.m[c->mouse.wi] = *m;
if(++mouse.wi == nelem(mouse.m)) if(++c->mouse.wi == nelem(c->mouse.m))
mouse.wi = 0; c->mouse.wi = 0;
if(mouse.wi == mouse.ri){ if(c->mouse.wi == c->mouse.ri){
mouse.stall = 1; c->mouse.stall = 1;
mouse.ri = 0; c->mouse.ri = 0;
mouse.wi = 1; c->mouse.wi = 1;
mouse.m[0] = *m; c->mouse.m[0] = *m;
} }
matchmouse(); matchmouse(c);
} }
zunlock(); qunlock(&c->inputlk);
} }
void void
kputc(int c) kputc(Client *c, int ch)
{ {
zlock(); qlock(&c->inputlk);
kbd.r[kbd.wi++] = c; c->kbd.r[c->kbd.wi++] = ch;
if(kbd.wi == nelem(kbd.r)) if(c->kbd.wi == nelem(c->kbd.r))
kbd.wi = 0; c->kbd.wi = 0;
if(kbd.ri == kbd.wi) if(c->kbd.ri == c->kbd.wi)
kbd.stall = 1; c->kbd.stall = 1;
matchkbd(); matchkbd(c);
zunlock(); qunlock(&c->inputlk);
} }
static int alting;
void void
abortcompose(void) abortcompose(Client *c)
{ {
if(alting) if(c->kbd.alting)
keystroke(Kalt); keystroke(c, Kalt);
} }
void void
keystroke(int c) keystroke(Client *c, int ch)
{ {
static Rune k[10]; static Rune k[10];
static int nk; static int nk;
int i; int i;
if(c == Kalt){ if(ch == Kalt){
alting = !alting; c->kbd.alting = !c->kbd.alting;
nk = 0; nk = 0;
return; return;
} }
if(c == Kcmd+'r') { if(ch == Kcmd+'r') {
if(forcedpi) if(c->forcedpi)
forcedpi = 0; c->forcedpi = 0;
else if(displaydpi >= 200) else if(c->displaydpi >= 200)
forcedpi = 100; c->forcedpi = 100;
else else
forcedpi = 225; c->forcedpi = 225;
resizeimg(); resizeimg(c);
return; return;
} }
if(!alting){ if(!c->kbd.alting){
kputc(c); kputc(c, ch);
return; return;
} }
if(nk >= nelem(k)) // should not happen if(nk >= nelem(k)) // should not happen
nk = 0; nk = 0;
k[nk++] = c; k[nk++] = ch;
c = _latin1(k, nk); ch = _latin1(k, nk);
if(c > 0){ if(ch > 0){
alting = 0; c->kbd.alting = 0;
kputc(c); kputc(c, ch);
nk = 0; nk = 0;
return; return;
} }
if(c == -1){ if(ch == -1){
alting = 0; c->kbd.alting = 0;
for(i=0; i<nk; i++) for(i=0; i<nk; i++)
kputc(k[i]); kputc(c, k[i]);
nk = 0; nk = 0;
return; return;
} }

View file

@ -16,7 +16,11 @@ WSYSOFILES=\
OFILES=$WSYSOFILES OFILES=$WSYSOFILES
HFILES=\ HFILES=\
bigarrow.h\
devdraw.h\ devdraw.h\
glendapng.h\
latin1.h\
$WSYSHFILES\
<$PLAN9/src/mkone <$PLAN9/src/mkone
@ -40,7 +44,7 @@ $O.macargv: $MACARGV
%.$O: %.m %.$O: %.m
$CC $CFLAGS $OBJCFLAGS -o $target $stem.m $CC $CFLAGS $OBJCFLAGS -o $target $stem.m
CLEANFILES=$O.devdraw $O.macargv $O.mklatinkbd latin1.h CLEANFILES=$O.devdraw $O.macargv $O.drawclient $O.mklatinkbd latin1.h
install: mklatinkbd.install install: mklatinkbd.install
install:Q: install:Q:

View file

@ -51,9 +51,11 @@ if [ $WSYSTYPE = x11 ]; then
echo 'HFILES=$HFILES $XHFILES' echo 'HFILES=$HFILES $XHFILES'
XO=`ls x11-*.c 2>/dev/null | sed 's/\.c$/.o/'` XO=`ls x11-*.c 2>/dev/null | sed 's/\.c$/.o/'`
echo 'WSYSOFILES=$WSYSOFILES '$XO echo 'WSYSOFILES=$WSYSOFILES '$XO
echo 'WSYSHFILES=x11-inc.h x11-keysym2ucs.h x11-memdraw.h'
elif [ $WSYSTYPE = mac ]; then elif [ $WSYSTYPE = mac ]; then
echo 'OBJCFLAGS=$OBJCFLAGS -fobjc-arc' echo 'OBJCFLAGS=$OBJCFLAGS -fobjc-arc'
echo 'WSYSOFILES=$WSYSOFILES mac-draw.o mac-screen.o mac-srv.o' echo 'WSYSOFILES=$WSYSOFILES mac-draw.o mac-screen.o mac-srv.o'
echo 'WSYSHFILES=mac-screen.h'
echo 'MACARGV=macargv.o' echo 'MACARGV=macargv.o'
elif [ $WSYSTYPE = nowsys ]; then elif [ $WSYSTYPE = nowsys ]; then
echo 'WSYSOFILES=nowsys.o' echo 'WSYSOFILES=nowsys.o'

View file

@ -2,6 +2,11 @@
#include <libc.h> #include <libc.h>
#include <draw.h> #include <draw.h>
#include <memdraw.h> #include <memdraw.h>
#include <memlayer.h>
#include <mouse.h>
#include <cursor.h>
#include <keyboard.h>
#include <drawfcall.h>
#include "devdraw.h" #include "devdraw.h"
enum enum

View file

@ -2,6 +2,11 @@
#include <libc.h> #include <libc.h>
#include <draw.h> #include <draw.h>
#include <memdraw.h> #include <memdraw.h>
#include <memlayer.h>
#include <mouse.h>
#include <cursor.h>
#include <keyboard.h>
#include <drawfcall.h>
#include "devdraw.h" #include "devdraw.h"
int int

View file

@ -6,6 +6,7 @@
#include <libc.h> #include <libc.h>
#include <draw.h> #include <draw.h>
#include <memdraw.h> #include <memdraw.h>
#include <memlayer.h>
#include <keyboard.h> #include <keyboard.h>
#include <mouse.h> #include <mouse.h>
#include <cursor.h> #include <cursor.h>
@ -232,7 +233,7 @@ _xattach(char *label, char *winsize)
if (XrmGetResource(database, "Xft.dpi", "String", &dpitype, &dpires) == True) { if (XrmGetResource(database, "Xft.dpi", "String", &dpitype, &dpires) == True) {
if (dpires.addr) { if (dpires.addr) {
displaydpi=atoi(dpires.addr); client0->displaydpi = atoi(dpires.addr);
} }
} }
geom = smprint("%s.geometry", label); geom = smprint("%s.geometry", label);