shithub: bar

ref: 28ee794ab5542ed1498fa40bc5219b1dd6518607
dir: /bar.c/

View raw version
#include "theme.c"
#include "nanosec.c"
#include <keyboard.h>
#include <mouse.h>

#define MAX(a,b) ((a)>=(b)?(a):(b))
#define MIN(a,b) ((a)<=(b)?(a):(b))
#define CLAMP(x,min,max) MAX(min, MIN(max, x))

enum {
	Off = 4,
};

static Font *f;
static struct {
	int w, h;
}scr;

static char *wday[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
static char *pos = "rb";
static int wctl, width, bottom, bat;

static void
place(void)
{
	static int ow, oh;
	char t[61], *a[5];
	int f, n, w, h, minx, miny, maxx, maxy;

	if((f = open("/dev/screen", OREAD)) < 0)
		return;
	n = read(f, t, sizeof(t)-1);
	close(f);
	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 = 48;
		}else{
			miny = h-48;
			maxy = h;
		}
		if(pos[0] == 'l' || pos[1] == 'l'){
			minx = 0;
			maxx = 4+width+4;
		}else{
			minx = w-4-width-4;
			maxx = w;
		}
		fprint(wctl, "resize -r %d %d %d %d", minx, miny, maxx, maxy);
		ow = w;
		oh = h;
	}
}

static void
redraw(void)
{
	Tm *tm;
	char bats[16], s[128], *t;
	Point p;
	Rectangle r;

	lockdisplay(display);
	r = screen->r;

	draw(screen, r, colors[Dback].im, nil, ZP);

	if(bat < 0 || pread(bat, bats, 4, 0) < 4)
		bats[0] = 0;
	else{
		t = strchr(bats, ' ');
		strcpy(t, "% | ");
	}
	tm = localtime(time(nil));
	snprint(
		s, sizeof(s),
		"%s%04d/%02d/%02d %s %02d:%02d:%02d",
		bats,
		tm->year+1900, tm->mon+1, tm->mday,
		wday[tm->wday],
		tm->hour, tm->min, tm->sec
	);
	width = Off + stringwidth(f, s) + Off;
	p.x = r.max.x - width + Off;
	p.y = (pos[0] == 't' || pos[1] == 't') ? r.max.y - (f->height + Off) : r.min.y + Off;
	string(screen, p, colors[Dfhigh].im, ZP, f, s);

	flushimage(display, 1);
	unlockdisplay(display);

	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);
}

void
themechanged(void)
{
	redraw();
}

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;
	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

	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;

	nanosec();
	themeinit();
	redraw();

	proccreate(updateproc, nil, 4096);

	for(;;){
		redraw();

		switch(alt(a)){
		case 0:
			break;

		case 1:
			if(getwindow(display, Refnone) < 0)
				sysfatal("getwindow: %r");
			break;

		case 2:
			if(key == Kdel){
				close(wctl);
				wctl = -1;
				threadexitsall(nil);
			}
			break;
		}
	}
}