#include #include #include #include #include #include #include #include "dat.h" #include "fns.h" Mousectl *mctl; ulong kdown; double Δt; Image *screenb; Memimage *fb; Memimage *bg, *fg; Rune keys[Ke] = { [K↑] Kup, [K↓] Kdown, [K←] Kleft, [K→] Kright }; Memimage* eallocmemimage(Rectangle r, ulong chan) { Memimage *i; i = allocmemimage(r, chan); if(i == nil) sysfatal("allocmemimage: %r"); memfillcolor(i, DTransparent); return i; } Memimage* rgb(ulong c) { Memimage *i; i = eallocmemimage(Rect(0,0,1,1), screen->chan); i->flags |= Frepl; i->clipr = Rect(-1e6, -1e6, 1e6, 1e6); memfillcolor(i, c); return i; } void kbdproc(void*) { Rune r, *a; char buf[128], *s; int fd, n; threadsetname("kbdproc"); if((fd = open("/dev/kbd", OREAD)) < 0) sysfatal("kbdproc: %r"); memset(buf, 0, sizeof buf); for(;;){ if(buf[0] != 0){ n = strlen(buf)+1; memmove(buf, buf+n, sizeof(buf)-n); } if(buf[0] == 0){ if((n = read(fd, buf, sizeof(buf)-1)) <= 0) break; buf[n-1] = 0; buf[n] = 0; } if(buf[0] == 'c'){ if(utfrune(buf, Kdel)){ close(fd); threadexitsall(nil); } } if(buf[0] != 'k' && buf[0] != 'K') continue; s = buf+1; kdown = 0; while(*s){ s += chartorune(&r, s); for(a = keys; a < keys+Ke; a++) if(r == *a){ kdown |= 1 << a-keys; break; } } } } void drawproc(void *arg) { Channel *c; c = arg; for(;;){ send(c, nil); sleep(FPS2MS(60)); } } void resetfb(void) { freeimage(screenb); screenb = allocimage(display, Rect(0,0,Dx(screen->r),Dy(screen->r)), screen->chan, 0, DNofill); freememimage(fb); fb = eallocmemimage(Rect(0,0,Dx(screen->r),Dy(screen->r)), screen->chan); } void redraw(void) { Rectangle r; Point p; static Point incp = {1,1}; memimagedraw(fb, fb->r, bg, ZP, nil, ZP, SoverD); for(p.y = 0; p.y < Dy(fb->r); p.y++) for(p.x = 0; p.x < Dx(fb->r); p.x++) if(p.x%15 == 0 || p.y%15 == 0) memimagedraw(fb, Rpt(p, addpt(p, incp)), fg, ZP, nil, ZP, SoverD); /*for(p = ZP; ptinrect(p, fb->r); p.x++, p.y++) memimagedraw(fb, Rpt(p, addpt(p, Pt(1,1))), fg, ZP, nil, ZP, SoverD);*/ for(r = fb->r; r.min.y < fb->r.max.y; r.min.y++){ r.max.y = r.min.y+1; loadimage(screenb, r, byteaddr(fb, r.min), bytesperline(r, fb->depth)); } lockdisplay(display); draw(screen, screen->r, screenb, nil, ZP); flushimage(display, 1); unlockdisplay(display); } void mouse(void) { } void resize(void) { if(getwindow(display, Refnone) < 0) fprint(2, "can't reattach to window\n"); resetfb(); redraw(); } void usage(void) { fprint(2, "usage: %s\n", argv0); exits("usage"); } void threadmain(int argc, char *argv[]) { vlong t0, t; Channel *drawc; ARGBEGIN{ default: usage(); }ARGEND; if(argc) usage(); if(initdraw(nil, nil, nil) < 0) sysfatal("initdraw: %r"); if(memimageinit() < 0) sysfatal("memimageinit: %r"); if((mctl = initmouse(nil, screen)) == nil) sysfatal("initmouse: %r"); resetfb(); bg = rgb(DWhite); fg = rgb(DBlack); drawc = chancreate(1, 0); display->locking = 1; unlockdisplay(display); proccreate(kbdproc, nil, mainstacksize); proccreate(drawproc, drawc, mainstacksize); t0 = nsec(); for(;;){ enum {MOUSE, RESIZE, DRAW}; Alt a[] = { {mctl->c, &mctl->Mouse, CHANRCV}, {mctl->resizec, nil, CHANRCV}, {drawc, nil, CHANRCV}, {nil, nil, CHANEND} }; switch(alt(a)){ case MOUSE: mouse(); break; case RESIZE: resize(); break; case DRAW: redraw(); break; } t = nsec(); Δt = (t-t0)/1e9; t0 = t; } }