summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2013-01-09 16:32:53 +0100
committercinap_lenrek <cinap_lenrek@gmx.de>2013-01-09 16:32:53 +0100
commit681bcfa96897805c8b13c1ad29aa26841d839347 (patch)
tree3a0f82a50d873b175f8ebd3225e1a091849e57f1
parent1c69f9c023e64225ffca05f955077012880accb4 (diff)
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().
-rw-r--r--sys/src/cmd/rio/dat.h7
-rw-r--r--sys/src/cmd/rio/rio.c24
-rw-r--r--sys/src/cmd/rio/wind.c39
3 files changed, 46 insertions, 24 deletions
diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h
index 1f12eef48..3c7313113 100644
--- a/sys/src/cmd/rio/dat.h
+++ b/sys/src/cmd/rio/dat.h
@@ -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) */
diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c
index 8dbbf47be..36aec2d64 100644
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -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);
}
/*
diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c
index 49bb30da3..af19507c9 100644
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -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);
}
}