ref: f637e7de9dc3c1bb8e90590ab2956fe9d86a2d02
dir: /bar.c/
#include <u.h> #include <libc.h> #include <bio.h> #include <draw.h> #include <keyboard.h> #include <mouse.h> #include <thread.h> #include <tos.h> #define MAX(a,b) ((a)>=(b)?(a):(b)) enum { Off = 4, }; static int wctl, width, bottom, bat; static Image *cback, *ctext; static char *pos = "rb"; static Tzone *local; static Font *f; /* * nsec() is wallclock and can be adjusted by timesync * so need to use cycles() instead, but fall back to * nsec() in case we can't */ static uvlong nanosec(void) { static uvlong fasthz, xstart; uvlong x, div; if(fasthz == ~0ULL) return nsec() - xstart; if(fasthz == 0){ if((fasthz = _tos->cyclefreq) == 0){ fasthz = ~0ULL; xstart = nsec(); return 0; }else{ cycles(&xstart); } } cycles(&x); x -= xstart; /* this is ugly */ for(div = 1000000000ULL; x < 0x1999999999999999ULL && div > 1 ; div /= 10ULL, x *= 10ULL); return x / (fasthz / div); } static void place(void) { int fd, n, w, h, minx, miny, maxx, maxy; char t[61], *a[5]; static int ow, oh; if((fd = open("/dev/screen", OREAD)) < 0) return; n = read(fd, t, sizeof(t)-1); close(fd); t[sizeof(t)-1] = 0; if(n != sizeof(t)-1 || tokenize(t, a, 5) != 5) return; w = atoi(a[3]); h = atoi(a[4]); if(ow != w || oh != h){ if(pos[0] == 't' || pos[1] == 't'){ miny = 0; maxy = Borderwidth+3*f->height+Borderwidth; }else{ miny = h - (Borderwidth+3*f->height+Borderwidth); maxy = h; } if(pos[0] == 'l' || pos[1] == 'l'){ minx = 0; maxx = MAX(100, Borderwidth+Off+width+Off+Borderwidth); }else{ minx = MAX(100, w-(Borderwidth+Off+width+Off+Borderwidth)); maxx = w; } snprint(t, sizeof(t), "resize -r %d %d %d %d", minx, miny, maxx, maxy); if(fprint(wctl, "%s", t) < 0) fprint(2, "%s: %r\n", t); ow = w; oh = h; } } static void redraw(void) { char bats[16], s[128], *t, tmp[16]; Rectangle r; Tmfmt tf; Point p; Tm tm; lockdisplay(display); r = screen->r; draw(screen, r, cback, nil, ZP); t = bat < 0 || pread(bat, tmp, 4, 0) < 4 ? nil : strchr(tmp, ' '); if(t != nil){ *t = 0; snprint(bats, sizeof(bats), pos[0] == 'l' || pos[1] == 'l' ? " │ %s%%" : "%s%% │ ", tmp); }else{ bats[0] = 0; } tf = tmfmt(tmnow(&tm, local), "YYYY/MM/DD WW hh:mm:ss"); if(pos[0] == 'l' || pos[1] == 'l'){ snprint(s, sizeof(s), "%τ%s", tf, bats); p.x = r.min.x + Off; }else{ snprint(s, sizeof(s), "%s%τ", bats, tf); p.x = r.max.x - (stringwidth(f, s) + Off); } p.y = (pos[0] == 't' || pos[1] == 't') ? r.max.y - (f->height + Off) : r.min.y + Off; string(screen, p, ctext, ZP, f, s); flushimage(display, 1); unlockdisplay(display); snprint(s, sizeof(s), "%s%τ", bats[0] ? "100% │ " : "", tf); width = stringwidth(f, s); place(); } static void updateproc(void *) { uvlong t, n; t = nanosec(); for(;;){ sleep(250); if(wctl < 0) break; fprint(wctl, bottom ? "bottom" : "top"); if((n = nanosec()) - t >= 1000000000ULL){ redraw(); t = n; } } threadexits(nil); } static void usage(void) { fprint(2, "usage: %s [-b] [-p lt|rt|lb|rb]\n", argv0); threadexitsall("usage"); } void threadmain(int argc, char **argv) { Keyboardctl *kctl; Mousectl *mctl; char *s, *v[3]; u32int brgb; Biobuf *b; Rune key; Mouse m; Alt a[] = { { nil, &m, CHANRCV }, { nil, nil, CHANRCV }, { nil, &key, CHANRCV }, { nil, nil, CHANEND }, }; ARGBEGIN{ case 'p': pos = EARGF(usage()); break; case 'b': bottom = 1; break; default: usage(); }ARGEND tmfmtinstall(); if((local = tzload("local")) == nil) sysfatal("zone: %r"); if((wctl = open("/dev/wctl", ORDWR)) < 0) sysfatal("%r"); bat = open("/mnt/acpi/battery", OREAD); if(initdraw(nil, nil, "bar") < 0) sysfatal("initdraw: %r"); f = display->defaultfont; unlockdisplay(display); if((mctl = initmouse(nil, screen)) == nil) sysfatal("initmouse: %r"); if((kctl = initkeyboard(nil)) == nil) sysfatal("initkeyboard: %r"); a[0].c = mctl->c; a[1].c = mctl->resizec; a[2].c = kctl->c; brgb = DPalegreygreen; if((b = Bopen("/dev/theme", OREAD)) != nil){ while((s = Brdline(b, '\n')) != nil){ s[Blinelen(b)-1] = 0; if(tokenize(s, v, nelem(v)) > 1 && strcmp(v[0], "ltitle") == 0){ brgb = strtoul(v[1], nil, 16)<<8 | 0xff; break; } } Bterm(b); } cback = allocimage(display, Rect(0,0,1,1), RGB24, 1, brgb); brgb = ~(brgb>>8 | brgb>>16 | brgb>>24); brgb = brgb<<8 | brgb<<16 | brgb<<24 | 0xff; ctext = allocimage(display, Rect(0,0,1,1), RGB24, 1, brgb); redraw(); proccreate(updateproc, nil, 4096); for(;;){ switch(alt(a)){ case 0: break; case 1: if(getwindow(display, Refnone) < 0) sysfatal("getwindow: %r"); redraw(); break; case 2: if(key == Kdel){ close(wctl); wctl = -1; threadexitsall(nil); } break; } } }