rio: preserve window z-order on resize, fix race conditions
sort the window array by w->topped before reshaping all windows. this preserves the window z-order. remove implicit focus change on reshape/move. it called wcurrent() in wtcl thread which might send a wctl message to itself, bad... also we might not want to change focus on reshape, like for the rio resize. so we set the input window explicitely in all call sites. window deletion was racy. wclosewin() destroys w->i, but it is called outside the wctl thread so it might just free the image under libframe doing some text selection. this is fixed the following: add wclunk() function, which basically just marks the window as deleted and removes the reference from the window[] and hidden[] arrays. (called on wclose() when refcount drops to zero). wclosewin() now just frees the image and is only called from the wctl thread on exit or when handing the Deleted message. get a reference to the window when doing sweeping or moving as the filesystem might just clunk it under us and we might end up sending wctl messages to a Exited window. wctl resize message has to fail if the window is not current as it might be hidden... would also be annoying.
This commit is contained in:
parent
558b9558d4
commit
624c9f5112
5 changed files with 223 additions and 183 deletions
|
@ -67,6 +67,7 @@ enum /* control messages */
|
|||
Rawoff,
|
||||
Holdon,
|
||||
Holdoff,
|
||||
Repaint,
|
||||
Deleted,
|
||||
Exited,
|
||||
};
|
||||
|
@ -194,6 +195,7 @@ uint wbacknl(Window*, uint, uint);
|
|||
uint winsert(Window*, Rune*, int, uint);
|
||||
void waddraw(Window*, Rune*, int);
|
||||
void wborder(Window*, int);
|
||||
void wclunk(Window*);
|
||||
void wclosewin(Window*);
|
||||
void wcurrent(Window*);
|
||||
void wcut(Window*);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
void keyboardsend(char*, int);
|
||||
int whide(Window*);
|
||||
int wunhide(int);
|
||||
int wunhide(Window*);
|
||||
void freescrtemps(void);
|
||||
int parsewctl(char**, Rectangle, Rectangle*, int*, int*, int*, int*, char**, char*, char*);
|
||||
int writewctl(Xfid*, char*);
|
||||
|
|
|
@ -347,7 +347,7 @@ keyboardthread(void*)
|
|||
while(s = recvp(kbdchan)){
|
||||
if(*s == 'k' || *s == 'K')
|
||||
shiftdown = utfrune(s+1, Kshift) != nil;
|
||||
if(input == nil || sendp(input->ck, s) <= 0)
|
||||
if(input == nil || input->deleted || sendp(input->ck, s) <= 0)
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
|
@ -470,7 +470,7 @@ void
|
|||
mousethread(void*)
|
||||
{
|
||||
int sending, inside, scrolling, moving, band;
|
||||
Window *oin, *w, *winput;
|
||||
Window *w, *winput;
|
||||
Image *i;
|
||||
Rectangle r;
|
||||
Point xy;
|
||||
|
@ -513,7 +513,7 @@ mousethread(void*)
|
|||
wtopme(wkeyboard);
|
||||
winput = wkeyboard;
|
||||
}
|
||||
if(winput!=nil && winput->i!=nil){
|
||||
if(winput!=nil && !winput->deleted && winput->i!=nil){
|
||||
/* convert to logical coordinates */
|
||||
xy.x = mouse->xy.x + (winput->i->r.min.x-winput->screenr.min.x);
|
||||
xy.y = mouse->xy.y + (winput->i->r.min.y-winput->screenr.min.y);
|
||||
|
@ -555,7 +555,7 @@ mousethread(void*)
|
|||
else
|
||||
riosetcursor(nil, 0);
|
||||
if(moving && (mouse->buttons&7)){
|
||||
oin = winput;
|
||||
incref(winput);
|
||||
band = mouse->buttons & 3;
|
||||
sweeping = 1;
|
||||
if(band)
|
||||
|
@ -564,18 +564,19 @@ mousethread(void*)
|
|||
i = drag(winput, &r);
|
||||
sweeping = 0;
|
||||
if(i != nil){
|
||||
if(winput == oin){
|
||||
if(band)
|
||||
wsendctlmesg(winput, Reshaped, i->r, i);
|
||||
else
|
||||
wsendctlmesg(winput, Moved, r, i);
|
||||
cornercursor(winput, mouse->xy, 1);
|
||||
}else
|
||||
freeimage(i);
|
||||
if(band)
|
||||
wsendctlmesg(winput, Reshaped, i->r, i);
|
||||
else
|
||||
wsendctlmesg(winput, Moved, r, i);
|
||||
cornercursor(winput, mouse->xy, 1);
|
||||
}
|
||||
if(wclose(winput) == 0)
|
||||
w = winput;
|
||||
else {
|
||||
riosetcursor(nil, 0);
|
||||
w = nil;
|
||||
}
|
||||
}
|
||||
if(w != nil)
|
||||
cornercursor(w, mouse->xy, 0);
|
||||
/* 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 */
|
||||
|
@ -583,8 +584,11 @@ mousethread(void*)
|
|||
if(mouse->buttons & 1){
|
||||
;
|
||||
}else if(mouse->buttons & 2){
|
||||
if(winput && !winput->mouseopen)
|
||||
if(winput && !winput->deleted && !winput->mouseopen){
|
||||
incref(winput);
|
||||
button2menu(winput);
|
||||
wclose(winput);
|
||||
}
|
||||
}else if(mouse->buttons & 4)
|
||||
button3menu();
|
||||
}else{
|
||||
|
@ -607,11 +611,17 @@ mousethread(void*)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
wtopcmp(void *a, void *b)
|
||||
{
|
||||
return (*(Window**)a)->topped - (*(Window**)b)->topped;
|
||||
}
|
||||
|
||||
void
|
||||
resized(void)
|
||||
{
|
||||
Image *im;
|
||||
int i, j, ishidden;
|
||||
int i, j;
|
||||
Rectangle r;
|
||||
Point o, n;
|
||||
Window *w;
|
||||
|
@ -627,10 +637,9 @@ resized(void)
|
|||
draw(view, view->r, background, nil, ZP);
|
||||
o = subpt(viewr.max, viewr.min);
|
||||
n = subpt(view->clipr.max, view->clipr.min);
|
||||
qsort(window, nwindow, sizeof(window[0]), wtopcmp);
|
||||
for(i=0; i<nwindow; i++){
|
||||
w = window[i];
|
||||
if(w->deleted)
|
||||
continue;
|
||||
r = rectsubpt(w->i->r, viewr.min);
|
||||
r.min.x = (r.min.x*n.x)/o.x;
|
||||
r.min.y = (r.min.y*n.y)/o.y;
|
||||
|
@ -639,26 +648,25 @@ resized(void)
|
|||
if(!goodrect(r))
|
||||
r = rectsubpt(w->i->r, viewr.min);
|
||||
r = rectaddpt(r, screen->clipr.min);
|
||||
ishidden = 0;
|
||||
for(j=0; j<nhidden; j++)
|
||||
if(w == hidden[j]){
|
||||
ishidden = 1;
|
||||
if(w == hidden[j])
|
||||
break;
|
||||
}
|
||||
if(ishidden){
|
||||
incref(w);
|
||||
if(j < nhidden){
|
||||
im = allocimage(display, r, screen->chan, 0, DWhite);
|
||||
r = ZR;
|
||||
}else
|
||||
} else
|
||||
im = allocwindow(wscreen, r, Refbackup, DWhite);
|
||||
if(im)
|
||||
wsendctlmesg(w, Reshaped, r, im);
|
||||
wclose(w);
|
||||
}
|
||||
viewr = screen->r;
|
||||
flushimage(display, 1);
|
||||
}
|
||||
|
||||
static int
|
||||
wcovered(Window *w, Rectangle r, int i)
|
||||
int
|
||||
obscured(Window *w, Rectangle r, int i)
|
||||
{
|
||||
Window *t;
|
||||
|
||||
|
@ -668,21 +676,21 @@ wcovered(Window *w, Rectangle r, int i)
|
|||
return 1;
|
||||
for(; i<nwindow; i++){
|
||||
t = window[i];
|
||||
if(t == w || t->topped <= w->topped || t->deleted)
|
||||
if(t == w || t->topped <= w->topped)
|
||||
continue;
|
||||
if(Dx(t->screenr) == 0 || Dy(t->screenr) == 0 || rectXrect(r, t->screenr) == 0)
|
||||
continue;
|
||||
if(r.min.y < t->screenr.min.y)
|
||||
if(!wcovered(w, Rect(r.min.x, r.min.y, r.max.x, t->screenr.min.y), i))
|
||||
if(!obscured(w, Rect(r.min.x, r.min.y, r.max.x, t->screenr.min.y), i))
|
||||
return 0;
|
||||
if(r.min.x < t->screenr.min.x)
|
||||
if(!wcovered(w, Rect(r.min.x, r.min.y, t->screenr.min.x, r.max.y), i))
|
||||
if(!obscured(w, Rect(r.min.x, r.min.y, t->screenr.min.x, r.max.y), i))
|
||||
return 0;
|
||||
if(r.max.y > t->screenr.max.y)
|
||||
if(!wcovered(w, Rect(r.min.x, t->screenr.max.y, r.max.x, r.max.y), i))
|
||||
if(!obscured(w, Rect(r.min.x, t->screenr.max.y, r.max.x, r.max.y), i))
|
||||
return 0;
|
||||
if(r.max.x > t->screenr.max.x)
|
||||
if(!wcovered(w, Rect(t->screenr.max.x, r.min.y, r.max.x, r.max.y), i))
|
||||
if(!obscured(w, Rect(t->screenr.max.x, r.min.y, r.max.x, r.max.y), i))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -699,13 +707,12 @@ button3menu(void)
|
|||
for(j=0; j<n; j++)
|
||||
if(window[i] == hidden[j])
|
||||
break;
|
||||
if(j < n || window[i]->deleted)
|
||||
continue;
|
||||
if(wcovered(window[i], window[i]->screenr, 0)){
|
||||
hidden[n++] = window[i];
|
||||
if(n >= nelem(hidden))
|
||||
break;
|
||||
}
|
||||
if(j == n)
|
||||
if(obscured(window[i], window[i]->screenr, 0)){
|
||||
hidden[n++] = window[i];
|
||||
if(n >= nelem(hidden))
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(n >= nelem(menu3str)-Hidden)
|
||||
n = nelem(menu3str)-Hidden-1;
|
||||
|
@ -752,9 +759,6 @@ button3menu(void)
|
|||
void
|
||||
button2menu(Window *w)
|
||||
{
|
||||
if(w->deleted)
|
||||
return;
|
||||
incref(w);
|
||||
if(w->scrolling)
|
||||
menu2str[Scroll] = "noscroll";
|
||||
else
|
||||
|
@ -803,7 +807,6 @@ button2menu(Window *w)
|
|||
wshow(w, w->nr);
|
||||
break;
|
||||
}
|
||||
wclose(w);
|
||||
wsendctlmesg(w, Wakeup, ZR, nil);
|
||||
flushimage(display, 1);
|
||||
}
|
||||
|
@ -1113,9 +1116,13 @@ resize(void)
|
|||
w = pointto(TRUE);
|
||||
if(w == nil)
|
||||
return;
|
||||
incref(w);
|
||||
i = sweep();
|
||||
if(i)
|
||||
if(i){
|
||||
wsendctlmesg(w, Reshaped, i->r, i);
|
||||
wcurrent(w);
|
||||
}
|
||||
wclose(w);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1128,10 +1135,14 @@ move(void)
|
|||
w = pointto(FALSE);
|
||||
if(w == nil)
|
||||
return;
|
||||
incref(w);
|
||||
i = drag(w, &r);
|
||||
if(i)
|
||||
if(i){
|
||||
wsendctlmesg(w, Moved, r, i);
|
||||
cornercursor(input, mouse->xy, 1);
|
||||
wcurrent(w);
|
||||
}
|
||||
cornercursor(w, mouse->xy, 1);
|
||||
wclose(w);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1145,38 +1156,39 @@ whide(Window *w)
|
|||
return -1;
|
||||
if(nhidden >= nelem(hidden))
|
||||
return 0;
|
||||
incref(w);
|
||||
i = allocimage(display, w->screenr, w->i->chan, 0, DWhite);
|
||||
if(i){
|
||||
if(w == input)
|
||||
input = nil;
|
||||
hidden[nhidden++] = w;
|
||||
wsendctlmesg(w, Reshaped, ZR, i);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
wclose(w);
|
||||
return i!=0;
|
||||
}
|
||||
|
||||
int
|
||||
wunhide(int h)
|
||||
wunhide(Window *w)
|
||||
{
|
||||
int j;
|
||||
Image *i;
|
||||
Window *w;
|
||||
|
||||
w = hidden[h];
|
||||
if(w == nil)
|
||||
return 0;
|
||||
if(h >= nhidden){
|
||||
wtopme(w);
|
||||
wcurrent(w);
|
||||
flushimage(display, 1);
|
||||
return 1;
|
||||
}
|
||||
for(j=0; j<nhidden; j++)
|
||||
if(hidden[j] == w)
|
||||
break;
|
||||
if(j == nhidden)
|
||||
return -1; /* not hidden */
|
||||
incref(w);
|
||||
i = allocwindow(wscreen, w->i->r, Refbackup, DWhite);
|
||||
if(i){
|
||||
--nhidden;
|
||||
memmove(hidden+h, hidden+h+1, (nhidden-h)*sizeof(Window*));
|
||||
memmove(hidden+j, hidden+j+1, (nhidden-j)*sizeof(Window*));
|
||||
wsendctlmesg(w, Reshaped, w->i->r, i);
|
||||
return 1;
|
||||
wcurrent(w);
|
||||
}
|
||||
return 0;
|
||||
wclose(w);
|
||||
return i!=0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1185,16 +1197,34 @@ hide(void)
|
|||
Window *w;
|
||||
|
||||
w = pointto(TRUE);
|
||||
if(w == nil)
|
||||
return;
|
||||
whide(w);
|
||||
if(w)
|
||||
whide(w);
|
||||
}
|
||||
|
||||
void
|
||||
unhide(int h)
|
||||
unhide(int j)
|
||||
{
|
||||
if(h >= Hidden)
|
||||
wunhide(h - Hidden);
|
||||
Window *w;
|
||||
|
||||
if(j < Hidden)
|
||||
return;
|
||||
j -= Hidden;
|
||||
w = hidden[j];
|
||||
if(w == nil)
|
||||
return;
|
||||
if(j < nhidden){
|
||||
wunhide(w);
|
||||
return;
|
||||
}
|
||||
/* uncover obscured window */
|
||||
for(j=0; j<nwindow; j++)
|
||||
if(window[j] == w){
|
||||
incref(w);
|
||||
wcurrent(w);
|
||||
wtopme(w);
|
||||
wclose(w);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Window*
|
||||
|
@ -1207,6 +1237,10 @@ new(Image *i, int hideit, int scrollit, int pid, char *dir, char *cmd, char **ar
|
|||
|
||||
if(i == nil)
|
||||
return nil;
|
||||
if(hideit && nhidden >= nelem(hidden)){
|
||||
freeimage(i);
|
||||
return nil;
|
||||
}
|
||||
cm = chancreate(sizeof(Mouse), 0);
|
||||
ck = chancreate(sizeof(char*), 0);
|
||||
cctl = chancreate(sizeof(Wctlmesg), 4);
|
||||
|
@ -1221,8 +1255,6 @@ new(Image *i, int hideit, int scrollit, int pid, char *dir, char *cmd, char **ar
|
|||
free(mc); /* wmk copies *mc */
|
||||
window = erealloc(window, ++nwindow*sizeof(Window*));
|
||||
window[nwindow-1] = w;
|
||||
if(nhidden >= nelem(hidden))
|
||||
hideit = 0;
|
||||
if(hideit){
|
||||
hidden[nhidden++] = w;
|
||||
w->screenr = ZR;
|
||||
|
|
|
@ -346,68 +346,32 @@ wctlnew(Rectangle rect, char *arg, int pid, int hideit, int scrollit, char *dir,
|
|||
}
|
||||
|
||||
int
|
||||
writewctl(Xfid *x, char *err)
|
||||
wctlcmd(Window *w, Rectangle r, int cmd, char *err)
|
||||
{
|
||||
int cnt, cmd, j, id, hideit, scrollit, pid;
|
||||
Image *i;
|
||||
char *arg, *dir;
|
||||
Rectangle rect;
|
||||
Window *w;
|
||||
|
||||
w = x->f->w;
|
||||
cnt = x->count;
|
||||
x->data[cnt] = '\0';
|
||||
id = 0;
|
||||
|
||||
rect = rectsubpt(w->screenr, screen->r.min);
|
||||
cmd = parsewctl(&arg, rect, &rect, &pid, &id, &hideit, &scrollit, &dir, x->data, err);
|
||||
if(cmd < 0)
|
||||
return -1;
|
||||
|
||||
if(mouse->buttons!=0 && cmd>=Top){
|
||||
strcpy(err, "action disallowed when mouse active");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(id != 0){
|
||||
for(j=0; j<nwindow; j++)
|
||||
if(window[j]->id == id)
|
||||
break;
|
||||
if(j == nwindow){
|
||||
strcpy(err, "no such window id");
|
||||
return -1;
|
||||
}
|
||||
w = window[j];
|
||||
if(w->deleted || w->i==nil){
|
||||
strcpy(err, "window deleted");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch(cmd){
|
||||
case New:
|
||||
return wctlnew(rect, arg, pid, hideit, scrollit, dir, err);
|
||||
case Set:
|
||||
if(pid > 0)
|
||||
wsetpid(w, pid, 0);
|
||||
return 1;
|
||||
case Move:
|
||||
rect = Rect(rect.min.x, rect.min.y, rect.min.x+Dx(w->screenr), rect.min.y+Dy(w->screenr));
|
||||
rect = rectonscreen(rect);
|
||||
r = Rect(r.min.x, r.min.y, r.min.x+Dx(w->screenr), r.min.y+Dy(w->screenr));
|
||||
r = rectonscreen(r);
|
||||
/* fall through */
|
||||
case Resize:
|
||||
if(!goodrect(rect)){
|
||||
if(!goodrect(r)){
|
||||
strcpy(err, Ebadwr);
|
||||
return -1;
|
||||
}
|
||||
if(eqrect(rect, w->screenr))
|
||||
if(w != input){
|
||||
strcpy(err, "window not current");
|
||||
return -1;
|
||||
}
|
||||
if(eqrect(r, w->screenr))
|
||||
return 1;
|
||||
i = allocwindow(wscreen, rect, Refbackup, DWhite);
|
||||
i = allocwindow(wscreen, r, Refbackup, DWhite);
|
||||
if(i == nil){
|
||||
strcpy(err, Ewalloc);
|
||||
return -1;
|
||||
}
|
||||
border(i, rect, Selborder, red, ZP);
|
||||
border(i, r, Selborder, red, ZP);
|
||||
wsendctlmesg(w, Reshaped, i->r, i);
|
||||
return 1;
|
||||
case Scroll:
|
||||
|
@ -441,26 +405,68 @@ writewctl(Xfid *x, char *err)
|
|||
}
|
||||
return 1;
|
||||
case Unhide:
|
||||
for(j=0; j<nhidden; j++)
|
||||
if(hidden[j] == w)
|
||||
break;
|
||||
if(j == nhidden){
|
||||
switch(wunhide(w)){
|
||||
case -1:
|
||||
strcpy(err, "window not hidden");
|
||||
return -1;
|
||||
}
|
||||
if(wunhide(j) == 0){
|
||||
case 0:
|
||||
strcpy(err, "hide failed");
|
||||
return -1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
case Delete:
|
||||
wsendctlmesg(w, Deleted, ZR, nil);
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(err, "invalid wctl message");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
writewctl(Xfid *x, char *err)
|
||||
{
|
||||
int cnt, cmd, id, hideit, scrollit, pid;
|
||||
char *arg, *dir;
|
||||
Rectangle r;
|
||||
Window *w;
|
||||
|
||||
w = x->f->w;
|
||||
cnt = x->count;
|
||||
x->data[cnt] = '\0';
|
||||
id = 0;
|
||||
|
||||
r = rectsubpt(w->screenr, screen->r.min);
|
||||
cmd = parsewctl(&arg, r, &r, &pid, &id, &hideit, &scrollit, &dir, x->data, err);
|
||||
if(cmd < 0)
|
||||
return -1;
|
||||
|
||||
if(id != 0){
|
||||
w = wlookid(id);
|
||||
if(w == 0){
|
||||
strcpy(err, "no such window id");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
switch(cmd){
|
||||
case New:
|
||||
return wctlnew(r, arg, pid, hideit, scrollit, dir, err);
|
||||
case Set:
|
||||
if(pid > 0)
|
||||
wsetpid(w, pid, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
incref(w);
|
||||
id = wctlcmd(w, r, cmd, err);
|
||||
wclose(w);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
wctlthread(void *v)
|
||||
{
|
||||
|
|
|
@ -131,7 +131,6 @@ wresize(Window *w, Image *i, int move)
|
|||
draw(i, i->r, w->i, nil, w->i->r.min);
|
||||
freeimage(w->i);
|
||||
w->i = i;
|
||||
wsetname(w);
|
||||
w->mc.image = i;
|
||||
r = insetrect(i->r, Selborder+1);
|
||||
w->scrollr = r;
|
||||
|
@ -151,10 +150,15 @@ wresize(Window *w, Image *i, int move)
|
|||
wsetselect(w, w->q0, w->q1);
|
||||
wscrdraw(w);
|
||||
}
|
||||
wborder(w, Selborder);
|
||||
if(w == input)
|
||||
wborder(w, Selborder);
|
||||
else
|
||||
wborder(w, Unselborder);
|
||||
wsetname(w);
|
||||
w->topped = ++topped;
|
||||
w->resized = TRUE;
|
||||
w->mouse.counter++;
|
||||
w->wctlready = 1;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -189,7 +193,7 @@ wclose(Window *w)
|
|||
if(i < 0)
|
||||
error("negative ref count");
|
||||
if(!w->deleted)
|
||||
wclosewin(w);
|
||||
wclunk(w);
|
||||
wsendctlmesg(w, Exited, ZR, nil);
|
||||
return 1;
|
||||
}
|
||||
|
@ -1121,24 +1125,16 @@ wctlmesg(Window *w, int m, Rectangle r, Image *i)
|
|||
w->screenr = r;
|
||||
strcpy(buf, w->name);
|
||||
wresize(w, i, m==Moved);
|
||||
w->wctlready = 1;
|
||||
proccreate(deletetimeoutproc, estrdup(buf), 4096);
|
||||
if(Dx(r) > 0){
|
||||
if(w != input)
|
||||
wcurrent(w);
|
||||
}else if(w == input)
|
||||
wcurrent(nil);
|
||||
flushimage(display, 1);
|
||||
break;
|
||||
case Refresh:
|
||||
if(w->deleted || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r))
|
||||
if(w->deleted || Dx(w->screenr)<=0 || !rectclip(&r, w->i->r) || w->mouseopen)
|
||||
break;
|
||||
if(!w->mouseopen)
|
||||
wrefresh(w, r);
|
||||
wrefresh(w, r);
|
||||
flushimage(display, 1);
|
||||
break;
|
||||
case Movemouse:
|
||||
if(sweeping || !ptinrect(r.min, w->i->r))
|
||||
if(w->deleted || Dx(w->screenr)<=0 || !ptinrect(r.min, w->i->r))
|
||||
break;
|
||||
wmovemouse(w, r.min);
|
||||
case Rawon:
|
||||
|
@ -1154,6 +1150,7 @@ wctlmesg(Window *w, int m, Rectangle r, Image *i)
|
|||
break;
|
||||
case Holdon:
|
||||
case Holdoff:
|
||||
case Repaint:
|
||||
if(w->deleted)
|
||||
break;
|
||||
wrepaint(w);
|
||||
|
@ -1162,11 +1159,13 @@ wctlmesg(Window *w, int m, Rectangle r, Image *i)
|
|||
case Deleted:
|
||||
if(w->deleted)
|
||||
break;
|
||||
wclunk(w);
|
||||
write(w->notefd, "hangup", 6);
|
||||
proccreate(deletetimeoutproc, estrdup(w->name), 4096);
|
||||
wclosewin(w);
|
||||
break;
|
||||
case Exited:
|
||||
wclosewin(w);
|
||||
frclear(w, TRUE);
|
||||
close(w->notefd);
|
||||
chanfree(w->mc.c);
|
||||
|
@ -1193,6 +1192,8 @@ wctlmesg(Window *w, int m, Rectangle r, Image *i)
|
|||
void
|
||||
wmovemouse(Window *w, Point p)
|
||||
{
|
||||
if(w != input || menuing || sweeping)
|
||||
return;
|
||||
p.x += w->screenr.min.x-w->i->r.min.x;
|
||||
p.y += w->screenr.min.y-w->i->r.min.y;
|
||||
moveto(mousectl, p);
|
||||
|
@ -1216,7 +1217,6 @@ wborder(Window *w, int type)
|
|||
else
|
||||
col = lighttitlecol;
|
||||
}
|
||||
|
||||
border(w->i, w->i->r, Selborder, col, ZP);
|
||||
}
|
||||
|
||||
|
@ -1230,7 +1230,6 @@ wpointto(Point pt)
|
|||
for(i=0; i<nwindow; i++){
|
||||
v = window[i];
|
||||
if(ptinrect(pt, v->screenr))
|
||||
if(!v->deleted)
|
||||
if(w==nil || v->topped>w->topped)
|
||||
w = v;
|
||||
}
|
||||
|
@ -1246,20 +1245,14 @@ wcurrent(Window *w)
|
|||
return;
|
||||
oi = input;
|
||||
input = w;
|
||||
if(oi!=w && oi!=nil)
|
||||
wrepaint(oi);
|
||||
if(w !=nil){
|
||||
wrepaint(w);
|
||||
wsetcursor(w, 0);
|
||||
}
|
||||
if(w != oi){
|
||||
if(oi){
|
||||
oi->wctlready = 1;
|
||||
wsendctlmesg(oi, Wakeup, ZR, nil);
|
||||
wsendctlmesg(oi, Repaint, ZR, nil);
|
||||
}
|
||||
if(w){
|
||||
w->wctlready = 1;
|
||||
wsendctlmesg(w, Wakeup, ZR, nil);
|
||||
wsendctlmesg(w, Repaint, ZR, nil);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1269,7 +1262,7 @@ wsetcursor(Window *w, int force)
|
|||
{
|
||||
Cursor *p;
|
||||
|
||||
if(w==nil || /*w!=input || */ w->i==nil || Dx(w->screenr)<=0)
|
||||
if(w==nil || w->deleted || w->i==nil || Dx(w->screenr)<=0)
|
||||
p = nil;
|
||||
else if(wpointto(mouse->xy) == w){
|
||||
p = w->cursorp;
|
||||
|
@ -1290,6 +1283,27 @@ riosetcursor(Cursor *p, int force)
|
|||
lastcursor = p;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
wtopme(Window *w)
|
||||
{
|
||||
if(w!=nil && w->i!=nil && !w->deleted && w->topped!=topped){
|
||||
w->topped = ++topped;
|
||||
topwindow(w->i);
|
||||
flushimage(display, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wbottomme(Window *w)
|
||||
{
|
||||
if(w!=nil && w->i!=nil && !w->deleted){
|
||||
w->topped = - ++topped;
|
||||
bottomwindow(w->i);
|
||||
flushimage(display, 1);
|
||||
}
|
||||
}
|
||||
|
||||
Window*
|
||||
wtop(Point pt)
|
||||
{
|
||||
|
@ -1299,34 +1313,14 @@ wtop(Point pt)
|
|||
if(w){
|
||||
if(w->topped == topped)
|
||||
return nil;
|
||||
topwindow(w->i);
|
||||
incref(w);
|
||||
wcurrent(w);
|
||||
flushimage(display, 1);
|
||||
w->topped = ++topped;
|
||||
wtopme(w);
|
||||
wclose(w);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
void
|
||||
wtopme(Window *w)
|
||||
{
|
||||
if(w!=nil && w->i!=nil && !w->deleted && w->topped!=topped){
|
||||
topwindow(w->i);
|
||||
flushimage(display, 1);
|
||||
w->topped = ++topped;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wbottomme(Window *w)
|
||||
{
|
||||
if(w!=nil && w->i!=nil && !w->deleted){
|
||||
bottomwindow(w->i);
|
||||
flushimage(display, 1);
|
||||
w->topped = - ++topped;
|
||||
}
|
||||
}
|
||||
|
||||
Window*
|
||||
wlookid(int id)
|
||||
{
|
||||
|
@ -1339,12 +1333,10 @@ wlookid(int id)
|
|||
}
|
||||
|
||||
void
|
||||
wclosewin(Window *w)
|
||||
wclunk(Window *w)
|
||||
{
|
||||
Rectangle r;
|
||||
int i;
|
||||
|
||||
w->deleted = TRUE;
|
||||
if(w == input){
|
||||
input = nil;
|
||||
wsetcursor(w, 0);
|
||||
|
@ -1360,16 +1352,24 @@ wclosewin(Window *w)
|
|||
for(i=0; i<nwindow; i++)
|
||||
if(window[i] == w){
|
||||
--nwindow;
|
||||
memmove(window+i, window+i+1, (nwindow-i)*sizeof(Window*));
|
||||
w->deleted = TRUE;
|
||||
r = w->i->r;
|
||||
/* move it off-screen to hide it, in case client is slow in letting it go */
|
||||
MOVEIT originwindow(w->i, r.min, view->r.max);
|
||||
freeimage(w->i);
|
||||
w->i = nil;
|
||||
return;
|
||||
memmove(window+i, window+i+1, (nwindow-i)*sizeof(window[0]));
|
||||
break;
|
||||
}
|
||||
error("unknown window in closewin");
|
||||
w->deleted = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
wclosewin(Window *w)
|
||||
{
|
||||
Image *i;
|
||||
|
||||
i = w->i;
|
||||
if(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);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue