19a747e4fSDavid du Colombier #include <u.h>
29a747e4fSDavid du Colombier #include <libc.h>
39a747e4fSDavid du Colombier #include <draw.h>
49a747e4fSDavid du Colombier #include <event.h>
513ec2712SDavid du Colombier #include <regexp.h>
69a747e4fSDavid du Colombier
79a747e4fSDavid du Colombier typedef struct Win Win;
89a747e4fSDavid du Colombier struct Win {
99a747e4fSDavid du Colombier int n;
109a747e4fSDavid du Colombier int dirty;
119a747e4fSDavid du Colombier char *label;
129a747e4fSDavid du Colombier Rectangle r;
139a747e4fSDavid du Colombier };
149a747e4fSDavid du Colombier
1513ec2712SDavid du Colombier
1613ec2712SDavid du Colombier
1713ec2712SDavid du Colombier Reprog *exclude = nil;
189a747e4fSDavid du Colombier Win *win;
199a747e4fSDavid du Colombier int nwin;
209a747e4fSDavid du Colombier int mwin;
219a747e4fSDavid du Colombier int onwin;
229a747e4fSDavid du Colombier int rows, cols;
239a747e4fSDavid du Colombier Font *font;
249a747e4fSDavid du Colombier Image *lightblue;
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier enum {
279a747e4fSDavid du Colombier PAD = 3,
289a747e4fSDavid du Colombier MARGIN = 5
299a747e4fSDavid du Colombier };
309a747e4fSDavid du Colombier
319a747e4fSDavid du Colombier void*
erealloc(void * v,ulong n)329a747e4fSDavid du Colombier erealloc(void *v, ulong n)
339a747e4fSDavid du Colombier {
349a747e4fSDavid du Colombier v = realloc(v, n);
359a747e4fSDavid du Colombier if(v == nil)
369a747e4fSDavid du Colombier sysfatal("out of memory reallocating %lud", n);
379a747e4fSDavid du Colombier return v;
389a747e4fSDavid du Colombier }
399a747e4fSDavid du Colombier
409a747e4fSDavid du Colombier void*
emalloc(ulong n)419a747e4fSDavid du Colombier emalloc(ulong n)
429a747e4fSDavid du Colombier {
439a747e4fSDavid du Colombier void *v;
449a747e4fSDavid du Colombier
459a747e4fSDavid du Colombier v = malloc(n);
469a747e4fSDavid du Colombier if(v == nil)
479a747e4fSDavid du Colombier sysfatal("out of memory allocating %lud", n);
489a747e4fSDavid du Colombier memset(v, 0, n);
499a747e4fSDavid du Colombier return v;
509a747e4fSDavid du Colombier }
519a747e4fSDavid du Colombier
529a747e4fSDavid du Colombier char*
estrdup(char * s)539a747e4fSDavid du Colombier estrdup(char *s)
549a747e4fSDavid du Colombier {
559a747e4fSDavid du Colombier int l;
569a747e4fSDavid du Colombier char *t;
579a747e4fSDavid du Colombier
589a747e4fSDavid du Colombier if (s == nil)
599a747e4fSDavid du Colombier return nil;
609a747e4fSDavid du Colombier l = strlen(s)+1;
619a747e4fSDavid du Colombier t = emalloc(l);
629a747e4fSDavid du Colombier memcpy(t, s, l);
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier return t;
659a747e4fSDavid du Colombier }
669a747e4fSDavid du Colombier
6713ec2712SDavid du Colombier
689a747e4fSDavid du Colombier void
refreshwin(void)699a747e4fSDavid du Colombier refreshwin(void)
709a747e4fSDavid du Colombier {
719a747e4fSDavid du Colombier char label[128];
729a747e4fSDavid du Colombier int i, fd, lfd, n, nr, nw, m;
739a747e4fSDavid du Colombier Dir *pd;
749a747e4fSDavid du Colombier
759a747e4fSDavid du Colombier if((fd = open("/dev/wsys", OREAD)) < 0)
769a747e4fSDavid du Colombier return;
779a747e4fSDavid du Colombier
789a747e4fSDavid du Colombier nw = 0;
799a747e4fSDavid du Colombier /* i'd rather read one at a time but rio won't let me */
809a747e4fSDavid du Colombier while((nr=dirread(fd, &pd)) > 0){
819a747e4fSDavid du Colombier for(i=0; i<nr; i++){
829a747e4fSDavid du Colombier n = atoi(pd[i].name);
839a747e4fSDavid du Colombier sprint(label, "/dev/wsys/%d/label", n);
849a747e4fSDavid du Colombier if((lfd = open(label, OREAD)) < 0)
859a747e4fSDavid du Colombier continue;
869a747e4fSDavid du Colombier m = read(lfd, label, sizeof(label)-1);
879a747e4fSDavid du Colombier close(lfd);
889a747e4fSDavid du Colombier if(m < 0)
899a747e4fSDavid du Colombier continue;
909a747e4fSDavid du Colombier label[m] = '\0';
9113ec2712SDavid du Colombier if(exclude != nil && regexec(exclude,label,nil,0))
9213ec2712SDavid du Colombier continue;
9313ec2712SDavid du Colombier
949a747e4fSDavid du Colombier if(nw < nwin && win[nw].n == n && strcmp(win[nw].label, label)==0){
959a747e4fSDavid du Colombier nw++;
969a747e4fSDavid du Colombier continue;
979a747e4fSDavid du Colombier }
989a747e4fSDavid du Colombier
999a747e4fSDavid du Colombier if(nw < nwin){
1009a747e4fSDavid du Colombier free(win[nw].label);
1019a747e4fSDavid du Colombier win[nw].label = nil;
1029a747e4fSDavid du Colombier }
10313ec2712SDavid du Colombier
1049a747e4fSDavid du Colombier if(nw >= mwin){
1059a747e4fSDavid du Colombier mwin += 8;
1069a747e4fSDavid du Colombier win = erealloc(win, mwin*sizeof(win[0]));
1079a747e4fSDavid du Colombier }
1089a747e4fSDavid du Colombier win[nw].n = n;
1099a747e4fSDavid du Colombier win[nw].label = estrdup(label);
1109a747e4fSDavid du Colombier win[nw].dirty = 1;
1119a747e4fSDavid du Colombier win[nw].r = Rect(0,0,0,0);
1129a747e4fSDavid du Colombier nw++;
1139a747e4fSDavid du Colombier }
1149a747e4fSDavid du Colombier free(pd);
1159a747e4fSDavid du Colombier }
1169a747e4fSDavid du Colombier while(nwin > nw)
1179a747e4fSDavid du Colombier free(win[--nwin].label);
1189a747e4fSDavid du Colombier nwin = nw;
1199a747e4fSDavid du Colombier close(fd);
1209a747e4fSDavid du Colombier }
1219a747e4fSDavid du Colombier
1229a747e4fSDavid du Colombier void
drawnowin(int i)1239a747e4fSDavid du Colombier drawnowin(int i)
1249a747e4fSDavid du Colombier {
1259a747e4fSDavid du Colombier Rectangle r;
1269a747e4fSDavid du Colombier
1279a747e4fSDavid du Colombier r = Rect(0,0,(Dx(screen->r)-2*MARGIN+PAD)/cols-PAD, font->height);
1289a747e4fSDavid du Colombier r = rectaddpt(rectaddpt(r, Pt(MARGIN+(PAD+Dx(r))*(i/rows),
1299a747e4fSDavid du Colombier MARGIN+(PAD+Dy(r))*(i%rows))), screen->r.min);
1309a747e4fSDavid du Colombier draw(screen, insetrect(r, -1), lightblue, nil, ZP);
1319a747e4fSDavid du Colombier }
1329a747e4fSDavid du Colombier
1339a747e4fSDavid du Colombier void
drawwin(int i)1349a747e4fSDavid du Colombier drawwin(int i)
1359a747e4fSDavid du Colombier {
1369a747e4fSDavid du Colombier draw(screen, win[i].r, lightblue, nil, ZP);
1379a747e4fSDavid du Colombier _string(screen, addpt(win[i].r.min, Pt(2,0)), display->black, ZP,
1389a747e4fSDavid du Colombier font, win[i].label, nil, strlen(win[i].label),
139ac57dd0bSDavid du Colombier win[i].r, nil, ZP, SoverD);
1409a747e4fSDavid du Colombier border(screen, win[i].r, 1, display->black, ZP);
1419a747e4fSDavid du Colombier win[i].dirty = 0;
1429a747e4fSDavid du Colombier }
1439a747e4fSDavid du Colombier
1449a747e4fSDavid du Colombier int
geometry(void)1459a747e4fSDavid du Colombier geometry(void)
1469a747e4fSDavid du Colombier {
1479a747e4fSDavid du Colombier int i, ncols, z;
1489a747e4fSDavid du Colombier Rectangle r;
1499a747e4fSDavid du Colombier
1509a747e4fSDavid du Colombier z = 0;
1519a747e4fSDavid du Colombier rows = (Dy(screen->r)-2*MARGIN+PAD)/(font->height+PAD);
1529a747e4fSDavid du Colombier if(rows*cols < nwin || rows*cols >= nwin*2){
1539552e201SDavid du Colombier ncols = nwin <= 0 ? 1 : (nwin+rows-1)/rows;
1549a747e4fSDavid du Colombier if(ncols != cols){
1559a747e4fSDavid du Colombier cols = ncols;
1569a747e4fSDavid du Colombier z = 1;
1579a747e4fSDavid du Colombier }
1589a747e4fSDavid du Colombier }
1599a747e4fSDavid du Colombier
1609a747e4fSDavid du Colombier r = Rect(0,0,(Dx(screen->r)-2*MARGIN+PAD)/cols-PAD, font->height);
1619a747e4fSDavid du Colombier for(i=0; i<nwin; i++)
1629a747e4fSDavid du Colombier win[i].r = rectaddpt(rectaddpt(r, Pt(MARGIN+(PAD+Dx(r))*(i/rows),
1639a747e4fSDavid du Colombier MARGIN+(PAD+Dy(r))*(i%rows))), screen->r.min);
1649a747e4fSDavid du Colombier
1659a747e4fSDavid du Colombier return z;
1669a747e4fSDavid du Colombier }
1679a747e4fSDavid du Colombier
1689a747e4fSDavid du Colombier void
redraw(Image * screen,int all)1699a747e4fSDavid du Colombier redraw(Image *screen, int all)
1709a747e4fSDavid du Colombier {
1719a747e4fSDavid du Colombier int i;
1729a747e4fSDavid du Colombier
1739a747e4fSDavid du Colombier all |= geometry();
1749a747e4fSDavid du Colombier if(all)
1759a747e4fSDavid du Colombier draw(screen, screen->r, lightblue, nil, ZP);
1769a747e4fSDavid du Colombier for(i=0; i<nwin; i++)
1779a747e4fSDavid du Colombier if(all || win[i].dirty)
1789a747e4fSDavid du Colombier drawwin(i);
1799a747e4fSDavid du Colombier if(!all)
1809a747e4fSDavid du Colombier for(; i<onwin; i++)
1819a747e4fSDavid du Colombier drawnowin(i);
1829a747e4fSDavid du Colombier
1839a747e4fSDavid du Colombier onwin = nwin;
1849a747e4fSDavid du Colombier }
1859a747e4fSDavid du Colombier
1869a747e4fSDavid du Colombier void
eresized(int new)1879a747e4fSDavid du Colombier eresized(int new)
1889a747e4fSDavid du Colombier {
1899a747e4fSDavid du Colombier if(new && getwindow(display, Refmesg) < 0)
1909a747e4fSDavid du Colombier fprint(2,"can't reattach to window");
1919a747e4fSDavid du Colombier geometry();
1929a747e4fSDavid du Colombier redraw(screen, 1);
1939a747e4fSDavid du Colombier }
1949a747e4fSDavid du Colombier
1959a747e4fSDavid du Colombier void
click(Mouse m)1969a747e4fSDavid du Colombier click(Mouse m)
1979a747e4fSDavid du Colombier {
1989a747e4fSDavid du Colombier int fd, i, j;
1999a747e4fSDavid du Colombier char buf[128];
2009a747e4fSDavid du Colombier
2019a747e4fSDavid du Colombier if(m.buttons == 0 || (m.buttons & ~4))
2029a747e4fSDavid du Colombier return;
2039a747e4fSDavid du Colombier
2049a747e4fSDavid du Colombier for(i=0; i<nwin; i++)
2059a747e4fSDavid du Colombier if(ptinrect(m.xy, win[i].r))
2069a747e4fSDavid du Colombier break;
2079a747e4fSDavid du Colombier if(i == nwin)
2089a747e4fSDavid du Colombier return;
2099a747e4fSDavid du Colombier
2109a747e4fSDavid du Colombier do
2119a747e4fSDavid du Colombier m = emouse();
2129a747e4fSDavid du Colombier while(m.buttons == 4);
2139a747e4fSDavid du Colombier
2149a747e4fSDavid du Colombier if(m.buttons != 0){
2159a747e4fSDavid du Colombier do
2169a747e4fSDavid du Colombier m = emouse();
2179a747e4fSDavid du Colombier while(m.buttons);
2189a747e4fSDavid du Colombier return;
2199a747e4fSDavid du Colombier }
2209a747e4fSDavid du Colombier
2219a747e4fSDavid du Colombier for(j=0; j<nwin; j++)
2229a747e4fSDavid du Colombier if(ptinrect(m.xy, win[j].r))
2239a747e4fSDavid du Colombier break;
2249a747e4fSDavid du Colombier if(j != i)
2259a747e4fSDavid du Colombier return;
2269a747e4fSDavid du Colombier
2279a747e4fSDavid du Colombier sprint(buf, "/dev/wsys/%d/wctl", win[i].n);
2289a747e4fSDavid du Colombier if((fd = open(buf, OWRITE)) < 0)
2299a747e4fSDavid du Colombier return;
230ac57dd0bSDavid du Colombier write(fd, "unhide\n", 7);
2319a747e4fSDavid du Colombier write(fd, "top\n", 4);
2329a747e4fSDavid du Colombier write(fd, "current\n", 8);
2339a747e4fSDavid du Colombier close(fd);
2349a747e4fSDavid du Colombier }
2359a747e4fSDavid du Colombier
2369a747e4fSDavid du Colombier void
usage(void)2379a747e4fSDavid du Colombier usage(void)
2389a747e4fSDavid du Colombier {
23913ec2712SDavid du Colombier fprint(2, "usage: winwatch [-e exclude] [-f font]\n");
2409a747e4fSDavid du Colombier exits("usage");
2419a747e4fSDavid du Colombier }
2429a747e4fSDavid du Colombier
2439a747e4fSDavid du Colombier void
main(int argc,char ** argv)2449a747e4fSDavid du Colombier main(int argc, char **argv)
2459a747e4fSDavid du Colombier {
2469a747e4fSDavid du Colombier char *fontname;
2479a747e4fSDavid du Colombier int Etimer;
2489a747e4fSDavid du Colombier Event e;
2499a747e4fSDavid du Colombier
2509a747e4fSDavid du Colombier fontname = "/lib/font/bit/lucidasans/unicode.8.font";
2519a747e4fSDavid du Colombier ARGBEGIN{
2529a747e4fSDavid du Colombier case 'f':
2539a747e4fSDavid du Colombier fontname = EARGF(usage());
2549a747e4fSDavid du Colombier break;
25513ec2712SDavid du Colombier case 'e':
25613ec2712SDavid du Colombier exclude = regcomp(EARGF(usage()));
25713ec2712SDavid du Colombier if(exclude == nil)
25813ec2712SDavid du Colombier sysfatal("Bad regexp");
25913ec2712SDavid du Colombier break;
260a22b0629SDavid du Colombier default:
261a22b0629SDavid du Colombier usage();
2629a747e4fSDavid du Colombier }ARGEND
2639a747e4fSDavid du Colombier
2649a747e4fSDavid du Colombier if(argc)
2659a747e4fSDavid du Colombier usage();
2669a747e4fSDavid du Colombier
2679a747e4fSDavid du Colombier initdraw(0, 0, "winwatch");
2689a747e4fSDavid du Colombier lightblue = allocimagemix(display, DPalebluegreen, DWhite);
2699a747e4fSDavid du Colombier if(lightblue == nil)
2709a747e4fSDavid du Colombier sysfatal("allocimagemix: %r");
2719a747e4fSDavid du Colombier if((font = openfont(display, fontname)) == nil)
2729a747e4fSDavid du Colombier sysfatal("font '%s' not found", fontname);
2739a747e4fSDavid du Colombier
2749a747e4fSDavid du Colombier refreshwin();
2759a747e4fSDavid du Colombier redraw(screen, 1);
2769a747e4fSDavid du Colombier einit(Emouse|Ekeyboard);
277*f30ccc91SDavid du Colombier Etimer = etimer(0, 2500);
2789a747e4fSDavid du Colombier
2799a747e4fSDavid du Colombier for(;;){
2809a747e4fSDavid du Colombier switch(eread(Emouse|Ekeyboard|Etimer, &e)){
2819a747e4fSDavid du Colombier case Ekeyboard:
2829a747e4fSDavid du Colombier if(e.kbdc==0x7F || e.kbdc=='q')
2839a747e4fSDavid du Colombier exits(0);
2849a747e4fSDavid du Colombier break;
2859a747e4fSDavid du Colombier case Emouse:
2869a747e4fSDavid du Colombier if(e.mouse.buttons)
2879a747e4fSDavid du Colombier click(e.mouse);
288*f30ccc91SDavid du Colombier /* fall through */
2899a747e4fSDavid du Colombier default: /* Etimer */
2909a747e4fSDavid du Colombier refreshwin();
2919a747e4fSDavid du Colombier redraw(screen, 0);
2929a747e4fSDavid du Colombier break;
2939a747e4fSDavid du Colombier }
2949a747e4fSDavid du Colombier }
2959a747e4fSDavid du Colombier }
296