rio: fix window resize and attach race
if a window gets hidden/unhidden/resized too fast, the client might have no chance attaching to that image using winname. so we move the window offscreen instead and delay the freeimage() by doing it in the deletethread().
This commit is contained in:
parent
1c69f9c023
commit
681bcfa968
|
@ -38,6 +38,7 @@ typedef struct Mousestate Mousestate;
|
|||
typedef struct Ref Ref;
|
||||
typedef struct Timer Timer;
|
||||
typedef struct Wctlmesg Wctlmesg;
|
||||
typedef struct Wdelmesg Wdelmesg;
|
||||
typedef struct Window Window;
|
||||
typedef struct Xfid Xfid;
|
||||
|
||||
|
@ -80,6 +81,12 @@ struct Wctlmesg
|
|||
void *p;
|
||||
};
|
||||
|
||||
struct Wdelmesg
|
||||
{
|
||||
char *s;
|
||||
Image *i;
|
||||
};
|
||||
|
||||
struct Conswritemesg
|
||||
{
|
||||
Channel *cw; /* chan(Stringpair) */
|
||||
|
|
|
@ -205,7 +205,7 @@ threadmain(int argc, char *argv[])
|
|||
|
||||
exitchan = chancreate(sizeof(int), 0);
|
||||
winclosechan = chancreate(sizeof(Window*), 0);
|
||||
deletechan = chancreate(sizeof(char*), 0);
|
||||
deletechan = chancreate(sizeof(Wdelmesg), 0);
|
||||
|
||||
timerinit();
|
||||
threadcreate(keyboardthread, nil, STACK);
|
||||
|
@ -422,30 +422,28 @@ winclosethread(void*)
|
|||
void
|
||||
deletethread(void*)
|
||||
{
|
||||
char *s;
|
||||
Image *i;
|
||||
Wdelmesg m;
|
||||
|
||||
threadsetname("deletethread");
|
||||
for(;;){
|
||||
s = recvp(deletechan);
|
||||
i = namedimage(display, s);
|
||||
if(i != nil){
|
||||
recv(deletechan, &m);
|
||||
freeimage(m.i);
|
||||
m.i = namedimage(display, m.s);
|
||||
if(m.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);
|
||||
originwindow(m.i, m.i->r.min, view->r.max);
|
||||
}
|
||||
freeimage(i);
|
||||
free(s);
|
||||
freeimage(m.i);
|
||||
free(m.s);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
deletetimeoutproc(void *v)
|
||||
{
|
||||
char *s;
|
||||
|
||||
s = v;
|
||||
sleep(750); /* remove window from screen after 3/4 of a second */
|
||||
sendp(deletechan, s);
|
||||
send(deletechan, v);
|
||||
free(v);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -88,13 +88,35 @@ void
|
|||
wresize(Window *w, Image *i, int move)
|
||||
{
|
||||
Rectangle r, or;
|
||||
Wdelmesg *m;
|
||||
|
||||
or = w->i->r;
|
||||
if(move || (Dx(or)==Dx(i->r) && Dy(or)==Dy(i->r)))
|
||||
draw(i, i->r, w->i, nil, w->i->r.min);
|
||||
freeimage(w->i);
|
||||
|
||||
m = emalloc(sizeof(Wdelmesg));
|
||||
m->s = estrdup(w->name);
|
||||
m->i = w->i;
|
||||
|
||||
w->i = i;
|
||||
w->mc.image = i;
|
||||
|
||||
if(w->mouseopen){
|
||||
/*
|
||||
* do not freeimage() here because the client might be in
|
||||
* the process of attaching that image using winname.
|
||||
* move the old window offscreen unless its completely
|
||||
* hidden by the new window and let deletetimeoutproc
|
||||
* free the image after some delay.
|
||||
*/
|
||||
if(!rectinrect(or, w->screenr))
|
||||
originwindow(m->i, or.min, view->r.max);
|
||||
} else {
|
||||
freeimage(m->i);
|
||||
m->i = nil;
|
||||
}
|
||||
proccreate(deletetimeoutproc, m, 4096);
|
||||
|
||||
r = insetrect(i->r, Selborder+1);
|
||||
w->scrollr = r;
|
||||
w->scrollr.max.x = r.min.x+Scrollwid;
|
||||
|
@ -1070,7 +1092,6 @@ wsendctlmesg(Window *w, int type, Rectangle r, void *p)
|
|||
int
|
||||
wctlmesg(Window *w, int m, Rectangle r, void *p)
|
||||
{
|
||||
char buf[64];
|
||||
Image *i = p;
|
||||
|
||||
switch(m){
|
||||
|
@ -1088,9 +1109,7 @@ wctlmesg(Window *w, int m, Rectangle r, void *p)
|
|||
break;
|
||||
}
|
||||
w->screenr = r;
|
||||
strcpy(buf, w->name);
|
||||
wresize(w, i, m==Moved);
|
||||
proccreate(deletetimeoutproc, estrdup(buf), 4096);
|
||||
flushimage(display, 1);
|
||||
if(Dx(r)<=0){ /* window got hidden, if we had the input, drop it */
|
||||
if(w==input)
|
||||
|
@ -1177,7 +1196,6 @@ wctlmesg(Window *w, int m, Rectangle r, void *p)
|
|||
break;
|
||||
wclunk(w);
|
||||
write(w->notefd, "hangup", 6);
|
||||
proccreate(deletetimeoutproc, estrdup(w->name), 4096);
|
||||
wclosewin(w);
|
||||
break;
|
||||
case Exited:
|
||||
|
@ -1361,14 +1379,13 @@ wclunk(Window *w)
|
|||
void
|
||||
wclosewin(Window *w)
|
||||
{
|
||||
Image *i;
|
||||
Wdelmesg m;
|
||||
|
||||
i = w->i;
|
||||
if(i){
|
||||
m.i = w->i;
|
||||
if(m.i){
|
||||
w->i = nil;
|
||||
/* move it off-screen to hide it, in case client is slow in letting it go */
|
||||
MOVEIT originwindow(i, i->r.min, view->r.max);
|
||||
freeimage(i);
|
||||
m.s = estrdup(w->name);
|
||||
send(deletechan, &m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue