diff options
| -rw-r--r-- | sys/src/cmd/rio/dat.h | 9 | ||||
| -rw-r--r-- | sys/src/cmd/rio/rio.c | 25 | ||||
| -rw-r--r-- | sys/src/cmd/rio/wctl.c | 19 | ||||
| -rw-r--r-- | sys/src/cmd/rio/wind.c | 129 | ||||
| -rw-r--r-- | sys/src/cmd/rio/xfid.c | 71 |
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; |
