summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@gmx.de>2012-10-22 07:03:47 +0200
committercinap_lenrek <cinap_lenrek@gmx.de>2012-10-22 07:03:47 +0200
commit99216e01291ab687f74a54dd21dc0b8aa27de8d5 (patch)
tree8659b1e1892f63e96abf79df244d2d3858f3a26e /sys
parent54d2424a7cab7fe1808f7bdb7acade6af0e3428a (diff)
rio: fix deadlock
we can't really change the Window *input from outside the winctl() thread. the problem is that the window might end up reading the mouse (scroll, select) which makes the w->cctl channel block once you try to talk to the window again (from the mousethread). this also means we have to coordinate window switchin from the winctl proc waiting for the current window to release the input and then take over. thers a new Winctl message Topped that basically does that now using Wakeup and a chan to synchronize.
Diffstat (limited to 'sys')
-rw-r--r--sys/src/cmd/rio/dat.h12
-rw-r--r--sys/src/cmd/rio/rio.c14
-rw-r--r--sys/src/cmd/rio/wctl.c1
-rw-r--r--sys/src/cmd/rio/wind.c89
-rw-r--r--sys/src/cmd/rio/xfid.c2
5 files changed, 71 insertions, 47 deletions
diff --git a/sys/src/cmd/rio/dat.h b/sys/src/cmd/rio/dat.h
index 363be0256..690bd4168 100644
--- a/sys/src/cmd/rio/dat.h
+++ b/sys/src/cmd/rio/dat.h
@@ -61,13 +61,14 @@ enum /* control messages */
Wakeup,
Reshaped,
Moved,
+ Topped,
+ Repaint,
Refresh,
Movemouse,
Rawon,
Rawoff,
Holdon,
Holdoff,
- Repaint,
Deleted,
Exited,
};
@@ -76,7 +77,7 @@ struct Wctlmesg
{
int type;
Rectangle r;
- Image *image;
+ void *p;
};
struct Conswritemesg
@@ -132,7 +133,7 @@ struct Window
Mousectl mc;
Mouseinfo mouse;
Channel *ck; /* chan(char*) */
- Channel *cctl; /* chan(Wctlmesg)[20] */
+ Channel *cctl; /* chan(Wctlmesg)[4] */
Channel *conswrite; /* chan(Conswritemesg) */
Channel *consread; /* chan(Consreadmesg) */
Channel *mouseread; /* chan(Mousereadmesg) */
@@ -188,8 +189,7 @@ char* wcontents(Window*, int*);
int wbswidth(Window*, Rune);
int wclickmatch(Window*, int, int, int, uint*);
int wclose(Window*);
-int wctlmesg(Window*, int, Rectangle, Image*);
-int wctlmesg(Window*, int, Rectangle, Image*);
+int wctlmesg(Window*, int, Rectangle, void*);
uint wbacknl(Window*, uint, uint);
uint winsert(Window*, Rune*, int, uint);
void waddraw(Window*, Rune*, int);
@@ -213,7 +213,7 @@ void wresize(Window*, Image*, int);
void wscrdraw(Window*);
void wscroll(Window*, int);
void wselect(Window*);
-void wsendctlmesg(Window*, int, Rectangle, Image*);
+void wsendctlmesg(Window*, int, Rectangle, void*);
void wsetcursor(Window*, int);
void wsetname(Window*);
void wsetorigin(Window*, uint, int);
diff --git a/sys/src/cmd/rio/rio.c b/sys/src/cmd/rio/rio.c
index 119117c93..8dbbf47be 100644
--- a/sys/src/cmd/rio/rio.c
+++ b/sys/src/cmd/rio/rio.c
@@ -345,7 +345,7 @@ keyboardthread(void*)
while(s = recvp(kbdchan)){
if(*s == 'k' || *s == 'K')
shiftdown = utfrune(s+1, Kshift) != nil;
- if(input == nil || input->deleted || sendp(input->ck, s) <= 0)
+ if(input == nil || sendp(input->ck, s) <= 0)
free(s);
}
}
@@ -1113,10 +1113,8 @@ resize(void)
return;
incref(w);
i = sweep();
- if(i){
+ if(i)
wsendctlmesg(w, Reshaped, i->r, i);
- wcurrent(w);
- }
wclose(w);
}
@@ -1132,10 +1130,8 @@ move(void)
return;
incref(w);
i = drag(w, &r);
- if(i){
+ if(i)
wsendctlmesg(w, Moved, r, i);
- wcurrent(w);
- }
cornercursor(w, mouse->xy, 1);
wclose(w);
}
@@ -1154,8 +1150,6 @@ whide(Window *w)
incref(w);
i = allocimage(display, w->screenr, w->i->chan, 0, DNofill);
if(i){
- if(w == input)
- input = nil;
hidden[nhidden++] = w;
wsendctlmesg(w, Reshaped, ZR, i);
}
@@ -1180,7 +1174,6 @@ wunhide(Window *w)
--nhidden;
memmove(hidden+j, hidden+j+1, (nhidden-j)*sizeof(Window*));
wsendctlmesg(w, Reshaped, w->i->r, i);
- wcurrent(w);
}
wclose(w);
return i!=0;
@@ -1257,7 +1250,6 @@ new(Image *i, int hideit, int scrollit, int pid, char *dir, char *cmd, char **ar
threadcreate(winctl, w, 8192);
if(!hideit)
wcurrent(w);
- flushimage(display, 1);
if(pid == 0){
arg = emalloc(5*sizeof(void*));
arg[0] = w;
diff --git a/sys/src/cmd/rio/wctl.c b/sys/src/cmd/rio/wctl.c
index efe6949ff..9d1cf796e 100644
--- a/sys/src/cmd/rio/wctl.c
+++ b/sys/src/cmd/rio/wctl.c
@@ -388,6 +388,7 @@ wctlcmd(Window *w, Rectangle r, int cmd, char *err)
wbottomme(w);
return 1;
case Current:
+ wtopme(w);
wcurrent(w);
return 1;
case Hide:
diff --git a/sys/src/cmd/rio/wind.c b/sys/src/cmd/rio/wind.c
index 313247576..fab34f95a 100644
--- a/sys/src/cmd/rio/wind.c
+++ b/sys/src/cmd/rio/wind.c
@@ -113,10 +113,7 @@ wresize(Window *w, Image *i, int move)
wsetselect(w, w->q0, w->q1);
wscrdraw(w);
}
- if(w == input)
- wborder(w, Selborder);
- else
- wborder(w, Unselborder);
+ wborder(w, Selborder);
wsetname(w);
w->topped = ++topped;
w->resized = TRUE;
@@ -312,7 +309,7 @@ winctl(void *arg)
send(mrm.cm, &m.Mouse);
continue;
case WCtl:
- if(wctlmesg(w, wcm.type, wcm.r, wcm.image) == Exited){
+ if(wctlmesg(w, wcm.type, wcm.r, wcm.p) == Exited){
for(i=0; i<nelem(kbdq); i++)
free(kbdq[i]);
chanfree(crm.c1);
@@ -1058,26 +1055,29 @@ wselect(Window *w)
}
void
-wsendctlmesg(Window *w, int type, Rectangle r, Image *image)
+wsendctlmesg(Window *w, int type, Rectangle r, void *p)
{
Wctlmesg wcm;
wcm.type = type;
wcm.r = r;
- wcm.image = image;
+ wcm.p = p;
send(w->cctl, &wcm);
}
int
-wctlmesg(Window *w, int m, Rectangle r, Image *i)
+wctlmesg(Window *w, int m, Rectangle r, void *p)
{
char buf[64];
+ Image *i = p;
switch(m){
default:
error("unknown control message");
break;
case Wakeup:
+ if(p!=nil)
+ sendp((Channel*)p, w);
break;
case Moved:
case Reshaped:
@@ -1090,6 +1090,55 @@ wctlmesg(Window *w, int m, Rectangle r, Image *i)
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)
+ input = nil;
+ break;
+ }
+ /* fall through to get input if needed */
+ case Topped:
+ if(w->deleted || w==input)
+ break;
+ if(input!=nil){
+ Window *oi;
+ Channel *c;
+
+ oi = input;
+ incref(oi);
+
+ /*
+ * have to wait until old input responds before
+ * changing input to us because the window might
+ * currently be mouse tracking and it is not
+ * prepared for getting its input revoked.
+ */
+ c = chancreate(sizeof(void*), 0);
+ wsendctlmesg(oi, Wakeup, ZR, c);
+ recv(c, nil);
+ chanfree(c);
+
+ /*
+ * if we are still top window and nobody else has taken
+ * input from original window, take the input.
+ */
+ if(!w->deleted && w->topped==topped && oi==input){
+ input = w;
+
+ oi->wctlready = 1;
+ wsendctlmesg(oi, Repaint, ZR, nil);
+ }
+ wclose(oi);
+ } else
+ input = w;
+ w->wctlready = 1;
+ if(m!=Topped && w==input)
+ break;
+ /* fall thrugh for redraw after input change */
+ case Repaint:
+ if(w->deleted || 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)
@@ -1114,12 +1163,10 @@ wctlmesg(Window *w, int m, Rectangle r, Image *i)
break;
case Holdon:
case Holdoff:
- if(w == input)
- wsetcursor(w, 0);
- /* no break */
- case Repaint:
if(w->deleted)
break;
+ if(w==input)
+ wsetcursor(w, 0);
wrepaint(w);
flushimage(display, 1);
break;
@@ -1206,22 +1253,8 @@ wpointto(Point pt)
void
wcurrent(Window *w)
{
- Window *oi;
-
- if(wkeyboard!=nil && w==wkeyboard)
- return;
- oi = input;
- input = w;
- if(w != oi){
- if(oi){
- oi->wctlready = 1;
- wsendctlmesg(oi, Repaint, ZR, nil);
- }
- if(w){
- w->wctlready = 1;
- wsendctlmesg(w, Repaint, ZR, nil);
- }
- }
+ if(w!=nil && w!=input)
+ wsendctlmesg(w, Topped, ZR, nil);
}
void
diff --git a/sys/src/cmd/rio/xfid.c b/sys/src/cmd/rio/xfid.c
index 9359bc12c..a0da0c5fd 100644
--- a/sys/src/cmd/rio/xfid.c
+++ b/sys/src/cmd/rio/xfid.c
@@ -190,7 +190,6 @@ xfidattach(Xfid *x)
if(pid == 0)
pid = -1; /* make sure we don't pop a shell! - UGH */
w = new(i, hideit, scrollit, pid, nil, nil, nil);
- flushimage(display, 1);
newlymade = TRUE;
}else
err = Ewindow;
@@ -550,7 +549,6 @@ xfidwrite(Xfid *x)
filsysrespond(x->fs, x, &fc, buf);
return;
}
- flushimage(display, 1);
break;
default: