mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
fix double free bug, simplify error handling, reduce X11 calls
This commit is contained in:
parent
3e764832bc
commit
846f724983
1 changed files with 58 additions and 63 deletions
|
@ -24,7 +24,6 @@ struct Win {
|
||||||
|
|
||||||
XDisplay *dpy;
|
XDisplay *dpy;
|
||||||
XWindow root;
|
XWindow root;
|
||||||
|
|
||||||
Atom net_active_window;
|
Atom net_active_window;
|
||||||
Reprog *exclude = nil;
|
Reprog *exclude = nil;
|
||||||
Win *win;
|
Win *win;
|
||||||
|
@ -38,8 +37,7 @@ Font *font;
|
||||||
Image *lightblue;
|
Image *lightblue;
|
||||||
|
|
||||||
|
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
PAD = 3,
|
PAD = 3,
|
||||||
MARGIN = 5
|
MARGIN = 5
|
||||||
};
|
};
|
||||||
|
@ -60,7 +58,7 @@ void*
|
||||||
erealloc(void *v, ulong n)
|
erealloc(void *v, ulong n)
|
||||||
{
|
{
|
||||||
v = realloc(v, n);
|
v = realloc(v, n);
|
||||||
if(v == nil)
|
if(v==nil)
|
||||||
sysfatal("out of memory reallocating");
|
sysfatal("out of memory reallocating");
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -69,9 +67,9 @@ char*
|
||||||
estrdup(char *s)
|
estrdup(char *s)
|
||||||
{
|
{
|
||||||
s = strdup(s);
|
s = strdup(s);
|
||||||
if(s == nil)
|
if(s==nil)
|
||||||
sysfatal("out of memory allocating");
|
sysfatal("out of memory allocating");
|
||||||
return s;
|
return(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
char*
|
||||||
|
@ -88,12 +86,12 @@ getproperty(XWindow w, Atom a)
|
||||||
s = XGetWindowProperty(dpy, w, a, 0, 100L, 0,
|
s = XGetWindowProperty(dpy, w, a, 0, 100L, 0,
|
||||||
AnyPropertyType, &type, &fmt, &n, &dummy, &p);
|
AnyPropertyType, &type, &fmt, &n, &dummy, &p);
|
||||||
|
|
||||||
if(s != 0){
|
if(s!=0){
|
||||||
XFree(p);
|
XFree(p);
|
||||||
return nil;
|
return(nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (char*)p;
|
return((char*)p);
|
||||||
}
|
}
|
||||||
|
|
||||||
XWindow
|
XWindow
|
||||||
|
@ -109,27 +107,27 @@ findname(XWindow w)
|
||||||
p = getproperty(w, XA_WM_NAME);
|
p = getproperty(w, XA_WM_NAME);
|
||||||
if(p){
|
if(p){
|
||||||
free(p);
|
free(p);
|
||||||
return w;
|
return(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", FALSE);
|
net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", FALSE);
|
||||||
p = getproperty(w, net_wm_name);
|
p = getproperty(w, net_wm_name);
|
||||||
if(p){
|
if(p){
|
||||||
free(p);
|
free(p);
|
||||||
return w;
|
return(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
rwin = 0;
|
rwin = 0;
|
||||||
|
|
||||||
s = XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin);
|
s = XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin);
|
||||||
|
|
||||||
if(s != 0){
|
if(s!=0){
|
||||||
for (i = 0; i < nxwin; i++){
|
for (i = 0; i < nxwin; i++){
|
||||||
w = findname(xwin[i]);
|
w = findname(xwin[i]);
|
||||||
if(w != 0){
|
if(w != 0){
|
||||||
rwin = w;
|
rwin = w;
|
||||||
break ;
|
break ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
XFree(xwin);
|
XFree(xwin);
|
||||||
}
|
}
|
||||||
|
@ -144,6 +142,7 @@ wcmp(const void *w1, const void *w2)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unicode-aware case-insensitive strcmp, taken from golang’s gc/subr.c */
|
/* unicode-aware case-insensitive strcmp, taken from golang’s gc/subr.c */
|
||||||
|
|
||||||
int
|
int
|
||||||
_cistrcmp(char *p, char *q)
|
_cistrcmp(char *p, char *q)
|
||||||
{
|
{
|
||||||
|
@ -189,49 +188,48 @@ refreshwin(void)
|
||||||
|
|
||||||
s = XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin);
|
s = XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin);
|
||||||
|
|
||||||
if(s == 0){
|
if(s==0){
|
||||||
if(xwin != NULL)
|
if(xwin!=NULL)
|
||||||
XFree(xwin);
|
XFree(xwin);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(xwin, nxwin, sizeof(xwin[0]), wcmp);
|
qsort(xwin, nxwin, sizeof(xwin[0]), wcmp);
|
||||||
|
|
||||||
nw = 0;
|
nw = 0;
|
||||||
for(i=0; i < nxwin; i++){
|
for(i=0; i<nxwin; i++){
|
||||||
memset(&attr, 0, sizeof attr);
|
memset(&attr, 0, sizeof attr);
|
||||||
xwin[i] = findname(xwin[i]);
|
xwin[i] = findname(xwin[i]);
|
||||||
if(xwin[i] == 0)
|
if(xwin[i]==0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
s = XGetWindowAttributes(dpy, xwin[i], &attr);
|
s = XGetWindowAttributes(dpy, xwin[i], &attr);
|
||||||
|
|
||||||
if(s == 0)
|
if(s==0)
|
||||||
continue;
|
continue;
|
||||||
if(attr.width <= 0 ||
|
if (attr.width <= 0 ||
|
||||||
attr.override_redirect ||
|
attr.override_redirect ||
|
||||||
attr.map_state != IsViewable)
|
attr.map_state != IsViewable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
s = XGetClassHint(dpy, xwin[i], &class);
|
s = XGetClassHint(dpy, xwin[i], &class);
|
||||||
|
|
||||||
if(s == 0)
|
if(s==0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (exclude != nil && regexec(exclude, class.res_name, nil, 0)){
|
if (exclude!=nil && regexec(exclude, class.res_name, nil, 0)) {
|
||||||
free(class.res_name);
|
free(class.res_name);
|
||||||
free(class.res_class);
|
free(class.res_class);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", FALSE);
|
net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", FALSE);
|
||||||
wmname = getproperty(xwin[i], net_wm_name);
|
wmname = getproperty(xwin[i], net_wm_name);
|
||||||
|
|
||||||
if(wmname == nil){
|
if(wmname==nil){
|
||||||
wmname = getproperty(xwin[i], XA_WM_NAME);
|
wmname = getproperty(xwin[i], XA_WM_NAME);
|
||||||
if(wmname == nil){
|
if(wmname==nil){
|
||||||
free(class.res_name);
|
free(class.res_name);
|
||||||
free(class.res_class);
|
free(class.res_class);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,24 +238,23 @@ refreshwin(void)
|
||||||
if(showwmnames==1)
|
if(showwmnames==1)
|
||||||
label = wmname;
|
label = wmname;
|
||||||
|
|
||||||
if(nw < nwin && win[nw].n == xwin[i] && strcmp(win[nw].label, label) == 0){
|
if(nw<nwin && win[nw].n==xwin[i] && strcmp(win[nw].label, label)==0) {
|
||||||
nw++;
|
nw++;
|
||||||
free(wmname);
|
free(wmname);
|
||||||
free(class.res_name);
|
free(class.res_name);
|
||||||
free(class.res_class);
|
free(class.res_class);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nw < nwin){
|
if(nw<nwin){
|
||||||
free(win[nw].label);
|
free(win[nw].label);
|
||||||
win[nw].label = nil;
|
win[nw].label = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(nw >= mwin){
|
if(nw>=mwin){
|
||||||
mwin += 8;
|
mwin += 8;
|
||||||
win = erealloc(win, mwin * sizeof(win[0]));
|
win = erealloc(win, mwin * sizeof(win[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
win[nw].n = xwin[i];
|
win[nw].n = xwin[i];
|
||||||
win[nw].label = estrdup(label);
|
win[nw].label = estrdup(label);
|
||||||
win[nw].dirty = 1;
|
win[nw].dirty = 1;
|
||||||
|
@ -270,11 +267,11 @@ refreshwin(void)
|
||||||
|
|
||||||
XFree(xwin);
|
XFree(xwin);
|
||||||
|
|
||||||
while(nwin > nw)
|
while(nwin>nw)
|
||||||
free(win[--nwin].label);
|
free(win[--nwin].label);
|
||||||
nwin = nw;
|
nwin = nw;
|
||||||
|
|
||||||
if(sortlabels == 1)
|
if(sortlabels==1)
|
||||||
qsort(win, nwin, sizeof(struct Win), winlabelcmp);
|
qsort(win, nwin, sizeof(struct Win), winlabelcmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,16 +310,16 @@ geometry(void)
|
||||||
rows = (Dy(screen->r) - 2 * MARGIN + PAD) / (font->height + PAD);
|
rows = (Dy(screen->r) - 2 * MARGIN + PAD) / (font->height + PAD);
|
||||||
if(rows*cols<nwin || rows*cols>=nwin*2){
|
if(rows*cols<nwin || rows*cols>=nwin*2){
|
||||||
ncols = 1;
|
ncols = 1;
|
||||||
if(nwin > 0)
|
if(nwin>0)
|
||||||
ncols = (nwin + rows - 1) / rows;
|
ncols = (nwin + rows - 1) / rows;
|
||||||
if(ncols != cols){
|
if(ncols!=cols){
|
||||||
cols = ncols;
|
cols = ncols;
|
||||||
z = 1;
|
z = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, font->height);
|
r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, font->height);
|
||||||
for(i=0; i <nwin; i++)
|
for(i=0; i<nwin; i++)
|
||||||
win[i].r =
|
win[i].r =
|
||||||
rectaddpt(
|
rectaddpt(
|
||||||
rectaddpt(r,
|
rectaddpt(r,
|
||||||
|
@ -341,11 +338,11 @@ redraw(Image *screen, int all)
|
||||||
all |= geometry();
|
all |= geometry();
|
||||||
if(all)
|
if(all)
|
||||||
draw(screen, screen->r, lightblue, nil, ZP);
|
draw(screen, screen->r, lightblue, nil, ZP);
|
||||||
for(i=0; i < nwin; i++)
|
for(i=0; i<nwin; i++)
|
||||||
if(all || win[i].dirty)
|
if(all || win[i].dirty)
|
||||||
drawwin(i);
|
drawwin(i);
|
||||||
if(!all)
|
if(!all)
|
||||||
for (; i < onwin; i++)
|
for (; i<onwin; i++)
|
||||||
drawnowin(i);
|
drawnowin(i);
|
||||||
onwin = nwin;
|
onwin = nwin;
|
||||||
}
|
}
|
||||||
|
@ -385,29 +382,29 @@ click(Mouse m)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
if(m.buttons == 0 || (m.buttons & ~4))
|
if(m.buttons==0 || (m.buttons&~4))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for(i=0; i < nwin; i++)
|
for(i=0; i<nwin; i++)
|
||||||
if(ptinrect(m.xy, win[i].r))
|
if(ptinrect(m.xy, win[i].r))
|
||||||
break;
|
break;
|
||||||
if(i == nwin)
|
if(i==nwin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
do
|
do
|
||||||
m = emouse();
|
m = emouse();
|
||||||
while(m.buttons == 4);
|
while(m.buttons==4);
|
||||||
|
|
||||||
if(m.buttons != 0){
|
if(m.buttons!=0){
|
||||||
do
|
do
|
||||||
m = emouse();
|
m = emouse();
|
||||||
while(m.buttons);
|
while(m.buttons);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for(j=0; j < nwin; j++)
|
for(j=0; j<nwin; j++)
|
||||||
if(ptinrect(m.xy, win[j].r))
|
if(ptinrect(m.xy, win[j].r))
|
||||||
break;
|
break;
|
||||||
if(j == i)
|
if(j==i)
|
||||||
selectwin(win[i].n);
|
selectwin(win[i].n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,7 +436,7 @@ main(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
exclude = regcomp(EARGF(usage()));
|
exclude = regcomp(EARGF(usage()));
|
||||||
if(exclude == nil)
|
if(exclude==nil)
|
||||||
sysfatal("Bad regexp");
|
sysfatal("Bad regexp");
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
|
@ -455,9 +452,11 @@ main(int argc, char **argv)
|
||||||
if(argc)
|
if(argc)
|
||||||
usage();
|
usage();
|
||||||
|
|
||||||
|
einit(Emouse | Ekeyboard);
|
||||||
|
Etimer = etimer(0, 1000);
|
||||||
|
|
||||||
dpy = XOpenDisplay("");
|
dpy = XOpenDisplay("");
|
||||||
if(dpy == nil)
|
if(dpy==nil)
|
||||||
sysfatal("open display: %r");
|
sysfatal("open display: %r");
|
||||||
|
|
||||||
root = DefaultRootWindow(dpy);
|
root = DefaultRootWindow(dpy);
|
||||||
|
@ -465,24 +464,20 @@ main(int argc, char **argv)
|
||||||
|
|
||||||
initdraw(0, 0, "winwatch");
|
initdraw(0, 0, "winwatch");
|
||||||
lightblue = allocimagemix(display, DPalebluegreen, DWhite);
|
lightblue = allocimagemix(display, DPalebluegreen, DWhite);
|
||||||
if(lightblue == nil)
|
if(lightblue==nil)
|
||||||
sysfatal("allocimagemix: %r");
|
sysfatal("allocimagemix: %r");
|
||||||
font = openfont(display, fontname);
|
font = openfont(display, fontname);
|
||||||
if(font == nil)
|
if(font==nil)
|
||||||
sysfatal("font '%s' not found", fontname);
|
sysfatal("font '%s' not found", fontname);
|
||||||
|
|
||||||
einit(Emouse | Ekeyboard);
|
|
||||||
Etimer = etimer(0, 1000);
|
|
||||||
|
|
||||||
XSetErrorHandler(winwatchxerrorhandler);
|
XSetErrorHandler(winwatchxerrorhandler);
|
||||||
|
|
||||||
refreshwin();
|
refreshwin();
|
||||||
redraw(screen, 1);
|
redraw(screen, 1);
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
switch(eread(Emouse|Ekeyboard|Etimer, &e)){
|
switch(eread(Emouse|Ekeyboard|Etimer, &e)){
|
||||||
case Ekeyboard:
|
case Ekeyboard:
|
||||||
if(e.kbdc==0x7F || e.kbdc == 'q')
|
if(e.kbdc==0x7F || e.kbdc=='q')
|
||||||
exits(0);
|
exits(0);
|
||||||
break;
|
break;
|
||||||
case Emouse:
|
case Emouse:
|
||||||
|
|
Loading…
Reference in a new issue