]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/rio/rio.c
rio: get rid of window delete thread, fix mysterious disappearing windows
[plan9front.git] / sys / src / cmd / rio / rio.c
index 0c1564f53137550925223fbe2c46f3d049d928cf..272fa5e716295cffd8131d9816c93005ee1ef08e 100644 (file)
@@ -39,7 +39,6 @@ int           threadrforkflag = 0;    /* should be RFENVG but that hides rio from plumber */
 void   mousethread(void*);
 void   keyboardthread(void*);
 void   winclosethread(void*);
-void   deletethread(void*);
 void   initcmd(void*);
 Channel* initkbd(void);
 
@@ -121,7 +120,6 @@ void
 threadmain(int argc, char *argv[])
 {
        char *initstr, *kbdin, *s;
-       static void *arg[1];
        char buf[256];
        Image *i;
        Rectangle r;
@@ -191,7 +189,6 @@ threadmain(int argc, char *argv[])
 
        exitchan = chancreate(sizeof(int), 0);
        winclosechan = chancreate(sizeof(Window*), 0);
-       deletechan = chancreate(sizeof(char*), 0);
 
        view = screen;
        viewr = view->r;
@@ -212,7 +209,6 @@ threadmain(int argc, char *argv[])
        threadcreate(keyboardthread, nil, STACK);
        threadcreate(mousethread, nil, STACK);
        threadcreate(winclosethread, nil, STACK);
-       threadcreate(deletethread, nil, STACK);
        filsys = filsysinit(xfidinit());
 
        if(filsys == nil)
@@ -355,11 +351,51 @@ keyboardthread(void*)
        }
 }
 
+int
+inborder(Rectangle r, Point xy)
+{
+       return ptinrect(xy, r) && !ptinrect(xy, insetrect(r, Selborder));
+}
+
+Rectangle
+whichrect(Rectangle r, Point p, int which)
+{
+       switch(which){
+       case 0: /* top left */
+               r = Rect(p.x, p.y, r.max.x, r.max.y);
+               break;
+       case 2: /* top right */
+               r = Rect(r.min.x, p.y, p.x+1, r.max.y);
+               break;
+       case 6: /* bottom left */
+               r = Rect(p.x, r.min.y, r.max.x, p.y+1);
+               break;
+       case 8: /* bottom right */
+               r = Rect(r.min.x, r.min.y, p.x+1, p.y+1);
+               break;
+       case 1: /* top edge */
+               r = Rect(r.min.x, p.y, r.max.x, r.max.y);
+               break;
+       case 5: /* right edge */
+               r = Rect(r.min.x, r.min.y, p.x+1, r.max.y);
+               break;
+       case 7: /* bottom edge */
+               r = Rect(r.min.x, r.min.y, r.max.x, p.y+1);
+               break;
+       case 3: /* left edge */
+               r = Rect(p.x, r.min.y, r.max.x, r.max.y);
+               break;
+       }
+       return canonrect(r);
+}
+
 int
 portion(int x, int lo, int hi)
 {
        x -= lo;
        hi -= lo;
+       if(hi < 20)
+               return x > 0 ? 2 : 0;
        if(x < 20)
                return 0;
        if(x > hi-20)
@@ -368,24 +404,15 @@ portion(int x, int lo, int hi)
 }
 
 int
-whichcorner(Window *w, Point p)
+whichcorner(Rectangle r, Point p)
 {
        int i, j;
        
-       i = portion(p.x, w->screenr.min.x, w->screenr.max.x);
-       j = portion(p.y, w->screenr.min.y, w->screenr.max.y);
+       i = portion(p.x, r.min.x, r.max.x);
+       j = portion(p.y, r.min.y, r.max.y);
        return 3*j+i;
 }
 
-void
-cornercursor(Window *w, Point p, int force)
-{
-       if(w!=nil && winborder(w, p))
-               riosetcursor(corners[whichcorner(w, p)], force);
-       else
-               wsetcursor(w, force);
-}
-
 /* thread to allow fsysproc to synchronize window closing with main proc */
 void
 winclosethread(void*)
@@ -399,37 +426,6 @@ winclosethread(void*)
        }
 }
 
-/* thread to make Deleted windows that the client still holds disappear offscreen after an interval */
-void
-deletethread(void*)
-{
-       char *s;
-       Image *i;
-
-       threadsetname("deletethread");
-       for(;;){
-               s = recvp(deletechan);
-               i = namedimage(display, s);
-               if(i != nil){
-                       /* move it off-screen to hide it, since client is slow in letting it go */
-                       originwindow(i, i->r.min, view->r.max);
-                       freeimage(i);
-                       flushimage(display, 1);
-               }
-               free(s);
-       }
-}
-
-void
-deletetimeoutproc(void *v)
-{
-       char *s;
-
-       s = v;
-       sleep(750);     /* remove window from screen after 3/4 of a second */
-       sendp(deletechan, s);
-}
-
 /*
  * Button 6 - keyboard toggle - has been pressed.
  * Send event to keyboard, wait for button up, send that.
@@ -449,7 +445,7 @@ keyboardhide(void)
 void
 mousethread(void*)
 {
-       int sending, inside, scrolling, moving, band;
+       int sending, inside, scrolling, moving;
        Window *w, *winput;
        Image *i;
        Point xy;
@@ -464,7 +460,6 @@ mousethread(void*)
        threadsetname("mousethread");
        sending = FALSE;
        scrolling = FALSE;
-       moving = FALSE;
 
        alts[MReshape].c = mousectl->resizec;
        alts[MReshape].v = nil;
@@ -485,6 +480,7 @@ mousethread(void*)
                                break;
                        }
                Again:
+                       moving = FALSE;
                        winput = input;
                        /* override everything for the keyboard window */
                        if(wkeyboard!=nil && ptinrect(mouse->xy, wkeyboard->screenr)){
@@ -509,50 +505,40 @@ mousethread(void*)
                                else
                                        scrolling = mouse->buttons && ptinrect(xy, winput->scrollr);
                                /* topped will be zero or less if window has been bottomed */
-                               if(sending == FALSE && !scrolling && winborder(winput, mouse->xy) && winput->topped>0){
+                               if(sending == FALSE && !scrolling && inborder(winput->screenr, mouse->xy) && winput->topped>0)
                                        moving = TRUE;
-                               }else if(inside && (scrolling || winput->mouseopen || (mouse->buttons&1)))
+                               else if(inside && (scrolling || winput->mouseopen || (mouse->buttons&1)))
                                        sending = TRUE;
                        }else
                                sending = FALSE;
                        if(sending){
                        Sending:
-                               if(mouse->buttons == 0){
-                                       cornercursor(winput, mouse->xy, 0);
+                               wsetcursor(winput, FALSE);
+                               if(mouse->buttons == 0)
                                        sending = FALSE;
-                               }else
-                                       wsetcursor(winput, 0);
                                tmp = mousectl->Mouse;
                                tmp.xy = xy;
                                send(winput->mc.c, &tmp);
                                continue;
                        }
-                       w = wpointto(mouse->xy);
-                       /* change cursor if over anyone's border */
-                       if(w != nil)
-                               cornercursor(w, mouse->xy, 0);
-                       else
-                               riosetcursor(nil, 0);
                        if(moving && (mouse->buttons&7)){
                                incref(winput);
-                               band = mouse->buttons & 3;
-                               sweeping = 1;
-                               if(band)
+                               sweeping = TRUE;
+                               if(mouse->buttons & 3)
                                        i = bandsize(winput);
                                else
                                        i = drag(winput);
-                               sweeping = 0;
-                               if(i != nil){
+                               sweeping = FALSE;
+                               if(i != nil)
                                        wsendctlmesg(winput, Reshaped, i->r, i);
-                                       cornercursor(winput, mouse->xy, 1);
-                               }
-                               if(wclose(winput) == 0)
-                                       w = winput;
-                               else {
-                                       riosetcursor(nil, 0);
-                                       w = winput = nil;
-                               }
+                               wclose(winput);
+                               continue;
                        }
+                       w = wpointto(mouse->xy);
+                       if(w!=nil && inborder(w->screenr, mouse->xy))
+                               riosetcursor(corners[whichcorner(w->screenr, mouse->xy)]);
+                       else
+                               wsetcursor(w, FALSE);
                        /* we're not sending the event, but if button is down maybe we should */
                        if(mouse->buttons){
                                /* w->topped will be zero or less if window has been bottomed */
@@ -570,19 +556,17 @@ mousethread(void*)
                                }else{
                                        /* if button 1 event in the window, top the window and wait for button up. */
                                        /* otherwise, top the window and pass the event on */
-                                       if(wtop(mouse->xy) && (mouse->buttons!=1 || winborder(w, mouse->xy)))
+                                       if(wtop(mouse->xy) && (mouse->buttons!=1 || inborder(w->screenr, mouse->xy)))
                                                goto Again;
                                        goto Drain;
                                }
                        }
-                       moving = FALSE;
                        break;
 
                Drain:
                        do
                                readmouse(mousectl);
                        while(mousectl->buttons);
-                       moving = FALSE;
                        goto Again;     /* recalculate mouse position, cursor */
                }
 }
@@ -726,7 +710,7 @@ button3menu(void)
                free(menu3str[i]);
                menu3str[i] = nil;
        }
-       sweeping = 1;
+       sweeping = TRUE;
        switch(i = menuhit(3, mousectl, &menu3, wscreen)){
        case -1:
                break;
@@ -755,7 +739,7 @@ button3menu(void)
                unhide(i);
                break;
        }
-       sweeping = 0;
+       sweeping = FALSE;
 }
 
 void
@@ -821,9 +805,9 @@ Point
 onscreen(Point p)
 {
        p.x = max(screen->clipr.min.x, p.x);
-       p.x = min(screen->clipr.max.x, p.x);
+       p.x = min(screen->clipr.max.x-1, p.x);
        p.y = max(screen->clipr.min.y, p.y);
-       p.y = min(screen->clipr.max.y, p.y);
+       p.y = min(screen->clipr.max.y-1, p.y);
        return p;
 }
 
@@ -836,7 +820,7 @@ sweep(void)
 
        i = nil;
        menuing = TRUE;
-       riosetcursor(&crosscursor, 1);
+       riosetcursor(&crosscursor);
        while(mouse->buttons == 0)
                readmouse(mousectl);
        p0 = onscreen(mouse->xy);
@@ -848,6 +832,7 @@ sweep(void)
                if(!eqpt(mouse->xy, p)){
                        p = onscreen(mouse->xy);
                        r = canonrect(Rpt(p0, p));
+                       r = whichrect(r, p, whichcorner(r, p));
                        if(Dx(r)>5 && Dy(r)>5){
                                i = allocwindow(wscreen, r, Refnone, DNofill);
                                freeimage(oi);
@@ -869,18 +854,18 @@ sweep(void)
        freeimage(oi);
        if(i == nil)
                goto Rescue;
-       cornercursor(input, mouse->xy, 1);
+       riosetcursor(corners[whichcorner(i->r, mouse->xy)]);
        goto Return;
 
  Rescue:
+       riosetcursor(nil);
        freeimage(i);
        i = nil;
-       cornercursor(input, mouse->xy, 1);
+       flushimage(display, 1);
        while(mouse->buttons)
                readmouse(mousectl);
 
  Return:
-       moveto(mousectl, mouse->xy);    /* force cursor update; ugly */
        menuing = FALSE;
        return i;
 }
@@ -925,11 +910,11 @@ drag(Window *w)
        Rectangle r;
 
        menuing = TRUE;
+       riosetcursor(&boxcursor);
        om = mouse->xy;
-       riosetcursor(&boxcursor, 1);
-       dm = subpt(mouse->xy, w->screenr.min);
+       dm = subpt(om, w->screenr.min);
        d = subpt(w->screenr.max, w->screenr.min);
-       op = subpt(mouse->xy, dm);
+       op = subpt(om, dm);
        drawborder(Rect(op.x, op.y, op.x+d.x, op.y+d.y), 1);
        while(mouse->buttons==4){
                p = subpt(mouse->xy, dm);
@@ -941,10 +926,11 @@ drag(Window *w)
        }
        r = Rect(op.x, op.y, op.x+d.x, op.y+d.y);
        drawborder(r, 0);
-       cornercursor(w, mouse->xy, 1);
-       moveto(mousectl, mouse->xy);    /* force cursor update; ugly */
+       p = mouse->xy;
+       riosetcursor(inborder(r, p) ? corners[whichcorner(r, p)] : nil);
        menuing = FALSE;
-       if(mouse->buttons!=0 || !goodrect(r)){
+       if(mouse->buttons!=0 || !goodrect(r) || eqrect(r, w->screenr)){
+               flushimage(display, 1);
                while(mouse->buttons)
                        readmouse(mousectl);
                return nil;
@@ -952,107 +938,40 @@ drag(Window *w)
        return allocwindow(wscreen, r, Refbackup, DNofill);
 }
 
-Point
-cornerpt(Rectangle r, Point p, int which)
-{
-       switch(which){
-       case 0: /* top left */
-               p = Pt(r.min.x, r.min.y);
-               break;
-       case 2: /* top right */
-               p = Pt(r.max.x,r.min.y);
-               break;
-       case 6: /* bottom left */
-               p = Pt(r.min.x, r.max.y);
-               break;
-       case 8: /* bottom right */
-               p = Pt(r.max.x, r.max.y);
-               break;
-       case 1: /* top edge */
-               p = Pt(p.x,r.min.y);
-               break;
-       case 5: /* right edge */
-               p = Pt(r.max.x, p.y);
-               break;
-       case 7: /* bottom edge */
-               p = Pt(p.x, r.max.y);
-               break;
-       case 3:         /* left edge */
-               p = Pt(r.min.x, p.y);
-               break;
-       }
-       return p;
-}
-
-Rectangle
-whichrect(Rectangle r, Point p, int which)
-{
-       switch(which){
-       case 0: /* top left */
-               r = Rect(p.x, p.y, r.max.x, r.max.y);
-               break;
-       case 2: /* top right */
-               r = Rect(r.min.x, p.y, p.x, r.max.y);
-               break;
-       case 6: /* bottom left */
-               r = Rect(p.x, r.min.y, r.max.x, p.y);
-               break;
-       case 8: /* bottom right */
-               r = Rect(r.min.x, r.min.y, p.x, p.y);
-               break;
-       case 1: /* top edge */
-               r = Rect(r.min.x, p.y, r.max.x, r.max.y);
-               break;
-       case 5: /* right edge */
-               r = Rect(r.min.x, r.min.y, p.x, r.max.y);
-               break;
-       case 7: /* bottom edge */
-               r = Rect(r.min.x, r.min.y, r.max.x, p.y);
-               break;
-       case 3:         /* left edge */
-               r = Rect(p.x, r.min.y, r.max.x, r.max.y);
-               break;
-       }
-       return canonrect(r);
-}
-
 Image*
 bandsize(Window *w)
 {
        Rectangle r, or;
        Point p, startp;
-       int which, but;
+       int which, owhich, but;
 
-       p = mouse->xy;
+       owhich = -1;
+       or = w->screenr;
        but = mouse->buttons;
-       which = whichcorner(w, p);
-       p = cornerpt(w->screenr, p, which);
-       wmovemouse(w, p);
-       readmouse(mousectl);
-       r = whichrect(w->screenr, p, which);
-       drawborder(r, 1);
-       or = r;
-       startp = p;
-       
-       while(mouse->buttons==but){
+       startp = onscreen(mouse->xy);
+       drawborder(or, 1);
+       while(mouse->buttons == but) {
                p = onscreen(mouse->xy);
-               r = whichrect(w->screenr, p, which);
+               which = whichcorner(or, p);
+               if(which != owhich && which != 4 && (owhich|~which) & 1){
+                       owhich = which;
+                       riosetcursor(corners[which]);
+               }
+               r = whichrect(or, p, owhich);
                if(!eqrect(r, or) && goodrect(r)){
-                       drawborder(r, 1);
                        or = r;
+                       drawborder(r, 1);
                }
                readmouse(mousectl);
        }
-       p = mouse->xy;
        drawborder(or, 0);
-       wsetcursor(w, 1);
-       if(mouse->buttons!=0 || !goodrect(or)){
+       if(mouse->buttons!=0 || !goodrect(or) || eqrect(or, w->screenr)
+       || abs(p.x-startp.x)+abs(p.y-startp.y) <= 1){
+               flushimage(display, 1);
                while(mouse->buttons)
                        readmouse(mousectl);
                return nil;
        }
-       if(abs(p.x-startp.x)+abs(p.y-startp.y) <= 1)
-               return nil;
        return allocwindow(wscreen, or, Refbackup, DNofill);
 }
 
@@ -1062,7 +981,7 @@ pointto(int wait)
        Window *w;
 
        menuing = TRUE;
-       riosetcursor(&sightcursor, 1);
+       riosetcursor(&sightcursor);
        while(mouse->buttons == 0)
                readmouse(mousectl);
        if(mouse->buttons == 4)
@@ -1072,7 +991,7 @@ pointto(int wait)
        if(wait){
                while(mouse->buttons){
                        if(mouse->buttons!=4 && w !=nil){       /* cancel */
-                               cornercursor(input, mouse->xy, 0);
+                               riosetcursor(nil);
                                w = nil;
                        }
                        readmouse(mousectl);
@@ -1080,8 +999,7 @@ pointto(int wait)
                if(w != nil && wpointto(mouse->xy) != w)
                        w = nil;
        }
-       cornercursor(input, mouse->xy, 0);
-       moveto(mousectl, mouse->xy);    /* force cursor update; ugly */
+       riosetcursor(nil);
        menuing = FALSE;
        return w;
 }
@@ -1125,7 +1043,6 @@ move(void)
        i = drag(w);
        if(i)
                wsendctlmesg(w, Reshaped, i->r, i);
-       cornercursor(w, mouse->xy, 1);
        wclose(w);
 }
 
@@ -1302,8 +1219,13 @@ kbdproc(void *arg)
                servekbd = 1;
 
                /* read kbd state */
-               while((n = read(kfd, buf, sizeof(buf))) > 0)
-                       chanprint(c, "%.*s", n, buf);
+               while((n = read(kfd, buf, sizeof(buf)-1)) > 0){
+                       e = buf+n;
+                       e[-1] = 0;
+                       e[0] = 0;
+                       for(p = buf; p < e; p += strlen(p)+1)
+                               chanprint(c, "%s", p);
+               }
        } else {
                /* read single characters */
                p = buf;