fix double free bug, simplify error handling, reduce X11 calls

This commit is contained in:
MvA 2022-09-11 15:04:39 +02:00 committed by Dan Cross
parent 3e764832bc
commit 846f724983

View file

@ -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 golangs gc/subr.c */ /* unicode-aware case-insensitive strcmp, taken from golangs 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: