123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295 |
- #include <u.h>
- #include <libc.h>
- #include <draw.h>
- #include <event.h>
- #include <regexp.h>
- typedef struct Win Win;
- struct Win {
- int n;
- int dirty;
- char *label;
- Rectangle r;
- };
- Reprog *exclude = nil;
- Win *win;
- int nwin;
- int mwin;
- int onwin;
- int rows, cols;
- Font *font;
- Image *lightblue;
- enum {
- PAD = 3,
- MARGIN = 5
- };
- void*
- erealloc(void *v, ulong n)
- {
- v = realloc(v, n);
- if(v == nil)
- sysfatal("out of memory reallocating %lud", n);
- return v;
- }
- void*
- emalloc(ulong n)
- {
- void *v;
- v = malloc(n);
- if(v == nil)
- sysfatal("out of memory allocating %lud", n);
- memset(v, 0, n);
- return v;
- }
- char*
- estrdup(char *s)
- {
- int l;
- char *t;
- if (s == nil)
- return nil;
- l = strlen(s)+1;
- t = emalloc(l);
- memcpy(t, s, l);
- return t;
- }
- void
- refreshwin(void)
- {
- char label[128];
- int i, fd, lfd, n, nr, nw, m;
- Dir *pd;
- if((fd = open("/dev/wsys", OREAD)) < 0)
- return;
- nw = 0;
- /* i'd rather read one at a time but rio won't let me */
- while((nr=dirread(fd, &pd)) > 0){
- for(i=0; i<nr; i++){
- n = atoi(pd[i].name);
- sprint(label, "/dev/wsys/%d/label", n);
- if((lfd = open(label, OREAD)) < 0)
- continue;
- m = read(lfd, label, sizeof(label)-1);
- close(lfd);
- if(m < 0)
- continue;
- label[m] = '\0';
- if(exclude != nil && regexec(exclude,label,nil,0))
- continue;
- if(nw < nwin && win[nw].n == n && strcmp(win[nw].label, label)==0){
- nw++;
- 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 = n;
- win[nw].label = estrdup(label);
- win[nw].dirty = 1;
- win[nw].r = Rect(0,0,0,0);
- nw++;
- }
- free(pd);
- }
- while(nwin > nw)
- free(win[--nwin].label);
- nwin = nw;
- close(fd);
- }
- 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);
- }
- 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;
- }
- 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;
- }
- 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;
- }
- void
- eresized(int new)
- {
- if(new && getwindow(display, Refmesg) < 0)
- fprint(2,"can't reattach to window");
- geometry();
- redraw(screen, 1);
- }
- void
- click(Mouse m)
- {
- int fd, i, j;
- char buf[128];
- 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;
- sprint(buf, "/dev/wsys/%d/wctl", win[i].n);
- if((fd = open(buf, OWRITE)) < 0)
- return;
- write(fd, "unhide\n", 7);
- write(fd, "top\n", 4);
- write(fd, "current\n", 8);
- close(fd);
- }
- void
- usage(void)
- {
- fprint(2, "usage: winwatch [-e exclude] [-f font]\n");
- exits("usage");
- }
- void
- main(int argc, char **argv)
- {
- char *fontname;
- int Etimer;
- Event e;
- fontname = "/lib/font/bit/lucidasans/unicode.8.font";
- ARGBEGIN{
- case 'f':
- fontname = EARGF(usage());
- break;
- case 'e':
- exclude = regcomp(EARGF(usage()));
- if(exclude == nil)
- sysfatal("Bad regexp");
- break;
- default:
- usage();
- }ARGEND
- if(argc)
- usage();
- 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);
- refreshwin();
- redraw(screen, 1);
- einit(Emouse|Ekeyboard);
- Etimer = etimer(0, 5000);
- 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);
- break;
- default: /* Etimer */
- refreshwin();
- redraw(screen, 0);
- break;
- }
- }
- }
|