diff options
Diffstat (limited to 'src/cmd/rio')
-rw-r--r-- | src/cmd/rio/winwatch.c | 838 |
1 files changed, 412 insertions, 426 deletions
diff --git a/src/cmd/rio/winwatch.c b/src/cmd/rio/winwatch.c index 66ec8cbe..1a93e78c 100644 --- a/src/cmd/rio/winwatch.c +++ b/src/cmd/rio/winwatch.c @@ -1,23 +1,25 @@ -/* slightly modified from -https://github.com/fhs/misc/blob/master/cmd/winwatch/winwatch.c -so as to deal with memory leaks and certain X errors */ +/* + * slightly modified from + * https://github.com/fhs/misc/blob/master/cmd/winwatch/winwatch.c + * so as to deal with memory leaks and certain X errors + */ #include <u.h> #include <libc.h> #include <draw.h> #include <event.h> #include <regexp.h> -#include <stdio.h> +#include <fmt.h> #include "../devdraw/x11-inc.h" AUTOLIB(X11); typedef struct Win Win; struct Win { - XWindow n; - int dirty; - char *label; - Rectangle r; + XWindow n; + int dirty; + char *label; + Rectangle r; }; XDisplay *dpy; @@ -37,502 +39,486 @@ Image *lightblue; XErrorHandler oldxerrorhandler; enum { - PAD = 3, - MARGIN = 5 + PAD = 3, + MARGIN = 5 }; static jmp_buf savebuf; -int +int winwatchxerrorhandler(XDisplay *disp, XErrorEvent *xe) { - char buf[100]; - - XGetErrorText(disp, xe->error_code, buf, 100); - fprintf(stderr, "winwatch: X error %s, request code %d\n", buf, - xe->request_code); - XFlush(disp); - XSync(disp, False); - XSetErrorHandler(oldxerrorhandler); - longjmp(savebuf, 1); + char buf[100]; + + XGetErrorText(disp, xe->error_code, buf, 100); + fprint(2, "winwatch: X error %s, request code %d\n", + buf, xe->request_code); + XFlush(disp); + XSync(disp, False); + XSetErrorHandler(oldxerrorhandler); + longjmp(savebuf, 1); + return(0); /* Not reached */ } void* erealloc(void *v, ulong n) { - v = realloc(v, n); - if (v == nil) - sysfatal("out of memory reallocating"); - return v; + v = realloc(v, n); + if(v==nil) + sysfatal("out of memory reallocating"); + return v; } char* estrdup(char *s) { - s = strdup(s); - if (s == nil) - sysfatal("out of memory allocating"); - return s; + s = strdup(s); + if(s==nil) + sysfatal("out of memory allocating"); + return(s); } char* getproperty(XWindow w, Atom a) { - uchar *p; - int fmt; - Atom type; - ulong n, dummy; - int s; - - n = 100; - p = nil; - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XGetWindowProperty(dpy, w, a, 0, 100L, 0, - AnyPropertyType, &type, &fmt, &n, &dummy, &p); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - - if (s == 0) - return (char *) p; - else { - free(p); - return nil; - } + uchar *p; + int fmt; + Atom type; + ulong n, dummy; + int s; + + n = 100; + p = nil; + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XGetWindowProperty(dpy, w, a, 0, 100L, 0, + AnyPropertyType, &type, &fmt, &n, &dummy, &p); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + if(s!=0){ + XFree(p); + return(nil); + } + + return((char*)p); } -XWindow +XWindow findname(XWindow w) { - int i; - uint nxwin; - XWindow dw1, dw2, *xwin; - char *p; - int s; - Atom net_wm_name; - - p = getproperty(w, XA_WM_NAME); - if (p) { - free(p); - return w; - } - - net_wm_name = XInternAtom (dpy, "_NET_WM_NAME", FALSE); - p = getproperty(w, net_wm_name); - if (p) { - free(p); - return w; - } - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) { - if (xwin != NULL) - XFree(xwin); - return 0; - } - - for (i = 0; i < nxwin; i++) { - w = findname(xwin[i]); - if (w != 0) { - XFree(xwin); - return w; - } - } - - XFree(xwin); - - return 0; + int i; + uint nxwin; + XWindow dw1, dw2, *xwin; + char *p; + int s; + Atom net_wm_name; + + p = getproperty(w, XA_WM_NAME); + if(p){ + free(p); + return(w); + } + + net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", FALSE); + p = getproperty(w, net_wm_name); + if(p){ + free(p); + return(w); + } + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XQueryTree(dpy, w, &dw1, &dw2, &xwin, &nxwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + if(s == 0) { + if (xwin != NULL) + XFree(xwin); + return 0; + } + + for (i = 0; i < nxwin; i++) { + w = findname(xwin[i]); + if (w != 0) { + XFree(xwin); + return w; + } + } + XFree(xwin); + + return 0; } -int +int wcmp(const void *w1, const void *w2) { - return *(XWindow *) w1 - *(XWindow *) w2; + return *(XWindow *) w1 - *(XWindow *) w2; } /* unicode-aware case-insensitive strcmp, taken from golang’s gc/subr.c */ -int +int _cistrcmp(char *p, char *q) { - Rune rp, rq; - - while(*p || *q) { - if(*p == 0) - return +1; - if(*q == 0) - return -1; - p += chartorune(&rp, p); - q += chartorune(&rq, q); - rp = tolowerrune(rp); - rq = tolowerrune(rq); - if(rp < rq) - return -1; - if(rp > rq) - return +1; - } - return 0; + Rune rp, rq; + + while(*p || *q) { + if(*p == 0) + return +1; + if(*q == 0) + return -1; + p += chartorune(&rp, p); + q += chartorune(&rq, q); + rp = tolowerrune(rp); + rq = tolowerrune(rq); + if(rp < rq) + return -1; + if(rp > rq) + return +1; + } + return 0; } -int +int winlabelcmp(const void *w1, const void *w2) { - const Win *p1 = (Win *) w1; - const Win *p2 = (Win *) w2; - return _cistrcmp(p1->label, p2->label); + const Win *p1 = (Win *) w1; + const Win *p2 = (Win *) w2; + return _cistrcmp(p1->label, p2->label); } -void +void refreshwin(void) { - XWindow dw1, dw2, *xwin; - XClassHint class; - XWindowAttributes attr; - char *label; - char *wmname; - int i, nw; - uint nxwin; - Status s; - Atom net_wm_name; - - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) { - if (xwin != NULL) - XFree(xwin); - return; - } - qsort(xwin, nxwin, sizeof(xwin[0]), wcmp); - - nw = 0; - for (i = 0; i < nxwin; i++) { - memset(&attr, 0, sizeof attr); - xwin[i] = findname(xwin[i]); - if (xwin[i] == 0) - continue; - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XGetWindowAttributes(dpy, xwin[i], &attr); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) - continue; - if (attr.width <= 0 || attr.override_redirect - || attr.map_state != IsViewable) - continue; - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - s = XGetClassHint(dpy, xwin[i], &class); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - if (s == 0) - continue; - - if (exclude != nil && regexec(exclude, class.res_name, nil, 0)) { - free(class.res_name); - free(class.res_class); - continue; - } - - net_wm_name = XInternAtom (dpy, "_NET_WM_NAME", FALSE); - wmname = getproperty(xwin[i], net_wm_name); - - if (wmname == nil) { - wmname = getproperty(xwin[i], XA_WM_NAME); - if (wmname == nil) { - free(class.res_name); - free(class.res_class); - continue; - } - } - - if (showwmnames == 1) - label = wmname; - else - label = class.res_name; - - if (nw < nwin && win[nw].n == xwin[i] - && strcmp(win[nw].label, label) == 0) { - nw++; - free(wmname); - free(class.res_name); - free(class.res_class); - continue; - } - - if (nw < nwin) { - free(win[nw].label); - win[nw].label = nil; - } - - if (nw >= mwin) { - mwin += 8; - win = erealloc(win, mwin * sizeof(win[0])); - } - win[nw].n = xwin[i]; - win[nw].label = estrdup(label); - win[nw].dirty = 1; - win[nw].r = Rect(0, 0, 0, 0); - free(wmname); - free(class.res_name); - free(class.res_class); - nw++; - } - - oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); - XFree(xwin); - XFlush(dpy); - XSync(dpy, False); - XSetErrorHandler(oldxerrorhandler); - - while (nwin > nw) - free(win[--nwin].label); - nwin = nw; - - if (sortlabels == 1) - qsort(win, nwin, sizeof(struct Win), winlabelcmp); - - return; + XWindow dw1, dw2, *xwin; + XClassHint class; + XWindowAttributes attr; + char *label; + char *wmname; + int i, nw; + uint nxwin; + Status s; + Atom net_wm_name; + + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XQueryTree(dpy, root, &dw1, &dw2, &xwin, &nxwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + if(s==0){ + if(xwin!=NULL) + XFree(xwin); + return; + } + qsort(xwin, nxwin, sizeof(xwin[0]), wcmp); + + nw = 0; + for(i=0; i<nxwin; i++){ + memset(&attr, 0, sizeof attr); + xwin[i] = findname(xwin[i]); + if(xwin[i]==0) + continue; + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XGetWindowAttributes(dpy, xwin[i], &attr); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + if(s==0) + continue; + if (attr.width <= 0 || + attr.override_redirect || + attr.map_state != IsViewable) + continue; + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + s = XGetClassHint(dpy, xwin[i], &class); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + if(s==0) + continue; + + if (exclude!=nil && regexec(exclude, class.res_name, nil, 0)) { + free(class.res_name); + free(class.res_class); + continue; + } + + net_wm_name = XInternAtom(dpy, "_NET_WM_NAME", FALSE); + wmname = getproperty(xwin[i], net_wm_name); + + if(wmname==nil){ + wmname = getproperty(xwin[i], XA_WM_NAME); + if(wmname==nil){ + free(class.res_name); + free(class.res_class); + continue; + } + } + + label = class.res_name; + if(showwmnames==1) + label = wmname; + + if(nw<nwin && win[nw].n==xwin[i] && strcmp(win[nw].label, label)==0) { + nw++; + free(wmname); + free(class.res_name); + free(class.res_class); + continue; + } + + if(nw<nwin){ + free(win[nw].label); + win[nw].label = nil; + } + + if(nw>=mwin){ + mwin += 8; + win = erealloc(win, mwin * sizeof(win[0])); + } + win[nw].n = xwin[i]; + win[nw].label = estrdup(label); + win[nw].dirty = 1; + win[nw].r = Rect(0, 0, 0, 0); + free(wmname); + free(class.res_name); + free(class.res_class); + nw++; + } + + oldxerrorhandler = XSetErrorHandler(winwatchxerrorhandler); + XFree(xwin); + XFlush(dpy); + XSync(dpy, False); + XSetErrorHandler(oldxerrorhandler); + + while(nwin>nw) + free(win[--nwin].label); + nwin = nw; + + if(sortlabels==1) + qsort(win, nwin, sizeof(struct Win), winlabelcmp); } -void +void drawnowin(int i) { - Rectangle r; - - r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, - font->height); - r = rectaddpt(rectaddpt - (r, - Pt(MARGIN + (PAD + Dx(r)) * (i / rows), - MARGIN + (PAD + Dy(r)) * (i % rows))), - screen->r.min); - draw(screen, insetrect(r, -1), lightblue, nil, ZP); + Rectangle r; + + r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, font->height); + r = rectaddpt( + rectaddpt(r, + Pt(MARGIN + (PAD + Dx(r)) * (i / rows), + MARGIN + (PAD + Dy(r)) * (i % rows))), + screen->r.min); + draw(screen, insetrect(r, -1), lightblue, nil, ZP); } -void +void drawwin(int i) { - draw(screen, win[i].r, lightblue, nil, ZP); - _string(screen, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, - font, win[i].label, nil, strlen(win[i].label), - win[i].r, nil, ZP, SoverD); - border(screen, win[i].r, 1, display->black, ZP); - win[i].dirty = 0; + draw(screen, win[i].r, lightblue, nil, ZP); + _string(screen, addpt(win[i].r.min, Pt(2, 0)), display->black, ZP, + font, win[i].label, nil, strlen(win[i].label), + win[i].r, nil, ZP, SoverD); + border(screen, win[i].r, 1, display->black, ZP); + win[i].dirty = 0; } -int +int geometry(void) { - int i, ncols, z; - Rectangle r; - - z = 0; - rows = (Dy(screen->r) - 2 * MARGIN + PAD) / (font->height + PAD); - if (rows * cols < nwin || rows * cols >= nwin * 2) { - ncols = nwin <= 0 ? 1 : (nwin + rows - 1) / rows; - if (ncols != cols) { - cols = ncols; - z = 1; - } - } - - r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, - font->height); - for (i = 0; i < nwin; i++) - win[i].r = - rectaddpt(rectaddpt - (r, - Pt(MARGIN + (PAD + Dx(r)) * (i / rows), - MARGIN + (PAD + Dy(r)) * (i % rows))), - screen->r.min); - - return z; + int i, ncols, z; + Rectangle r; + + z = 0; + rows = (Dy(screen->r) - 2 * MARGIN + PAD) / (font->height + PAD); + if(rows*cols<nwin || rows*cols>=nwin*2){ + ncols = 1; + if(nwin>0) + ncols = (nwin + rows - 1) / rows; + if(ncols!=cols){ + cols = ncols; + z = 1; + } + } + + r = Rect(0, 0, (Dx(screen->r) - 2 * MARGIN + PAD) / cols - PAD, font->height); + for(i=0; i<nwin; i++) + win[i].r = + rectaddpt( + rectaddpt(r, + Pt(MARGIN + (PAD + Dx(r)) * (i / rows), + MARGIN + (PAD + Dy(r)) * (i % rows))), + screen->r.min); + + return z; } -void +void redraw(Image *screen, int all) { - int i; - - all |= geometry(); - if (all) - draw(screen, screen->r, lightblue, nil, ZP); - for (i = 0; i < nwin; i++) - if (all || win[i].dirty) - drawwin(i); - if (!all) - for (; i < onwin; i++) - drawnowin(i); - - onwin = nwin; + int i; + + all |= geometry(); + if(all) + draw(screen, screen->r, lightblue, nil, ZP); + for(i=0; i<nwin; i++) + if(all || win[i].dirty) + drawwin(i); + if(!all) + for (; i<onwin; i++) + drawnowin(i); + onwin = nwin; } -void +void eresized(int new) { - if (new && getwindow(display, Refmesg) < 0) - fprint(2, "can't reattach to window"); - geometry(); - redraw(screen, 1); + if(new && getwindow(display, Refmesg)<0) + fprint(2, "can't reattach to window"); + geometry(); + redraw(screen, 1); } -void +void selectwin(XWindow win) { - XEvent ev; - long mask; - - memset(&ev, 0, sizeof ev); - ev.xclient.type = ClientMessage; - ev.xclient.serial = 0; - ev.xclient.send_event = True; - ev.xclient.message_type = net_active_window; - ev.xclient.window = win; - ev.xclient.format = 32; - mask = SubstructureRedirectMask | SubstructureNotifyMask; - - XSendEvent(dpy, root, False, mask, &ev); - XMapRaised(dpy, win); - XSync(dpy, False); + XEvent ev; + long mask; + + memset(&ev, 0, sizeof ev); + ev.xclient.type = ClientMessage; + ev.xclient.serial = 0; + ev.xclient.send_event = True; + ev.xclient.message_type = net_active_window; + ev.xclient.window = win; + ev.xclient.format = 32; + mask = SubstructureRedirectMask | SubstructureNotifyMask; + + XSendEvent(dpy, root, False, mask, &ev); + XMapRaised(dpy, win); + XSync(dpy, False); } - -void +void click(Mouse m) { - int i, j; - - if (m.buttons == 0 || (m.buttons & ~4)) - return; - - for (i = 0; i < nwin; i++) - if (ptinrect(m.xy, win[i].r)) - break; - if (i == nwin) - return; - - do - m = emouse(); - while (m.buttons == 4); - - if (m.buttons != 0) { - do - m = emouse(); - while (m.buttons); - return; - } - - for (j = 0; j < nwin; j++) - if (ptinrect(m.xy, win[j].r)) - break; - if (j != i) - return; - - selectwin(win[i].n); + int i, j; + + if(m.buttons==0 || (m.buttons&~4)) + return; + + for(i=0; i<nwin; i++) + if(ptinrect(m.xy, win[i].r)) + break; + if(i==nwin) + return; + + do + m = emouse(); + while(m.buttons==4); + + if(m.buttons!=0){ + do + m = emouse(); + while(m.buttons); + return; + } + for(j=0; j<nwin; j++) + if(ptinrect(m.xy, win[j].r)) + break; + if(j==i) + selectwin(win[i].n); } -void +void usage(void) { - fprint(2, - "usage: winwatch [-e exclude] [-W winsize] [-f font] [-n] [-s]\n"); - exits("usage"); + fprint(2, + "usage: winwatch [-e exclude] [-W winsize] [-f font] [-n] [-s]\n"); + exits("usage"); } -void +void main(int argc, char **argv) { - char *fontname; - int Etimer; - Event e; - - sortlabels = 0; - showwmnames = 0; - - fontname = "/lib/font/bit/lucsans/unicode.8.font"; - - ARGBEGIN { - case 'W': - winsize = EARGF(usage()); - break; - case 'f': - fontname = EARGF(usage()); - break; - case 'e': - exclude = regcomp(EARGF(usage())); - if (exclude == nil) - sysfatal("Bad regexp"); - break; - case 's': - sortlabels = 1; - break; - case 'n': - showwmnames = 1; - break; - default: - usage(); - } - ARGEND if (argc) - usage(); - - /* moved up from original winwatch.c for p9p because there can be only one but we want to restart when needed */ - einit(Emouse | Ekeyboard); - Etimer = etimer(0, 1000); - - dpy = XOpenDisplay(""); - - if (dpy == nil) - sysfatal("open display: %r"); - - root = DefaultRootWindow(dpy); - net_active_window = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); - - initdraw(0, 0, "winwatch"); - lightblue = allocimagemix(display, DPalebluegreen, DWhite); - if (lightblue == nil) - sysfatal("allocimagemix: %r"); - if ((font = openfont(display, fontname)) == nil) - sysfatal("font '%s' not found", fontname); - - - /* reentry point upon X server errors */ - setjmp(savebuf); - - refreshwin(); - redraw(screen, 1); - - for (;;) { - switch (eread(Emouse | Ekeyboard | Etimer, &e)) { - case Ekeyboard: - if (e.kbdc == 0x7F || e.kbdc == 'q') - exits(0); - break; - case Emouse: - if (e.mouse.buttons) - click(e.mouse); - /* fall through */ - default: /* Etimer */ - refreshwin(); - redraw(screen, 0); - break; - } - } + char *fontname; + int Etimer; + Event e; + + sortlabels = 0; + showwmnames = 0; + fontname = "/lib/font/bit/lucsans/unicode.8.font"; + + ARGBEGIN { + case 'W': + winsize = EARGF(usage()); + break; + case 'f': + fontname = EARGF(usage()); + break; + case 'e': + exclude = regcomp(EARGF(usage())); + if(exclude==nil) + sysfatal("Bad regexp"); + break; + case 's': + sortlabels = 1; + break; + case 'n': + showwmnames = 1; + break; + default: + usage(); + } ARGEND; + + if(argc) + usage(); + + /* moved up from original winwatch.c for p9p because there can be only one but we want to restart when needed */ + einit(Emouse | Ekeyboard); + Etimer = etimer(0, 1000); + + dpy = XOpenDisplay(""); + if(dpy==nil) + sysfatal("open display: %r"); + + root = DefaultRootWindow(dpy); + net_active_window = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); + + initdraw(0, 0, "winwatch"); + lightblue = allocimagemix(display, DPalebluegreen, DWhite); + if(lightblue==nil) + sysfatal("allocimagemix: %r"); + font = openfont(display, fontname); + if(font==nil) + sysfatal("font '%s' not found", fontname); + + /* reentry point upon X server errors */ + setjmp(savebuf); + + refreshwin(); + redraw(screen, 1); + for(;;){ + switch(eread(Emouse|Ekeyboard|Etimer, &e)){ + case Ekeyboard: + if(e.kbdc==0x7F || e.kbdc=='q') + exits(0); + break; + case Emouse: + if(e.mouse.buttons) + click(e.mouse); + /* fall through */ + default: /* Etimer */ + refreshwin(); + redraw(screen, 0); + break; + } + } } |