#include #include #include #include #include #include static struct nk_context sctx; static struct nk_context *ctx = &sctx; static struct nk_user_font nkfont; static Channel *kbdchan, *timerchan; static Mousectl *mousectl; static void kbdthread(void *v) { int fd; long n; Channel *c; Ioproc *io; IOchunk chk; c = v; io = ioproc(); if((fd = ioopen(io, "/dev/kbd", OREAD)) < 0) sysfatal("open: %r"); for(;;){ chk.addr = malloc(64); if(chk.addr == nil) sysfatal("malloc: %r"); n = ioread(io, fd, chk.addr, 64); if(n < 0) sysfatal("read: %r"); chk.len = n; send(c, &chk); } } static void timerthread(void *v) { Channel *c; Ioproc *io; vlong t; static long sleepms = 100; c = v; io = ioproc(); for(;;){ iosleep(io, sleepms); t = nsec(); send(c, &t); } } static void nkrun(void *v) { vlong t; IOchunk kbdchk; Mouse m; Image *buffer; void (*render)(struct nk_context*); render = v; buffer = allocimage(display, Rect(0, 0, Dx(screen->r), Dy(screen->r)), RGBA32, 0, DNofill); if(buffer == nil) display->error(display, "failed to allocate backbuffer"); enum { ATIMER, AKBD, ARESIZE, AMOUSE, AWAIT, AEND }; Alt alts[] = { [ATIMER] { timerchan, &t, CHANRCV }, [AKBD] { kbdchan, &kbdchk, CHANRCV }, [ARESIZE] { mousectl->resizec, nil, CHANRCV }, [AMOUSE] { mousectl->c, &m, CHANRCV }, [AEND] { nil, nil, CHANEND }, }; for(;;){ nk_input_begin(ctx); switch(alt(alts)){ case ATIMER: break; case AKBD: nk_plan9_handle_kbd(ctx, kbdchk.addr, kbdchk.len); free(kbdchk.addr); kbdchk.addr = nil; break; case ARESIZE: if(getwindow(display, Refnone) < 0) sysfatal("getwindow: %r"); break; case AMOUSE: nk_plan9_handle_mouse(ctx, m, screen->r.min); break; } nk_input_end(ctx); /* handle usual plan 9 exit key */ if(nk_input_is_key_down(&ctx->input, NK_KEY_DEL)) threadexitsall(nil); render(ctx); /* render everything */ draw(buffer, buffer->r, display->black, nil, ZP); nk_plan9_render(ctx, buffer); draw(screen, screen->r, buffer, nil, ZP); flushimage(display, 1); } } void nkinit(void (*render)(struct nk_context*)) { if(initdraw(nil, nil, argv0) < 0) sysfatal("initdraw: %r"); kbdchan = chancreate(sizeof(IOchunk), 0); timerchan = chancreate(sizeof(vlong), 0); threadcreate(kbdthread, kbdchan, 8192); threadcreate(timerthread, timerchan, 8192); mousectl = initmouse(nil, screen); if(mousectl == nil) sysfatal("initmouse: %r"); /* create nuklear font from default libdraw font */ nk_plan9_makefont(&nkfont, font); /* initialize nuklear */ if(!nk_init_default(ctx, &nkfont)) sysfatal("nk_init: %r"); nkrun(render); }