ref: 5756ecf17937f697444fe02f6b13a205a78a975c
dir: /theme.c/
#include <u.h> #include <libc.h> #include <plumb.h> #include <draw.h> #include <bio.h> #include <thread.h> #include "theme.h" ThemeColor colors[Numcolors] = { [Dback] = {"background", 0x000000}, [Dfhigh] = {"f_high", 0xffffff}, [Dfmed] = {"f_med", 0x777777}, [Dflow] = {"f_low", 0x444444}, [Dfinv] = {"f_inv", 0x000000}, [Dbhigh] = {"b_high", 0xdddddd}, [Dbmed] = {"b_med", 0x72dec2}, [Dblow] = {"b_low", 0x222222}, [Dbinv] = {"b_inv", 0xffb545}, }; void themechanged(void); static char *themeplumb; static void runpicker(void *x) { int *p, f; char tmp[32]; snprint(tmp, sizeof(tmp), "-pid %d -dx %d -dy %d", getpid(), 384, 320); newwindow(tmp); p = x; dup(*p, 0); dup(*p, 1); close(*p); close(p[1]); close(p[2]); dup(f = open("/dev/null", OWRITE), 2); close(f); execl("/bin/picker", "picker", nil); threadexits("exec: %r"); } static void themeproc(void *audio) { Biobuf *b; char *s, *v[3]; int p[3], n, i; static int pid; threadsetname("themeproc"); pipe(p); p[2] = *(int*)audio; postnote(PNGROUP, pid, "interrupt"); pid = threadpid(procrfork(runpicker, p, 4096, RFFDG|RFNAMEG|RFNOTEG)); close(p[0]); b = Bfdopen(p[1], OREAD); for(i = 0; i < nelem(colors); i++) fprint(p[1], "%s\t%06ux\n", colors[i].id, colors[i].rgb); for(;;){ if((s = Brdstr(b, '\n', 1)) == nil) break; if((n = tokenize(s, v, nelem(v))) >= 2){ for(i = 0; i < nelem(colors); i++){ if(strcmp(colors[i].id, v[0]) == 0){ if(display->locking) lockdisplay(display); freeimage(colors[i].im); colors[i].rgb = strtoul(v[1], nil, 16); colors[i].im = allocimage(display, Rect(0,0,1,1), RGB24, 1, colors[i].rgb<<8 | 0xff); if(display->locking) unlockdisplay(display); themechanged(); break; } } } free(s); if(n != 2) break; } Bterm(b); postnote(PNGROUP, pid, "interrupt"); threadexits(nil); } static int loadtheme(char *filename, int init) { Biobuf *in; char *s, *v[3]; int i, n; if ((in = Bopen(filename, OREAD)) != nil) { if(display->locking && !init) lockdisplay(display); for(;;){ if((s = Brdstr(in, '\n', 1)) == nil) break; if((n = tokenize(s, v, nelem(v))) == 2){ for(i = 0; i < nelem(colors); i++){ if(strcmp(colors[i].id, v[0]) == 0){ freeimage(colors[i].im); colors[i].rgb = strtoul(v[1], nil, 16); colors[i].im = allocimage(display, Rect(0,0,1,1), RGB24, 1, colors[i].rgb<<8 | 0xff); break; } } } free(s); if(n != 2) break; } if(display->locking && !init) unlockdisplay(display); Bterm(in); if(!init) themechanged(); return 0; } return -1; } static void plumbproc(void *) { int f; Plumbmsg *m; threadsetname("theme/plumb"); if ((f = plumbopen(themeplumb, OREAD)) >= 0) { while ((m = plumbrecv(f)) != nil) { loadtheme(m->data, 0); themechanged(); plumbfree(m); } } threadexits(nil); } void themeinit(void) { char *s; int i; if((s = getenv("theme")) != nil){ if(loadtheme(s, 1) != 0) sysfatal("theme load failed: %r"); free(s); } for(i = 0; i < Numcolors; i++){ if(colors[i].im == nil) colors[i].im = allocimage(display, Rect(0,0,1,1), RGB24, 1, colors[i].rgb<<8 | 0xff); } if((themeplumb = getenv("themeplumb")) != nil) proccreate(plumbproc, nil, 4096); }