summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/src/cmd/rio/dat.h9
-rw-r--r--sys/src/cmd/rio/rio.c25
-rw-r--r--sys/src/cmd/rio/wctl.c19
-rw-r--r--sys/src/cmd/rio/wind.c129
-rw-r--r--sys/src/cmd/rio/xfid.c71
5 files changed, 163 insertions, 90 deletions
diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h
index e1d617ac9..f4f7f4efa 100644
--- a/sys/src/cmd/rio/dat.h
+++ b/sys/src/cmd/rio/dat.h
@@ -129,17 +129,18 @@ struct Window
Ref;
QLock;
Frame;
- Image *i;
- Mousectl mc;
+ Image *i; /* window image, nil when deleted */
+ Mousectl mc;
Mouseinfo mouse;
- Channel *ck; /* chan(char*) */
+ Channel *ck; /* chan(char*) */
Channel *cctl; /* chan(Wctlmesg)[4] */
Channel *conswrite; /* chan(Conswritemesg) */
Channel *consread; /* chan(Consreadmesg) */
Channel *mouseread; /* chan(Mousereadmesg) */
- Channel *wctlread; /* chan(Consreadmesg) */
+ Channel *wctlread; /* chan(Consreadmesg) */
Channel *kbdread; /* chan(Kbdreadmesg) */
Channel *complete; /* chan(Completion*) */
+ Channel *gone; /* chan(char*) */
uint nr; /* number of runes in window */
uint maxr; /* number of runes allocated in r */
Rune *r;
diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c
index 37a7e3d62..c65af8891 100644
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -571,7 +571,7 @@ mousethread(void*)
w = winput;
else {
riosetcursor(nil, 0);
- w = nil;
+ w = winput = nil;
}
}
/* we're not sending the event, but if button is down maybe we should */
@@ -642,9 +642,9 @@ resized(void)
r.min.y = (r.min.y*n.y)/o.y;
r.max.x = (r.max.x*n.x)/o.x;
r.max.y = (r.max.y*n.y)/o.y;
+ r = rectaddpt(r, view->clipr.min);
if(!goodrect(r))
r = rectsubpt(w->i->r, subpt(w->i->r.min, r.min));
- r = rectaddpt(r, screen->clipr.min);
for(j=0; j<nhidden; j++)
if(w == hidden[j])
break;
@@ -658,7 +658,7 @@ resized(void)
wsendctlmesg(w, Reshaped, r, im);
wclose(w);
}
- viewr = screen->r;
+ viewr = view->r;
flushimage(display, 1);
}
@@ -882,7 +882,7 @@ sweep(void)
}
if(mouse->buttons != 0)
goto Rescue;
- if(i==nil || Dx(i->r)<100 || Dy(i->r)<3*font->height)
+ if(i==nil || !goodrect(r))
goto Rescue;
oi = i;
i = allocwindow(wscreen, oi->r, Refbackup, DNofill);
@@ -941,20 +941,18 @@ drawborder(Rectangle r, int show)
Image*
drag(Window *w, Rectangle *rp)
{
- Image *i, *ni;
Point p, op, d, dm, om;
Rectangle r;
- i = w->i;
menuing = TRUE;
om = mouse->xy;
riosetcursor(&boxcursor, 1);
dm = subpt(mouse->xy, w->screenr.min);
- d = subpt(i->r.max, i->r.min);
+ d = subpt(w->screenr.max, w->screenr.min);
op = subpt(mouse->xy, dm);
drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1);
flushimage(display, 1);
- while(mouse->buttons == 4){
+ while(mouse->buttons==4){
p = subpt(mouse->xy, dm);
if(!eqpt(p, op)){
drawborder(Rect(p.x, p.y, p.x+d.x, p.y+d.y), 1);
@@ -969,16 +967,13 @@ drag(Window *w, Rectangle *rp)
moveto(mousectl, mouse->xy); /* force cursor update; ugly */
menuing = FALSE;
flushimage(display, 1);
- if(mouse->buttons!=0 || (ni=allocwindow(wscreen, r, Refbackup, DNofill))==nil){
- moveto(mousectl, om);
+ if(mouse->buttons!=0 || !goodrect(r)){
while(mouse->buttons)
readmouse(mousectl);
- *rp = Rect(0, 0, 0, 0);
return nil;
}
- draw(ni, ni->r, i, nil, i->r.min);
*rp = r;
- return ni;
+ return allocwindow(wscreen, r, Refbackup, DNofill);
}
Point
@@ -1063,7 +1058,7 @@ bandsize(Window *w)
or = r;
startp = p;
- while(mouse->buttons == but){
+ while(mouse->buttons==but){
p = onscreen(mouse->xy);
r = whichrect(w->screenr, p, which);
if(!eqrect(r, or) && goodrect(r)){
@@ -1077,7 +1072,7 @@ bandsize(Window *w)
drawborder(or, 0);
flushimage(display, 1);
wsetcursor(w, 1);
- if(mouse->buttons!=0 || Dx(or)<100 || Dy(or)<3*font->height){
+ if(mouse->buttons!=0 || !goodrect(or)){
while(mouse->buttons)
readmouse(mousectl);
return nil;
diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c
index 9d1cf796e..a19c5a4e8 100644
--- a/sys/src/cmd/rio/wctl.c
+++ b/sys/src/cmd/rio/wctl.c
@@ -90,16 +90,19 @@ goodrect(Rectangle r)
{
if(!eqrect(canonrect(r), r))
return 0;
- if(Dx(r)<100 || Dy(r)<3*font->height)
- return 0;
- /* must have some screen and border visible so we can move it out of the way */
- if(Dx(r) >= Dx(screen->r) && Dy(r) >= Dy(screen->r))
- return 0;
/* reasonable sizes only please */
if(Dx(r) > BIG*Dx(screen->r))
return 0;
if(Dy(r) > BIG*Dx(screen->r))
return 0;
+ if(Dx(r) < 100 || Dy(r) < 3*font->height)
+ return 0;
+ /* window must be on screen */
+ if(!rectXrect(screen->r, r))
+ return 0;
+ /* must have some screen and border visible so we can move it out of the way */
+ if(rectinrect(screen->r, insetrect(r, Borderwidth)))
+ return 0;
return 1;
}
@@ -159,6 +162,8 @@ shift(int *minp, int *maxp, int min, int max)
}
if(*minp < min){
*maxp += min-*minp;
+ if(*maxp > max)
+ *maxp = max;
*minp = min;
}
}
@@ -355,6 +360,8 @@ wctlcmd(Window *w, Rectangle r, int cmd, char *err)
r = rectonscreen(r);
/* fall through */
case Resize:
+ if(eqrect(r, w->screenr))
+ return 1;
if(!goodrect(r)){
strcpy(err, Ebadwr);
return -1;
@@ -363,8 +370,6 @@ wctlcmd(Window *w, Rectangle r, int cmd, char *err)
strcpy(err, "window not current");
return -1;
}
- if(eqrect(r, w->screenr))
- return 1;
i = allocwindow(wscreen, r, Refbackup, DNofill);
if(i == nil){
strcpy(err, Ewalloc);
diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c
index fc9a1176d..74758bcc5 100644
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -45,6 +45,7 @@ wmk(Image *i, Mousectl *mc, Channel *ck, Channel *cctl, int scrolling)
w->mouseread = chancreate(sizeof(Mousereadmesg), 0);
w->wctlread = chancreate(sizeof(Consreadmesg), 0);
w->complete = chancreate(sizeof(Completion*), 0);
+ w->gone = chancreate(sizeof(char*), 0);
w->scrollr = r;
w->scrollr.max.x = r.min.x+Scrollwid;
w->lastsr = ZR;
@@ -152,8 +153,7 @@ wclose(Window *w)
return 0;
if(i < 0)
error("negative ref count");
- if(!w->deleted)
- wclunk(w);
+ wclunk(w);
wsendctlmesg(w, Exited, ZR, nil);
return 1;
}
@@ -170,7 +170,7 @@ winctl(void *arg)
char *s, *t, part[3];
Window *w;
Mousestate *mp, m;
- enum { WKbd, WKbdread, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, WComplete, NWALT };
+ enum { WKbd, WKbdread, WMouse, WMouseread, WCtl, WCwrite, WCread, WWread, WComplete, Wgone, NWALT };
Alt alts[NWALT+1];
Mousereadmesg mrm;
Kbdreadmesg krm;
@@ -222,6 +222,9 @@ winctl(void *arg)
alts[WComplete].c = w->complete;
alts[WComplete].v = &cr;
alts[WComplete].op = CHANRCV;
+ alts[Wgone].c = w->gone;
+ alts[Wgone].v = "window deleted";
+ alts[Wgone].op = CHANNOP;
alts[NWALT].op = CHANEND;
memset(kbdq, 0, sizeof(kbdq));
@@ -229,28 +232,38 @@ winctl(void *arg)
npart = 0;
lastb = -1;
for(;;){
- alts[WKbdread].op = (w->kbdopen && kbdqw != kbdqr) ?
- CHANSND : CHANNOP;
- alts[WMouseread].op = (w->mouseopen && w->mouse.counter != w->mouse.lastcounter) ?
- CHANSND : CHANNOP;
- alts[WCwrite].op = (!w->scrolling && !w->mouseopen && w->qh>w->org+w->nchars) ?
- CHANNOP : CHANSND;
- alts[WWread].op = (w->deleted || !w->wctlready) ?
- CHANNOP : CHANSND;
-
- /* this code depends on NL and EOT fitting in a single byte */
- /* kind of expensive for each loop; worth precomputing? */
- if(w->holding)
- alts[WCread].op = CHANNOP;
- else if(npart || (w->rawing && w->nraw>0))
- alts[WCread].op = CHANSND;
- else{
+ if(w->i==nil){
+ /* window deleted */
+ alts[Wgone].op = CHANSND;
+
+ alts[WKbdread].op = CHANNOP;
+ alts[WMouseread].op = CHANNOP;
+ alts[WCwrite].op = CHANNOP;
+ alts[WWread].op = CHANNOP;
alts[WCread].op = CHANNOP;
- for(i=w->qh; i<w->nr; i++){
- c = w->r[i];
- if(c=='\n' || c=='\004'){
- alts[WCread].op = CHANSND;
- break;
+ } else {
+ alts[WKbdread].op = (w->kbdopen && kbdqw != kbdqr) ?
+ CHANSND : CHANNOP;
+ alts[WMouseread].op = (w->mouseopen && w->mouse.counter != w->mouse.lastcounter) ?
+ CHANSND : CHANNOP;
+ alts[WCwrite].op = w->scrolling || w->mouseopen || (w->qh <= w->org+w->nchars) ?
+ CHANSND : CHANNOP;
+ alts[WWread].op = w->wctlready ?
+ CHANSND : CHANNOP;
+ /* this code depends on NL and EOT fitting in a single byte */
+ /* kind of expensive for each loop; worth precomputing? */
+ if(w->holding)
+ alts[WCread].op = CHANNOP;
+ else if(npart || (w->rawing && w->nraw>0))
+ alts[WCread].op = CHANSND;
+ else{
+ alts[WCread].op = CHANNOP;
+ for(i=w->qh; i<w->nr; i++){
+ c = w->r[i];
+ if(c=='\n' || c=='\004'){
+ alts[WCread].op = CHANSND;
+ break;
+ }
}
}
}
@@ -408,25 +421,16 @@ winctl(void *arg)
case WWread:
w->wctlready = 0;
recv(cwrm.c1, &pair);
- if(w->deleted || w->i==nil)
- pair.ns = sprint(pair.s, "");
- else{
- s = "visible";
- for(i=0; i<nhidden; i++)
- if(hidden[i] == w){
- s = "hidden";
- break;
- }
- t = "notcurrent";
- if(w == input)
- t = "current";
- pair.ns = snprint(pair.s, pair.ns, "%11d %11d %11d %11d %s %s ",
- w->i->r.min.x, w->i->r.min.y, w->i->r.max.x, w->i->r.max.y, t, s);
- }
+ s = Dx(w->screenr) > 0 ? "visible" : "hidden";
+ t = "notcurrent";
+ if(w == input)
+ t = "current";
+ pair.ns = snprint(pair.s, pair.ns, "%11d %11d %11d %11d %s %s ",
+ w->i->r.min.x, w->i->r.min.y, w->i->r.max.x, w->i->r.max.y, t, s);
send(cwrm.c2, &pair);
continue;
case WComplete:
- if(!w->deleted){
+ if(w->i!=nil){
if(!cr->advance)
showcandidates(w, cr);
if(cr->advance){
@@ -441,7 +445,7 @@ winctl(void *arg)
freecompletion(cr);
break;
}
- if(!w->deleted)
+ if(w->i!=nil && Dx(w->screenr) > 0)
flushimage(display, 1);
}
}
@@ -620,7 +624,7 @@ wkeyctl(Window *w, Rune r)
return;
}
- if(w->deleted)
+ if(w->i==nil)
return;
/* navigation keys work only when mouse and kbd is not open */
if(!w->mouseopen)
@@ -718,6 +722,8 @@ wkeyctl(Window *w, Rune r)
case Kdel: /* send interrupt */
w->qh = w->nr;
wshow(w, w->qh);
+ if(w->notefd < 0)
+ return;
notefd = emalloc(sizeof(int));
*notefd = dup(w->notefd, -1);
proccreate(interruptproc, notefd, 4096);
@@ -920,7 +926,7 @@ wmousectl(Window *w)
}
incref(w); /* hold up window while we track */
- if(w->deleted)
+ if(w->i==nil)
goto Return;
if(ptinrect(w->mc.xy, w->scrollr)){
if(but)
@@ -1176,26 +1182,24 @@ wctlmesg(Window *w, int m, Rectangle r, void *p)
break;
/* fall thrugh for redraw after input change */
case Repaint:
- if(w->deleted || Dx(w->screenr)<=0)
+ if(w->i==nil || Dx(w->screenr)<=0)
break;
wrepaint(w);
flushimage(display, 1);
break;
case Refresh:
- if(w->deleted || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r) || w->mouseopen)
+ if(w->i==nil || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r) || w->mouseopen)
break;
wrefresh(w, r);
flushimage(display, 1);
break;
case Movemouse:
- if(w->deleted || Dx(w->screenr)<=0 || !ptinrect(r.min, w->i->r))
+ if(w->i==nil || Dx(w->screenr)<=0 || !ptinrect(r.min, w->i->r))
break;
wmovemouse(w, r.min);
case Rawon:
break;
case Rawoff:
- if(w->deleted)
- break;
while(w->nraw > 0){
wkeyctl(w, w->raw[0]);
--w->nraw;
@@ -1204,7 +1208,7 @@ wctlmesg(Window *w, int m, Rectangle r, void *p)
break;
case Holdon:
case Holdoff:
- if(w->deleted)
+ if(w->i==nil)
break;
if(w==input)
wsetcursor(w, 0);
@@ -1212,17 +1216,19 @@ wctlmesg(Window *w, int m, Rectangle r, void *p)
flushimage(display, 1);
break;
case Deleted:
- if(w->deleted)
- break;
wclunk(w);
- write(w->notefd, "hangup", 6);
- proccreate(deletetimeoutproc, estrdup(w->name), 4096);
- wclosewin(w);
+ if(w->notefd >= 0)
+ write(w->notefd, "hangup", 6);
+ if(w->i!=nil){
+ proccreate(deletetimeoutproc, estrdup(w->name), 4096);
+ wclosewin(w);
+ }
break;
case Exited:
wclosewin(w);
frclear(w, TRUE);
- close(w->notefd);
+ if(w->notefd >= 0)
+ close(w->notefd);
chanfree(w->mc.c);
chanfree(w->ck);
chanfree(w->cctl);
@@ -1232,6 +1238,7 @@ wctlmesg(Window *w, int m, Rectangle r, void *p)
chanfree(w->wctlread);
chanfree(w->kbdread);
chanfree(w->complete);
+ chanfree(w->gone);
free(w->raw);
free(w->r);
free(w->dir);
@@ -1304,7 +1311,7 @@ wsetcursor(Window *w, int force)
{
Cursor *p;
- if(w==nil || w->deleted || w->i==nil || Dx(w->screenr)<=0)
+ if(w==nil || w->i==nil || Dx(w->screenr)<=0)
p = nil;
else if(wpointto(mouse->xy) == w){
p = w->cursorp;
@@ -1329,7 +1336,7 @@ riosetcursor(Cursor *p, int force)
void
wtopme(Window *w)
{
- if(w!=nil && w->i!=nil && !w->deleted && w->topped!=topped){
+ if(w!=nil && w->i!=nil && w->topped!=topped){
w->topped = ++topped;
topwindow(w->i);
flushimage(display, 1);
@@ -1339,7 +1346,7 @@ wtopme(Window *w)
void
wbottomme(Window *w)
{
- if(w!=nil && w->i!=nil && !w->deleted){
+ if(w!=nil && w->i!=nil){
w->topped = - ++topped;
bottomwindow(w->i);
flushimage(display, 1);
@@ -1377,6 +1384,9 @@ wclunk(Window *w)
{
int i;
+ if(w->deleted)
+ return;
+ w->deleted = TRUE;
if(w == input){
input = nil;
wsetcursor(w, 0);
@@ -1395,7 +1405,6 @@ wclunk(Window *w)
memmove(window+i, window+i+1, (nwindow-i)*sizeof(window[0]));
break;
}
- w->deleted = TRUE;
}
void
@@ -1403,6 +1412,8 @@ wclosewin(Window *w)
{
Image *i;
+ assert(w->deleted==TRUE);
+
i = w->i;
if(i){
w->i = nil;
diff --git a/sys/src/cmd/rio/xfid.c b/sys/src/cmd/rio/xfid.c
index 305f22875..03f06be95 100644
--- a/sys/src/cmd/rio/xfid.c
+++ b/sys/src/cmd/rio/xfid.c
@@ -363,7 +363,7 @@ xfidwrite(Xfid *x)
Rune *r;
Conswritemesg cwm;
Stringpair pair;
- enum { CWdata, CWflush, NCW };
+ enum { CWdata, CWgone, CWflush, NCW };
Alt alts[NCW+1];
w = x->f->w;
@@ -402,6 +402,9 @@ xfidwrite(Xfid *x)
alts[CWdata].c = w->conswrite;
alts[CWdata].v = &cwm;
alts[CWdata].op = CHANRCV;
+ alts[CWgone].c = w->gone;
+ alts[CWgone].v = nil;
+ alts[CWgone].op = CHANRCV;
alts[CWflush].c = x->flushc;
alts[CWflush].v = nil;
alts[CWflush].op = CHANRCV;
@@ -410,6 +413,16 @@ xfidwrite(Xfid *x)
switch(alt(alts)){
case CWdata:
break;
+ case CWgone:
+ qlock(&x->active);
+ if(!x->flushing){
+ filsysrespond(x->fs, x, &fc, Edeleted);
+ qunlock(&x->active);
+ free(r);
+ return;
+ }
+ qunlock(&x->active);
+ /* no break */
case CWflush:
free(r);
filsyscancel(x);
@@ -609,9 +622,9 @@ xfidread(Xfid *x)
Consreadmesg cwrm;
Kbdreadmesg krm;
Stringpair pair;
- enum { CRdata, CRflush, NCR };
- enum { MRdata, MRflush, NMR };
- enum { WCRdata, WCRflush, NWCR };
+ enum { CRdata, CRgone, CRflush, NCR };
+ enum { MRdata, MRgone, MRflush, NMR };
+ enum { WCRdata, WCRgone, WCRflush, NWCR };
Alt alts[NCR+1];
w = x->f->w;
@@ -629,6 +642,9 @@ xfidread(Xfid *x)
alts[CRdata].c = w->consread;
alts[CRdata].v = &crm;
alts[CRdata].op = CHANRCV;
+ alts[CRgone].c = w->gone;
+ alts[CRgone].v = nil;
+ alts[CRgone].op = CHANRCV;
alts[CRflush].c = x->flushc;
alts[CRflush].v = nil;
alts[CRflush].op = CHANRCV;
@@ -637,6 +653,15 @@ xfidread(Xfid *x)
switch(alt(alts)){
case CRdata:
break;
+ case CRgone:
+ qlock(&x->active);
+ if(!x->flushing){
+ filsysrespond(x->fs, x, &fc, Edeleted);
+ qunlock(&x->active);
+ return;
+ }
+ qunlock(&x->active);
+ /* no break */
case CRflush:
filsyscancel(x);
return;
@@ -683,6 +708,9 @@ xfidread(Xfid *x)
alts[MRdata].c = w->mouseread;
alts[MRdata].v = &mrm;
alts[MRdata].op = CHANRCV;
+ alts[MRgone].c = w->gone;
+ alts[MRgone].v = nil;
+ alts[MRgone].op = CHANRCV;
alts[MRflush].c = x->flushc;
alts[MRflush].v = nil;
alts[MRflush].op = CHANRCV;
@@ -691,6 +719,15 @@ xfidread(Xfid *x)
switch(alt(alts)){
case MRdata:
break;
+ case MRgone:
+ qlock(&x->active);
+ if(!x->flushing){
+ filsysrespond(x->fs, x, &fc, Edeleted);
+ qunlock(&x->active);
+ return;
+ }
+ qunlock(&x->active);
+ /* no break */
case MRflush:
filsyscancel(x);
return;
@@ -723,6 +760,9 @@ xfidread(Xfid *x)
alts[MRdata].c = w->kbdread;
alts[MRdata].v = &krm;
alts[MRdata].op = CHANRCV;
+ alts[MRgone].c = w->gone;
+ alts[MRgone].v = nil;
+ alts[MRgone].op = CHANRCV;
alts[MRflush].c = x->flushc;
alts[MRflush].v = nil;
alts[MRflush].op = CHANRCV;
@@ -731,6 +771,15 @@ xfidread(Xfid *x)
switch(alt(alts)){
case MRdata:
break;
+ case MRgone:
+ qlock(&x->active);
+ if(!x->flushing){
+ filsysrespond(x->fs, x, &fc, Edeleted);
+ qunlock(&x->active);
+ return;
+ }
+ qunlock(&x->active);
+ /* no break */
case MRflush:
filsyscancel(x);
return;
@@ -741,7 +790,7 @@ xfidread(Xfid *x)
qlock(&x->active);
if(x->flushing){
qunlock(&x->active);
- free(t); /* wake up window and toss data */
+ free(t); /* toss data */
recv(x->flushc, nil); /* wake up flushing xfid */
filsyscancel(x);
return;
@@ -851,6 +900,9 @@ xfidread(Xfid *x)
alts[WCRdata].c = w->wctlread;
alts[WCRdata].v = &cwrm;
alts[WCRdata].op = CHANRCV;
+ alts[WCRgone].c = w->gone;
+ alts[WCRgone].v = nil;
+ alts[WCRgone].op = CHANRCV;
alts[WCRflush].c = x->flushc;
alts[WCRflush].v = nil;
alts[WCRflush].op = CHANRCV;
@@ -859,6 +911,15 @@ xfidread(Xfid *x)
switch(alt(alts)){
case WCRdata:
break;
+ case WCRgone:
+ qlock(&x->active);
+ if(!x->flushing){
+ filsysrespond(x->fs, x, &fc, Edeleted);
+ qunlock(&x->active);
+ return;
+ }
+ qunlock(&x->active);
+ /* no break */
case WCRflush:
filsyscancel(x);
return;