Last active
October 4, 2023 15:44
-
-
Save vurtun/0bf28ba10d5cbf69c11f5ef638e3ca45 to your computer and use it in GitHub Desktop.
Revisions
-
vurtun revised this gist
May 21, 2017 . 1 changed file with 54 additions and 35 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -27,6 +27,7 @@ struct rect {int x,y,w,h;}; #define copy(d,s,sz) ((int)(((char*)d+sz)-((char*)memcpy(d,s,(size_t)(sz))))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x)+(mask-1))&~(mask-1)))) #define alignb(x, mask) ((void*)((long long)(x) & ~(mask-1))) #define mod(x,N) ((uint)(((unsigned long long)(x)*(unsigned long long)(N))>>32)) static inline void unused_impl(int dummy,...){(void)dummy;} @@ -48,7 +49,7 @@ static inline void unused_impl(int dummy,...){(void)dummy;} #define h16(s,i,x) h4(s,i,h4(s,i+4,h4(s,i+8,h4(s,i+12,x)))) #define h64(s,i,x) h16(s,i,h16(s,i+16,h16(s,i+32,h16(s,i+48,x)))) #define idx(s,i) tid(((uint)(h64(s,0,i)^(h64(s,0,i)>>16))),0) #define id(s) idx(s,1021) struct layout; struct context; @@ -99,11 +100,12 @@ enum component_flags { INTERACTIVE = flag(1), PAINTABLE = flag(2), STATIC = flag(3), SELETABLE = flag(4), BACKGROUND = flag(5), IS_LAYER = flag(6), LAYER = IS_LAYER|PAINTABLE, IS_MOVABLE_X = flag(7), IS_MOVABLE_Y = flag(8), IS_MOVABLE = IS_MOVABLE_X|IS_MOVABLE_Y, MOVABLE_X = IS_MOVABLE_X|INTERACTIVE, MOVABLE_Y = IS_MOVABLE_Y|INTERACTIVE, @@ -179,11 +181,12 @@ struct module { struct constraint con[MODULE_MAX_CON]; int cnt; }; struct mem {struct reducer *red; int cap;}; struct reducer { int mode, payload; int max_com, max_con; int max_ext, max_nodes; char *buf; int sz, cap; }; /* extension */ @@ -268,25 +271,29 @@ api void End(struct context*); /* layout */ api void clear(struct layout*); api void layouting(struct layout*); api void reposit(FILE*, in struct layout*, in struct commit*); api inline uint find(const struct layout*, uint id); api void fold(out struct layout**, in struct reducer*, in struct layout*, void*mem, int sz, in struct extdef**, int cnt); #define map(ui,t,e) for((e)=(ui)->ext;(e)<(ui)->ext+(ui)->ext_cnt;++(e)) if((e)->info.id==(t)) api void reorder(struct layout*, struct component*); /* reducer */ api void reducer_init(struct reducer*, enum layout_type, void *mem, int sz); api void reducer_push(struct reducer*, union reducible*, in void *data, int sz, int ualign); #define reducer_comp(r,ID,def,user) reducer_push(r,&(union reducible){.comp={.tid=ID,._={.type=RED_COMP},.d=def,.usr=user}},0,0,0) #define reducer_con(r,c) reducer_push((r),&(union reducible){.con={._={.type=RED_CON},.con=(c)}},0,0,0) #define reducer_lnk(r,c,p) reducer_push(r,&(union reducible){.lnk={._={.type=RED_LNK},.child=c,.parent=p}},0,0,0) #define reducer_ext(r,t,p,s,a) reducer_push(r,&(union reducible){.ext={._={.type=RED_EXT},.id=t}},p,s,a) api void reducer_add(struct reducer*, in struct module*, int cnt); api void reducer_calc(struct reducer*, in struct layout*, out int *mem); #define reducer_begin(r) align((r)->buf, alignof(union reducible)) #define reducer_end(r) (union reducible*)(void*)((char*)(r)->buf+(r)->sz) #define reducer_next(i) (union reducible*)(void*)(((char*)(i)+(i)->com.next)) /* memory */ #define mem_begin(r) (struct mem){.red = (r), .cap = (r)->cap} api void *mem_alloc(struct mem*, int size, int align); #define mem_end(t) ((t)->red->cap = (t)->cap) /* component */ api void adjust(struct context*, struct layout*, struct component*, XEvent*, void*); @@ -306,9 +313,9 @@ api void dispatch(uint index, struct context*, struct layout*, XEvent*); intern inline int ceili(float x) { if (x >= 0) return cast(int,x); int t = cast(int,x); float r = x - cast(float,t); return (r > 0.0f) ? t+1: t; } intern inline void @@ -390,7 +397,7 @@ setup(struct component *c, const struct definition *d, struct surface *s) intern inline int cond(const struct function *f, int d, int src) { float s = cast(float,src); if (f->eq == COND_TRUE) return 1; else if (f->eq == COND_FALSE) return 0; else if (f->eq == COND_EQ) @@ -410,7 +417,7 @@ cond(const struct function *f, int d, int src) intern inline void eval(const struct function *f, int *d, int src) { float s = cast(float,src); if (f->eq == CON_CPY) *d = src; else if (f->eq == CON_SET) *d = ceili(f->cons.mul*s)+f->cons.off; @@ -448,12 +455,12 @@ at(const struct layout *ui, const struct component *c, int *x, int *y) { loop:; uint *tbl = ui->seq; const struct node *n = ui->tree + find(ui,c->id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[find(ui, ui->nodes[n->sub+i])].zorder] = ui->nodes[n->sub+i]; *x += c->off.x; *y += c->off.y; for (int i = n->cnt-1; i >= 0; --i) { const struct component *sub = ui->comp + find(ui, tbl[i]); if (!sub->attr[ACT] || !(sub->flags & INTERACTIVE)) continue; if (inbox(*x, *y, sub->attr[L], sub->attr[T], sub->attr[W], sub->attr[H])) {c = sub; goto loop;} @@ -466,15 +473,15 @@ reorder(struct layout *ui, struct component *c) const struct node *n = ui->tree + find(ui,c->id); while (n->parent != n->id) { struct component *p = ui->comp + find(ui,n->parent); if (p->flags & STATIC) goto nxt; n = ui->tree + find(ui,p->id); for (int i = 0; i < n->cnt; ++i) { struct component *sub = ui->comp + find(ui,ui->nodes[n->sub+i]); if (sub->flags & BACKGROUND) continue; if (sub->zorder > c->zorder) sub->zorder--; } c->zorder = max(n->cnt-1, 0); nxt: c = p; } return; } @@ -670,18 +677,18 @@ reducer_push(struct reducer *r, union reducible *a, const void *dat, int size, int align) { assert(r->sz + szof(union reducible) + size + align + alignof(union reducible) < r->cap); char *end = r->buf + r->sz; char *usr = align(end + szof(union reducible), max(align,1)); char *nxt = (align(usr + size + align, alignof(union reducible))); a->com.next = cast(int,(nxt-end)); switch (a->com.type) { case RED_COMP: r->max_com++; break; case RED_CON: r->max_con++; break; case RED_LNK: r->max_nodes++; break; case RED_EXT: r->payload += size + a->ext.align; a->ext.off = cast(int,usr-end); a->ext.align = align; a->ext.size = size; r->max_ext++; @@ -691,6 +698,16 @@ reducer_push(struct reducer *r, union reducible *a, copy(usr, dat, size); r->sz += a->com.next; } api void* mem_alloc(struct mem *t, int size, int align) { struct reducer *r = t->red; assert(r->sz + size + align < r->cap); char *begin = r->buf + r->cap - size; char *ptr = alignb(begin, align); r->cap -= (ptr - (r->buf + r->cap)); return ptr; } api void reducer_add(struct reducer *r, in struct module *m, int cnt) { @@ -733,7 +750,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, /* 0.) setup temp node memory for stage III and IV */ assert((r->cap - r->sz) > (szof(int) * r->max_com) + alignof(int)); int *tbl = align(r->buf + r->sz, alignof(int)); for (int i = 0; i < ui->comp_cnt; ++i) tbl[i] = ui->tree[i].cnt; @@ -780,15 +797,15 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, if (RED_CON == a->com.type) con[res->con_cnt++] = a->con.con; else if (RED_LNK == a->com.type) tbl[find(res, a->lnk.parent)]++; else if (RED_COMP == a->com.type) { const uint index = cast(uint, res->comp_cnt++); res->comp[index].usr = a->comp.usr; def[index] = a->comp.d; if (r->mode == IMMEDIATE) insert(res->tbl, res->tbl_cnt, a->comp.tid, index); res->comp[index].id = tree[index].id = a->comp.tid; setup(res->comp + index, def + index, ui->comp[0].surf); } else if (RED_EXT == a->com.type) { const void *obj = (const void*)((const char*)a + a->ext.off); char *dst = align(payload, a->ext.align); @@ -813,7 +830,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, } /* V.) setup extension state */ for (int i = 0; i < cnt; ++i) { const struct extension *e = 0; map(res, ed[i]->info.id, e) ed[i]->link(res, (void*)e->addr); } } @@ -862,20 +879,22 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) tab, n->id, n->parent, n->cnt, n->sub); } fputs("};\n", fp); for (int i = 0; i < com->cnt; ++i) { const struct extension *e = 0; const struct extlnk *lnk = com->ext_list + i; fprintf(fp, "global %s %s[] = {\n", lnk->def->info.type, lnk->name); map(ui, lnk->def->info.id, e) { fprintf(fp, "%s",tab); lnk->def->commit(fp, (void*)e->addr); } fputs("0};\n",fp); } fprintf(fp, "global const struct extension %s[] = {", com->ext); for (int i = 0; i < com->cnt; ++i) { const struct extension *e = 0; int cnt = 0; const struct extlnk *lnk = com->ext_list + i; map(ui, lnk->def->info.id, e) fprintf(fp, "\n%s{.info = {.id = %lu, .size = %d, .align = %d}, .addr = (addr)&%s[%u]},", tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); } if (!ui->ext_cnt) fputs("{{0}}};\n", fp); else fputs("\n};\n",fp); fprintf(fp, "global uint %s[cntof(%s)];\n",com->buffer,com->def); fprintf(fp, "global uint %s[cntof(%s)];\n",com->seq,com->def); fprintf(fp, "global struct component %s[cntof(%s)];\n", com->comp,com->def); -
vurtun revised this gist
May 19, 2017 . 1 changed file with 40 additions and 30 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -66,6 +66,7 @@ typedef void(*commit_f)(FILE*, void*); /* interaction */ enum {Enter = LASTEvent, Leave, Drag}; enum interaction_type { INTERACTION_NOP, INTERACTION_SET, INTERACTION_SIGNAL, INTERACTION_ENABLE, @@ -117,19 +118,21 @@ struct definition { paint_f paint; blueprint_f blueprint; struct rect size; unsigned flags; int zorder; const char *i, *p, *b; }; struct component { uint id; int attr[ATTR_CNT]; unsigned flags; int zorder; unsigned pressed:1; unsigned released:1; unsigned entered:1; unsigned hovered:1; unsigned left:1; unsigned dragged:1; struct v2 off, total; @@ -160,7 +163,7 @@ struct constraint { int anch; }; /* reducer */ enum reducible_type {RED_COMP, RED_CON, RED_LNK, RED_EXT}; union reducible { struct com {int type, next;} com; @@ -243,7 +246,6 @@ struct layout { struct context { struct reducer red; struct canvas *canvas; struct layout *root; struct layout *layout; #define MAX_COMPONENT_DEPTH 32 @@ -256,7 +258,7 @@ api void paint(struct context*,struct layout*); api void draw(struct context*, struct layout*, uint root); /* declaration */ api void Begin(struct context*, struct layout*, enum layout_type, uint root, void *mem, int size, struct surface*); #define Bind(ctx, id) (ctx)->stk[(ctx)->cur = 0] = id #define Push(ctx,id) (ctx)->stk[++(ctx)->cur] = (id) #define Peek(ctx) (ctx)->stk[(ctx)->cur] @@ -489,7 +491,8 @@ intern void interact(struct context *ctx, struct layout *ui, struct component *c, struct interaction *i, XEvent *e) { if (INTERACTION_NOP == i->type); else if (INTERACTION_SIGNAL == i->type) i->src.s(ctx, ui, c, e, i->dst); else if (INTERACTION_SET == i->type) {int *v = (int*)i->dst; *v = i->src.i;} @@ -606,12 +609,13 @@ update(struct context *ctx, struct layout *ui, XEvent *e) struct component *prev = ui->comp + last_hot; struct component *cur = ui->comp + ui->hot; prev->left = true; prev->hovered = false; e->xmotion.type = Leave; interact(ctx, ui, prev, &prev->slot.leave, e); dispatch(prev->id, ctx, ui, e); cur->entered = cur->hovered = true; e->xmotion.type = Enter; interact(ctx, ui, cur, &cur->slot.enter, e); dispatch(cur->id, ctx, ui, e); @@ -747,14 +751,14 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, res->tree = tree = align(res->def + r->max_com, alignof(struct node)); res->con = con = align(res->tree + r->max_com, alignof(struct constraint)); res->ext = ext = align(res->con + r->max_con, alignof(struct extension)); void *payload = ext + r->max_ext; res->payload = ui->payload + r->payload; res->comp_cnt = ui->comp_cnt; res->con_cnt = ui->con_cnt; res->ext_cnt = ui->ext_cnt; res->node_cnt = r->max_nodes; res->init = true; res->size = sz; *ret = res; /* II.) copy old state */ @@ -781,10 +785,9 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, const uint index = cast(uint, res->comp_cnt++); ui->comp[index].usr = a->comp.usr; def[index] = a->comp.d; if (r->mode == IMMEDIATE) insert(res->tbl, res->tbl_cnt, a->comp.tid, index); ui->comp[index].id = tree[index].id = a->comp.tid; setup(ui->comp + index, def + index, ui->comp[0].surf); } else if (RED_EXT == a->com.type) { const void *obj = (const void*)((const char*)a + a->ext.off); @@ -805,8 +808,8 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, for (a = reducer_begin(r); a < reducer_end(r); a = reducer_next(a)) { if (RED_LNK != a->com.type) continue; const uint id = find(res, a->lnk.parent); nodes[tree[id].sub + tree[id].cnt++] = a->lnk.child; tree[find(res, a->lnk.child)].parent = a->lnk.parent; } /* V.) setup extension state */ for (int i = 0; i < cnt; ++i) { const struct extension *e = 0; @@ -820,38 +823,44 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) const char *tab = (!com->tab) ? " ": com->tab; const char *attrs[] = {"0","ACT","L","T","R","B","W","H","CX","CY"}; const char *cons[] = {"CON_CPY","CON_SET","CON_MIN","CON_MAX"}; const char *cond[] = {"COND_TRUE","COND_FALSE","COND_EQ","COND_NEQ","COND_GR","COND_LS","COND_GRE","COND_LSE"}; fprintf(fp,"global const struct constraint %s[] = {\n", com->con); for (int i = 0; i < ui->con_cnt; ++i) { const struct constraint *c = ui->con + i; fprintf(fp, "%s{{.eq = %s, .dst = {%lu,%s}, .src = {%lu,%s}, .cons = {.mul = %.2ff, .off = %d}}, .anch = %s,", tab,cons[c->self.eq], c->self.dst.comp, attrs[c->self.dst.attr], c->self.src.comp, attrs[c->self.src.attr], (double)c->self.cons.mul, c->self.cons.off, attrs[c->anch]); if (c->cond.eq != COND_TRUE) { fprintf(fp, " .cond = {.eq = %s, .dst = {%lu,%s}, .src = {%lu,%s}, .cons = {.mul = %.2ff, .off = %d}}},\n", cond[c->cond.eq], c->cond.dst.comp, attrs[c->cond.dst.attr], c->cond.src.comp,attrs[c->cond.src.attr], (double)c->cond.cons.mul, c->cond.cons.off); } else fputs("},\n",fp); } fputs("};\n", fp); fprintf(fp, "global const struct definition %s[] = {\n", com->def); for (int i = 0; i < ui->comp_cnt; ++i) { const struct definition *d = ui->def + i; char buf[128]; int n = 0; buf[n++] = '0'; if (d->flags & HIDDEN) n += copy(buf+n, "|HIDDEN",7); if (d->flags & INTERACTIVE) n += copy(buf+n, "|INTERACTIVE",12); if (d->flags & PAINTABLE) n += copy(buf+n, "|PAINTABLE",10); if (d->flags & IS_LAYER) n += copy(buf+n, "|LAYER",6); if (d->flags & IS_MOVABLE_X) n += copy(buf+n, "|MOVABLE_X",10); if (d->flags & IS_MOVABLE_Y) n += copy(buf+n, "|MOVABLE_Y",10); buf[n] = 0; fprintf(fp, "%s{tbl(%s,%s,%s), .size={%d,%d,%d,%d}, .flags = %s},\n", tab,d->i, d->p, d->b, d->size.x, d->size.y, d->size.w, d->size.h, buf); } fputs("};\n", fp); fprintf(fp, "global const uint %s[] = {", com->nodes); for (int i = 0; i < ui->node_cnt; ++i) { if (!(i & 15)) fprintf(fp,"\n%s", tab); fprintf(fp, "%lu,", ui->nodes[i]); } fputs("\n};\n",fp); fprintf(fp, "global const struct node %s[] = {\n", com->tree); for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; fprintf(fp, "%s{.id = %lu, .parent = %lu, .cnt = %d, .sub = %d},\n", tab, n->id, n->parent, n->cnt, n->sub); } fputs("};\n", fp); for (int i = 0; i < com->cnt; ++i) { const struct extlnk *lnk = com->ext_list + i; fprintf(fp, "global const %s %s[] = {", lnk->def->info.type, lnk->name); @@ -865,7 +874,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) map(ui, lnk->def->info.id, e) fprintf(fp, "\n%s{.id = %lu, .size = %d, .align = %d, .addr = (addr)&%s[%u]},", tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); } if (!ui->ext_cnt) fputs("{{0}}", fp); fputs("};\n",fp); fprintf(fp, "global uint %s[cntof(%s)];\n",com->buffer,com->def); fprintf(fp, "global uint %s[cntof(%s)];\n",com->seq,com->def); @@ -879,22 +888,23 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) } api void Begin(struct context *ctx, struct layout *ui, enum layout_type type, uint root, void *mem, int siz, struct surface *scrn) { ctx->layout = ui; ctx->cur = ctx->stk[0] = 0; ui->comp[ROOT].surf = scrn; reducer_init(&ctx->red, type, mem, siz); for (int i = 0; i < ui->comp_cnt; ++i) ui->comp[i].pressed = ui->comp[i].released = ui->comp[i].entered = ui->comp[i].left = ui->comp[i].dragged = 0; if (!ui->init) { for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; struct component *c = ui->comp + i; c->id = cast(uint, n->id); setup(c, ui->def + i, scrn); } ui->init = true; } Push(ctx, root); } api void End(struct context *ctx) @@ -904,4 +914,4 @@ End(struct context *ctx) ctx->layout = ctx->root; ctx->stk[0] = ctx->cur = 0; } #endif -
vurtun revised this gist
May 18, 2017 . 1 changed file with 15 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -268,8 +268,7 @@ api void clear(struct layout*); api void layouting(struct layout*); api void reorder(struct layout*, struct component*); api void reposit(FILE*, in struct layout*, in struct commit*); api inline uint find(const struct layout*, uint id); #define map(ui,t,e) for((e)=(ui)->ext;(e)<(ui)->ext+(ui)->ext_cnt;++(e)) if((e)->info.id==(t)) #define apply(ui,t,f,u) for(const struct extension *_=(ui)->ext;(_)<(ui)->ext+(ui)->ext_cnt;++(_)) if((_)->info.id==(t)) f(u,(void*)_->addr) @@ -423,27 +422,23 @@ insert(uint *tbl, int tbl_cnt, uint tid, uint val) { if (off(tid)) return; uint begin = mod(key(tid), cast(uint, tbl_cnt)), id = begin; do {uint idx = tbl[id]; if ((!id && val) || idx) continue; tbl[id] = val; return; } while ((mod(++id, cast(uint, tbl_cnt))) != begin); } api inline uint find(const struct layout *ui, uint tid) { if (ui->tbl) { uint begin = mod(key(tid), cast(uint, ui->tbl_cnt)), id = begin; do {uint idx = ui->tbl[id]; if (!idx) return 0; struct component *c = ui->comp + idx; if (c->id == id) return id+off(tid); } while ((mod(++id, cast(uint, ui->tbl_cnt))) != begin); return 0; } uint idx = key(tid) + off(tid); return (idx >= cast(uint,ui->comp_cnt)) ? 0: idx; } intern uint @@ -856,7 +851,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) for (int i = 0; i < ui->node_cnt; ++i) { if (!(i & 31)) fprintf(fp,"\n%s", tab); fprintf(fp, "%lu,", ui->nodes[i]); } fputs("\n};\n",fp); for (int i = 0; i < com->cnt; ++i) { const struct extlnk *lnk = com->ext_list + i; fprintf(fp, "global const %s %s[] = {", lnk->def->info.type, lnk->name); @@ -886,10 +881,10 @@ api void Begin(struct context *ctx, struct layout *ui, enum layout_type type, void *mem, int siz, struct surface *scrn) { ui->comp[ROOT].surf = scrn; ctx->layout = ui; ctx->cur = ctx->stk[0] = 0; reducer_init(&ctx->red, type, mem, siz); for (int i = 0; i < ui->comp_cnt; ++i) ui->comp[i].pressed = ui->comp[i].released = ui->comp[i].dragged = 0; if (!ui->init) { -
vurtun revised this gist
May 17, 2017 . 1 changed file with 58 additions and 45 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -38,14 +38,17 @@ static inline void unused_impl(int dummy,...){(void)dummy;} #define inbox(px,py,x,y,w,h) (between(px,x,x+w) && between(py,y,y+h)) #define intersect(x0,y0,w0,h0,x1,y1,w1,h1) (!(((x1>(x0+w0))||((x1+w1)<x0)||(y1>(y0+h0))||(y1+h1)<y0))) #define off(id) (((id)>>24u)&255u) #define key(id) ((id)&(~(255u<<24u))) #define tid(id,off) (((id)&(~(255u<<24u)))|((off&255u)<<24u)) #define len(s) (cntof(s)-1) #define h1(s,i,x) (x*65599u+(unsigned char)s[(i)<len(s)?len(s)-1-(i):len(s)]) #define h4(s,i,x) h1(s,i,h1(s,i+1,h1(s,i+2,h1(s,i+3,x)))) #define h16(s,i,x) h4(s,i,h4(s,i+4,h4(s,i+8,h4(s,i+12,x)))) #define h64(s,i,x) h16(s,i,h16(s,i+16,h16(s,i+32,h16(s,i+48,x)))) #define idx(s,i) tid(((uint)(h64(s,0,i)^(h64(s,0,i)>>16))),0) #define id(s) idx(s,42) struct layout; struct context; @@ -239,6 +242,8 @@ struct layout { #define ROOT 0 struct context { struct reducer red; struct canvas *canvas; struct surface *scrn; struct layout *root; struct layout *layout; #define MAX_COMPONENT_DEPTH 32 @@ -249,7 +254,6 @@ api void update(struct context*, struct layout*, XEvent*); api void blueprint(struct context*,struct layout*); api void paint(struct context*,struct layout*); api void draw(struct context*, struct layout*, uint root); /* declaration */ api void Begin(struct context*, struct layout*, enum layout_type, void *mem, int size, struct surface*); @@ -260,23 +264,27 @@ api void Begin(struct context*, struct layout*, enum layout_type, void *mem, int api void End(struct context*); /* layout */ api void clear(struct layout*); api void layouting(struct layout*); api void reorder(struct layout*, struct component*); api void reposit(FILE*, in struct layout*, in struct commit*); api inline uint lookup(in struct layout*, uint id); api inline uint find(const struct layout *ui, uint id); #define map(ui,t,e) for((e)=(ui)->ext;(e)<(ui)->ext+(ui)->ext_cnt;++(e)) if((e)->info.id==(t)) #define apply(ui,t,f,u) for(const struct extension *_=(ui)->ext;(_)<(ui)->ext+(ui)->ext_cnt;++(_)) if((_)->info.id==(t)) f(u,(void*)_->addr) /* fold */ api void reducer_init(struct reducer*, enum layout_type, void *mem, int sz); api void reducer_push(struct reducer*, union reducible*, in void *data, int sz, int ualign); #define reducer_comp(r,ID,def,user) reducer_push(r,&(union reducible){.comp={.tid=ID,._={.type=RED_COMP},.d=def,.usr=user}},0,0,0) #define reducer_con(r,c) reducer_push((r),&(union reducible){.con={._={.type=RED_CON},.con=(c)}},0,0,0) #define reducer_lnk(r,c,p) reducer_push(r,&(union reducible){.lnk={._={.type=RED_LNK},.child=c,.parent=p}},0,0,0) #define reducer_custom(r,t,p,s,a) reducer_push(r,&(union reducible){.ext={._={.type=RED_EXT},.id=t}},p,s,a) api void reducer_add(struct reducer*, in struct module*, int cnt); api void reducer_calc(struct reducer*, in struct layout*, out int *mem); #define reducer_begin(r) align((r)->buf, alignof(union reducible)) #define reducer_end(r) (union reducible*)(void*)((char*)(r)->buf+(r)->sz) #define reducer_next(i) (union reducible*)(void*)(((char*)(i)+(i)->com.next)) api void fold(out struct layout**, in struct reducer*, in struct layout*, void*mem, int sz, in struct extdef**, int cnt); /* component */ @@ -413,34 +421,37 @@ eval(const struct function *f, int *d, int src) intern void insert(uint *tbl, int tbl_cnt, uint tid, uint val) { if (off(tid)) return; uint begin = mod(key(tid), cast(uint, tbl_cnt)), id = begin; do {uint index = tbl[id]; if ((!id && val) || index) continue; tbl[id] = val; return; } while ((mod(++id, cast(uint, tbl_cnt))) != begin); } api uint lookup(const struct layout *ui, uint tid) { uint begin = mod(key(tid), cast(uint, ui->tbl_cnt)), id = begin; do {uint index = ui->tbl[id]; if (!index) return 0; struct component *c = ui->comp + index; if (c->id == id) return id+off(tid); } while ((mod(++id, cast(uint, ui->tbl_cnt))) != begin); return 0; } api inline uint find(const struct layout *ui, uint id) { if (ui->tbl) return lookup(ui,id); uint idx = key(id) + off(id); return (idx >= cast(uint,ui->comp_cnt)) ? 0: idx; } intern uint at(const struct layout *ui, const struct component *c, int *x, int *y) { loop:; uint *tbl = ui->seq; const struct node *n = ui->tree + find(ui,c->id); for (int i = 0; i < n->cnt; ++i) /* O(n) sub-nodes sort by zorder */ tbl[ui->comp[find(ui, ui->nodes[n->sub+i])].zorder] = ui->nodes[n->sub+i]; *x += c->off.x; *y += c->off.y; @@ -641,15 +652,14 @@ update(struct context *ctx, struct layout *ui, XEvent *e) } break;} } api void clear(struct layout *ui) { for (int i = 1; i < ui->comp_cnt; ++i) if (ui->comp[i].surf) surf_del(ui->comp[i].surf); } api void reducer_init(struct reducer *r, enum layout_type type, void *mem, int sz) { r->mode = type; r->buf = mem; r->cap = sz; @@ -662,17 +672,17 @@ reducer_push(struct reducer *r, union reducible *a, { assert(r->sz + szof(union reducible) + size + align + alignof(union reducible) < r->cap); char *end = (char*)r->buf + r->sz; char *usr = align(end + szof(union reducible), max(align,1)); char *nxt = (align(usr + size + align, alignof(union reducible))); a->com.next = (int)(nxt-end); switch (a->com.type) { case RED_COMP: r->max_com++; break; case RED_CON: r->max_con++; break; case RED_LNK: r->max_nodes++; break; case RED_EXT: r->payload += size + a->ext.align; a->ext.off = (int)(usr-end); a->ext.align = align; a->ext.size = size; r->max_ext++; @@ -694,7 +704,7 @@ reducer_add(struct reducer *r, in struct module *m, int cnt) } } api void reducer_calc(struct reducer *r, in struct layout *ui, out int *mem) { r->max_nodes += ui->node_cnt; r->max_ext += ui->ext_cnt; r->max_com += ui->comp_cnt; r->max_con += ui->con_cnt; @@ -724,7 +734,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, /* 0.) setup temp node memory for stage III and IV */ assert((r->cap - r->sz) > (szof(int) * r->max_com) + alignof(int)); int *tbl = align((char*)r->buf+r->sz, alignof(int)); for (int i = 0; i < ui->comp_cnt; ++i) tbl[i] = ui->tree[i].cnt; @@ -743,10 +753,11 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, res->con = con = align(res->tree + r->max_com, alignof(struct constraint)); res->ext = ext = align(res->con + r->max_con, alignof(struct extension)); res->payload = ui->payload + r->payload; res->comp_cnt = ui->comp_cnt; res->con_cnt = ui->con_cnt; res->ext_cnt = ui->ext_cnt; res->node_cnt = r->max_nodes; res->init = true; res->size = sz; void *payload = ext + r->max_ext; *ret = res; @@ -766,11 +777,11 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, payload = (char*)ext[i].addr + ext[i].info.size; } /* III.) add new state */ for (a = reducer_begin(r); a < reducer_end(r); a = reducer_next(a)) { if (RED_CON == a->com.type) con[res->con_cnt++] = a->con.con; else if (RED_LNK == a->com.type) tbl[find(res,a->lnk.parent)]++; else if (RED_COMP == a->com.type) { const uint index = cast(uint, res->comp_cnt++); ui->comp[index].usr = a->comp.usr; @@ -792,13 +803,14 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, ext[res->ext_cnt++].addr = (addr)dst; } } /* IV.) setup tree nodes */ for (int i = 1; i < r->max_com; ++i) tree[i].sub = tbl[i-1] + tree[i-1].sub; for (int i = 0; i < ui->comp_cnt; ++i) copy(nodes+tree[i].sub, ui->nodes+ui->tree[i].sub, ui->tree[i].cnt*szof(int)); for (a = reducer_begin(r); a < reducer_end(r); a = reducer_next(a)) { if (RED_LNK != a->com.type) continue; const uint id = find(res, a->lnk.parent); tree[id].parent = a->lnk.parent; nodes[tree[id].sub + tree[id].cnt++] = a->lnk.child; } /* V.) setup extension state */ for (int i = 0; i < cnt; ++i) { @@ -837,12 +849,12 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) fprintf(fp, "global const struct node %s[] = {\n", com->tree); for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; fprintf(fp, "%s{.id = %lu, .parent = %lu, .cnt = %d, .sub = %d},\n", tab, n->id, n->parent, n->cnt, n->sub); } fputs("};\n", fp); fprintf(fp, "global const uint %s[] = {", com->nodes); for (int i = 0; i < ui->node_cnt; ++i) { if (!(i & 31)) fprintf(fp,"\n%s", tab); fprintf(fp, "%lu,", ui->nodes[i]); } fputs("};\n",fp); for (int i = 0; i < com->cnt; ++i) { @@ -860,22 +872,23 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); } if (!ui->ext_cnt) fputs("0", fp); fputs("};\n",fp); fprintf(fp, "global uint %s[cntof(%s)];\n",com->buffer,com->def); fprintf(fp, "global uint %s[cntof(%s)];\n",com->seq,com->def); fprintf(fp, "global struct component %s[cntof(%s)];\n", com->comp,com->def); fprintf(fp, "global struct layout %s = {\n", com->layout); fprintf(fp, "%s.comp = %s,\n%s.tree = %s,\n", tab,com->comp, tab, com->tree); fprintf(fp, "%s.buffer = %s,\n%s.seq = %s,\n", tab,com->buffer, tab,com->seq); fprintf(fp, "%s.def = %s,\n%s.con = %s,\n%s.ext = %s,\n",tab,com->def,tab,com->con,tab,com->ext); fprintf(fp, "%s.comp_cnt = %d,\n%s.con_cnt = %d,\n", tab,ui->comp_cnt,tab,ui->con_cnt); fprintf(fp, "%s.ext_cnt = %d,\n%s.node_cnt = %d,\n};\n", tab,ui->ext_cnt, tab,ui->node_cnt); } api void Begin(struct context *ctx, struct layout *ui, enum layout_type type, void *mem, int siz, struct surface *scrn) { ctx->layout = ui; ctx->cur = ctx->stk[0] = 0; reducer_init(&ctx->red, type, mem, siz); ui->comp[ROOT].surf = scrn; for (int i = 0; i < ui->comp_cnt; ++i) ui->comp[i].pressed = ui->comp[i].released = ui->comp[i].dragged = 0; @@ -885,14 +898,14 @@ Begin(struct context *ctx, struct layout *ui, enum layout_type type, struct component *c = ui->comp + i; c->id = cast(uint, n->id); setup(c, ui->def + i, scrn); } ui->init = true; } } api void End(struct context *ctx) { struct layout *ui = ctx->layout; reducer_calc(&ctx->red, ui, &ui->requested); ctx->layout = ctx->root; ctx->stk[0] = ctx->cur = 0; } -
vurtun renamed this gist
May 16, 2017 . 1 changed file with 18 additions and 20 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -19,15 +19,15 @@ struct rect {int x,y,w,h;}; #define rect(x,y,w,h) (struct rect){x,y,w,h} #define cast(t,p) ((t)(p)) #define szof(a) ((int)sizeof(a)) #define zero(d,sz) memset(d,0,(size_t)(sz)) #define unused(...) unused_impl(0,__VA_ARGS__) #define cntof(a) ((int)(sizeof(a)/sizeof((a)[0]))) #define fourcc(a,b,c,d) ((unsigned long)(((d)<<24)|((c)<<16)|((b)<<8)|(a))) #define copy(d,s,sz) ((int)(((char*)d+sz)-((char*)memcpy(d,s,(size_t)(sz))))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x)+(mask-1))&~(mask-1)))) #define mod(x,N) ((uint)(((unsigned long long)(x)*(unsigned long long)(N))>>32)) static inline void unused_impl(int dummy,...){(void)dummy;} #define flag(n) (1<<(n)) @@ -94,14 +94,13 @@ enum component_flags { HIDDEN = flag(0), INTERACTIVE = flag(1), PAINTABLE = flag(2), STATIC = flag(3), BACKGROUND = flag(4), IS_LAYER = flag(5), LAYER = IS_LAYER|PAINTABLE, IS_MOVABLE_X = flag(6), IS_MOVABLE_Y = flag(7), IS_MOVABLE = IS_MOVABLE_X|IS_MOVABLE_Y, MOVABLE_X = IS_MOVABLE_X|INTERACTIVE, MOVABLE_Y = IS_MOVABLE_Y|INTERACTIVE, MOVABLE = IS_MOVABLE|INTERACTIVE, @@ -275,7 +274,7 @@ api void reducer_push(struct reducer*, union reducible*, in void *data, int sz, #define reducer_comp(r,ID,def,user) reducer_push(r,&(union reducible){.comp={.tid=ID,._={.type=RED_COMP},.d=def,.usr=user}},0,0,0) #define reducer_con(r,c) reducer_push(r,&(union reducible){.con={._={.type=RED_CON},.con=c}},0,0,0) #define reducer_lnk(r,c,p) reducer_push(r,&(union reducible){.lnk={._={.type=RED_LNK},.child=c,.parent=p}},0,0,0) #define reducer_custom(r,t,p,s,a) reducer_push(r,&(union reducible){.ext={._={.type=RED_EXT},.id=t}},p,s,a) api void reducer_add(struct reducer*, in struct module*, int cnt); api void reducer_end(struct reducer*, in struct layout*, out int *mem); api void fold(out struct layout**, in struct reducer*, in struct layout*, void*mem, int sz, in struct extdef**, int cnt); @@ -504,7 +503,7 @@ paint(struct context *ctx, struct layout *ui) for (int i = 0; i < ui->comp_cnt; ++i) { struct component *c = ui->comp + i; surf_resize(c->surf, c->attr[W], c->attr[H]); if (!(c->flags & PAINTABLE) || (c->flags & IS_LAYER)) continue; if (ui->def[i].paint) ui->def[i].paint(ctx,ui,c); @@ -514,23 +513,21 @@ api void draw(struct context *ctx, struct layout *ui, uint root_id) { uint head = 0; struct component *r = ui->comp + find(ui, root_id); uint *tbl = ui->seq, *stk = ui->buffer; stk[head++] = root_id; while (head > 0) { struct component *c = ui->comp + find(ui, stk[--head]); if (c->surf && c->attr[ACT] && c->id != root_id) { if (c->flags & IS_LAYER) { ui->buffer = stk + head; if (ui->def[c->id].paint) ui->def[c->id].paint(ctx,ui,c); } surf_blit(r->surf, c->surf, c->attr[L] - r->attr[L] - r->off.x, c->attr[T] - r->attr[T] - r->off.y, 0, 0, c->attr[W], c->attr[H]); } if (!c->attr[ACT] || ((c->flags & IS_LAYER) && (c->id != root_id))) continue; const struct node *n = ui->tree + find(ui, c->id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[find(ui, ui->nodes[n->sub+i])].zorder] = ui->nodes[n->sub+i]; @@ -657,7 +654,7 @@ reducer_begin(struct reducer *r, enum layout_type type, void *mem, int sz) r->mode = type; r->buf = mem; r->cap = sz; r->max_com = r->max_con = 0; r->max_ext = r->payload = r->sz = 0; } api void reducer_push(struct reducer *r, union reducible *a, @@ -815,7 +812,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) { const char *tab = (!com->tab) ? " ": com->tab; const char *attrs[] = {"0","ACT","L","T","R","B","W","H","CX","CY"}; const char *cons[] = {"CON_CPY","CON_SET","CON_MIN","CON_MAX"}; fprintf(fp,"global const struct constraint %s[] = {\n", com->con); for (int i = 0; i < ui->con_cnt; ++i) { const struct constraint *c = ui->con + i; @@ -830,7 +827,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) if (d->flags & HIDDEN) n += copy(buf+n, "|HIDDEN",12); if (d->flags & INTERACTIVE) n += copy(buf+n, "|INTERACTABLE",18); if (d->flags & PAINTABLE) n += copy(buf+n, "|PAINTABLE",15); if (d->flags & IS_LAYER) n += copy(buf+n, "|LAYER",11); if (d->flags & IS_MOVABLE_X) n += copy(buf+n, "|MOVABLE_X",15); if (d->flags & IS_MOVABLE_Y) n += copy(buf+n, "|MOVABLE_Y",15); buf[n] = 0; @@ -897,5 +894,6 @@ End(struct context *ctx) struct layout *ui = ctx->layout; reducer_end(&ctx->red, ui, &ui->requested); ctx->layout = ctx->root; ctx->stk[0] = ctx->cur = 0; } #endif -
vurtun revised this gist
May 16, 2017 . 1 changed file with 0 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -33,8 +33,6 @@ static inline void unused_impl(int dummy,...){(void)dummy;} #define flag(n) (1<<(n)) #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define clamp(a,v,b) (max(min(b,v),a)) #define between(x,a,b) ((a) <= (x) && (x) <= (b)) #define inbox(px,py,x,y,w,h) (between(px,x,x+w) && between(py,y,y+h)) -
vurtun revised this gist
May 16, 2017 . 1 changed file with 5 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -707,12 +707,12 @@ reducer_end(struct reducer *r, in struct layout *ui, out int *mem) *mem += r->max_com * szof(struct definition); *mem += r->max_con * szof(struct constraint); *mem += r->max_com * szof(struct component); *mem += r->max_ext * szof(struct extension); *mem += (r->max_com+1) * szof(int) * ((r->mode == RETAINED) ?1:2); *mem += (r->max_nodes) * szof(int) * 2; *mem += szof(struct layout) + alignof(struct layout); *mem += alignof(struct component) + alignof(struct definition); *mem += alignof(struct constraint) + alignof(struct extension); *mem += alignof(struct node) + alignof(int); *mem += ui->payload + r->payload; } @@ -746,7 +746,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, res->def = def = align(res->comp + r->max_com, alignof(struct definition)); res->tree = tree = align(res->def + r->max_com, alignof(struct node)); res->con = con = align(res->tree + r->max_com, alignof(struct constraint)); res->ext = ext = align(res->con + r->max_con, alignof(struct extension)); res->payload = ui->payload + r->payload; res->comp_cnt = ui->con_cnt; res->con_cnt = ui->con_cnt; @@ -761,7 +761,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, copy(def, ui->def, szof(struct definition)*ui->comp_cnt); copy(tree, ui->tree, szof(struct node)*ui->comp_cnt); copy(con, ui->con, szof(struct constraint)*ui->con_cnt); copy(ext, ui->ext, szof(struct extension)*ui->ext_cnt); for (int i = 0; r->mode == IMMEDIATE && i < ui->comp_cnt; ++i) insert(res->tbl, res->tbl_cnt, ui->comp[i].id, cast(uint,i)); for (int i = 0; i < ui->ext_cnt; ++i) { @@ -807,7 +807,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, nodes[tree[id].sub + tree[id].cnt++] = a->lnk.child; } /* V.) setup extension state */ for (int i = 0; i < cnt; ++i) { const struct extension *e = 0; map(ui, ed[i]->info.id, e) ed[i]->link(res, (void*)e->addr); } -
vurtun revised this gist
May 16, 2017 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -269,7 +269,7 @@ api void reposit(FILE*, in struct layout*, in struct commit*); api inline uint lookup(in struct layout*, uint id); #define find(ui,id) ((ui->tbl)?lookup(ui,id):id) #define map(ui,t,e) for((e)=(ui)->ext;(e)<(ui)->ext+(ui)->ext_cnt;++(e)) if((e)->info.id==(t)) #define apply(ui,t,f,u) for(const struct extension *_=(ui)->ext;(_)<(ui)->ext+(ui)->ext_cnt;++(_)) if((_)->info.id==(t)) f(u,(void*)_->addr) /* fold */ api void reducer_begin(struct reducer*, enum layout_type, void *mem, int sz); @@ -724,7 +724,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, struct node *tree; struct definition *def; struct constraint *con; struct extension *ext; uint *nodes; /* 0.) setup temp node memory for stage III and IV */ @@ -858,7 +858,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) } fprintf(fp, "global const struct extension %s[] = {", com->ext); for (int i = 0; i < com->cnt; ++i) { const struct extension *e = 0; int cnt = 0; const struct extlnk *lnk = com->ext_list + i; map(ui, lnk->def->info.id, e) fprintf(fp, "\n%s{.id = %lu, .size = %d, .align = %d, .addr = (addr)&%s[%u]},", -
vurtun revised this gist
May 16, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -277,7 +277,7 @@ api void reducer_push(struct reducer*, union reducible*, in void *data, int sz, #define reducer_comp(r,ID,def,user) reducer_push(r,&(union reducible){.comp={.tid=ID,._={.type=RED_COMP},.d=def,.usr=user}},0,0,0) #define reducer_con(r,c) reducer_push(r,&(union reducible){.con={._={.type=RED_CON},.con=c}},0,0,0) #define reducer_lnk(r,c,p) reducer_push(r,&(union reducible){.lnk={._={.type=RED_LNK},.child=c,.parent=p}},0,0,0) #define reducer_ext(r,t,p,s,a) reducer_push(r,&(union reducible){.ext={._={.type=RED_EXT},.id=t}},p,s,a) api void reducer_add(struct reducer*, in struct module*, int cnt); api void reducer_end(struct reducer*, in struct layout*, out int *mem); api void fold(out struct layout**, in struct reducer*, in struct layout*, void*mem, int sz, in struct extdef**, int cnt); -
vurtun revised this gist
May 16, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -161,7 +161,7 @@ struct constraint { }; /* reduce */ enum reducible_type {RED_COMP, RED_CON, RED_LNK, RED_EXT}; union reducible { struct com {int type, next;} com; struct comp {struct com _; uint tid; struct definition d; addr usr;} comp; -
vurtun revised this gist
May 16, 2017 . 1 changed file with 25 additions and 25 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -167,7 +167,7 @@ union reducible { struct comp {struct com _; uint tid; struct definition d; addr usr;} comp; struct con {struct com _; struct constraint con;} con; struct lnk {struct com _; uint child, parent;} lnk; struct ext {struct com _; uint id; int align, size, off;} ext; }; struct module { struct definition def; @@ -177,7 +177,7 @@ struct module { int cnt; }; struct reducer { int mode, payload; int max_com, max_con; int max_ext, max_nodes; void *buf; int sz, cap; @@ -194,7 +194,7 @@ struct extdef { commit_f commit; link_f link; }; struct extension { struct extinfo info; addr addr; }; @@ -226,15 +226,15 @@ struct layout { struct component *comp; const struct definition *def; const struct constraint *con; const struct extension *ext; uint *buffer, *tbl, *seq; int comp_cnt, con_cnt; int ext_cnt, tbl_cnt; int node_cnt; int requested; int payload; int size; }; @@ -659,7 +659,7 @@ reducer_begin(struct reducer *r, enum layout_type type, void *mem, int sz) r->mode = type; r->buf = mem; r->cap = sz; r->max_com = r->max_con = 0; r->max_ext = r->payload = r->sz = 0; } api void reducer_push(struct reducer *r, union reducible *a, @@ -675,11 +675,11 @@ reducer_push(struct reducer *r, union reducible *a, case RED_COMP: r->max_com++; break; case RED_CON: r->max_con++; break; case RED_LNK: r->max_nodes++; break; case RED_EXT: r->payload += size + a->ext.align; a->ext.off = (int)(usr - end); a->ext.align = align; a->ext.size = size; r->max_ext++; default: break;} @@ -714,7 +714,7 @@ reducer_end(struct reducer *r, in struct layout *ui, out int *mem) *mem += alignof(struct component) + alignof(struct definition); *mem += alignof(struct constraint) + alignof(struct ext); *mem += alignof(struct node) + alignof(int); *mem += ui->payload + r->payload; } api void fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, @@ -747,13 +747,13 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, res->tree = tree = align(res->def + r->max_com, alignof(struct node)); res->con = con = align(res->tree + r->max_com, alignof(struct constraint)); res->ext = ext = align(res->con + r->max_con, alignof(struct ext)); res->payload = ui->payload + r->payload; res->comp_cnt = ui->con_cnt; res->con_cnt = ui->con_cnt; res->ext_cnt = ui->ext_cnt; res->init = True; res->size = sz; void *payload = ext + r->max_ext; *ret = res; /* II.) copy old state */ @@ -766,9 +766,9 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, insert(res->tbl, res->tbl_cnt, ui->comp[i].id, cast(uint,i)); for (int i = 0; i < ui->ext_cnt; ++i) { ext[i] = ui->ext[i]; ext[i].addr = (addr)align(payload, ext[i].info.align); copy((void*)ext[i].addr, (void*)ui->ext[i].addr, ext[i].info.size); payload = (char*)ext[i].addr + ext[i].info.size; } /* III.) add new state */ for (a=r->buf; (char*)a<(char*)r->buf+r->sz; a=(void*)((char*)a+a->com.next)) { @@ -785,15 +785,15 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, insert(res->tbl, res->tbl_cnt, a->comp.tid, index); } else ui->comp[index].id = tree[index].id = index; setup(ui->comp + index, def + index, ui->comp[0].surf); } else if (RED_EXT == a->com.type) { const void *obj = (const void*)((const char*)a + a->ext.off); char *dst = align(payload, a->ext.align); copy(dst, obj, a->ext.size); payload = dst + a->ext.size; ext[res->ext_cnt].info.id = a->ext.id; ext[res->ext_cnt].info.size = a->ext.size; ext[res->ext_cnt].info.align = a->ext.align; ext[res->ext_cnt++].addr = (addr)dst; } } /* IV.) setup tree nodes */ -
vurtun revised this gist
May 16, 2017 . 1 changed file with 13 additions and 16 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -23,11 +23,11 @@ struct rect {int x,y,w,h;}; #define zero(d,sz) memset(d,0,(size_t)(sz)) #define szof(a) ((int)sizeof(a)) #define cntof(a) ((int)(sizeof(a)/sizeof((a)[0]))) #define copy(d,s,sz) ((int)(((char*)d+sz)-((char*)memcpy(d,s,(size_t)(sz))))) #define fourcc(a,b,c,d) ((unsigned long)(((d)<<24)|((c)<<16)|((b)<<8)|(a))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x) + (mask-1)) & ~(mask-1)))) #define mod(x,N) ((uint)(((unsigned long long)(x)*(unsigned long long)(N)) >> 32)) static inline void unused_impl(int dummy,...){(void)dummy;} #define flag(n) (1<<(n)) @@ -249,7 +249,7 @@ struct context { }; /* context */ api void update(struct context*, struct layout*, XEvent*); api void blueprint(struct context*,struct layout*); api void paint(struct context*,struct layout*); api void draw(struct context*, struct layout*, uint root); api void clear(struct context*); @@ -295,10 +295,6 @@ api void dispatch(uint index, struct context*, struct layout*, XEvent*); #define bind_drag_y(d) (struct interaction){INTERACTION_DRAG_Y, .dst = d} #define bind_signal(d,u) (struct interaction){INTERACTION_SIGNAL, .dst = (void*)(addr)u, .src = {.s = d}} #include <assert.h> intern inline int @@ -361,7 +357,7 @@ adjust(struct context *ctx, struct layout *ui, solve(c, L, R, CX, W, CX, W); solve(c, T, B, CY, H, CY, H); blueprint(ctx, ui); layouting(ui); } intern inline void @@ -546,7 +542,7 @@ draw(struct context *ctx, struct layout *ui, uint root_id) ui->buffer = stk; } api void blueprint(struct context *ctx, struct layout *ui) { uint head = 0, tail = 1; uint *que = ui->buffer; que[tail] = ROOT; @@ -595,7 +591,7 @@ update(struct context *ctx, struct layout *ui, XEvent *e) int h = (e->type == Expose) ? e->xexpose.height: e->xconfigure.height; build(c, 0, 0, w, h); surf_resize(c->surf, w, h); blueprint(ctx, ui); layouting(ui); for (int i = 0; i < ui->comp_cnt; ++i) dispatch(cast(uint,i),ctx,ui,e); @@ -825,7 +821,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) fprintf(fp,"global const struct constraint %s[] = {\n", com->con); for (int i = 0; i < ui->con_cnt; ++i) { const struct constraint *c = ui->con + i; fprintf(fp, "%s{{.eq = %s, .dst = {%lu,%s}, .src = {%lu,%s}, .cons = {.mul = %.2ff, .off = %d}}, .anch = %s},\n", tab,cons[c->self.eq], c->self.dst.comp, attrs[c->self.dst.attr], c->self.src.comp, attrs[c->self.src.attr], (double)c->self.cons.mul, c->self.cons.off, attrs[c->anch]); } fputs("};\n", fp); @@ -846,12 +842,13 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) fprintf(fp, "global const struct node %s[] = {\n", com->tree); for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; fprintf(fp, "%s{.id = %lu, .parent = %lu, .cnt = %d, .sub = %d},", tab, n->id, n->parent, n->cnt, n->sub); } fputs("};\n", fp); fprintf(fp, "global const uint %s[] = {\n", com->nodes); for (int i = 0; i < ui->node_cnt; ++i) { if (i && !(i & 31)) fputs("\n", fp); fprintf(fp, "%lu,", ui->nodes[i]); } fputs("};\n",fp); for (int i = 0; i < com->cnt; ++i) { const struct extlnk *lnk = com->ext_list + i; @@ -864,13 +861,13 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) const struct ext *e = 0; int cnt = 0; const struct extlnk *lnk = com->ext_list + i; map(ui, lnk->def->info.id, e) fprintf(fp, "\n%s{.id = %lu, .size = %d, .align = %d, .addr = (addr)&%s[%u]},", tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); } if (!ui->ext_cnt) fputs("0", fp); fputs("};\n",fp); fprintf(fp, "global int %s[cntof(%s)];\n",com->buffer,com->def); fprintf(fp, "global int %s[cntof(%s)];\n",com->seq,com->def); fprintf(fp, "global struct component %s[cntof(%s)];\n", com->comp,com->def); fprintf(fp, "global struct layout %s = {\n", com->layout); fprintf(fp, "%s.comp_cnt = cntof(%s),\n%s.con_cnt = cntof(%s),\n", tab,com->def,tab,com->con); fprintf(fp, "%s.ext_cnt = cntof(%s)\n,%s.buffer = %s\n",tab,com->ext,tab,com->buffer); @@ -903,4 +900,4 @@ End(struct context *ctx) reducer_end(&ctx->red, ui, &ui->requested); ctx->layout = ctx->root; } #endif -
vurtun revised this gist
May 15, 2017 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -861,8 +861,8 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) } fprintf(fp, "global const struct extension %s[] = {", com->ext); for (int i = 0; i < com->cnt; ++i) { const struct ext *e = 0; int cnt = 0; const struct extlnk *lnk = com->ext_list + i; map(ui, lnk->def->info.id, e) fprintf(fp, "\n%s{.id = %d, .size = %d, .align = %d, .addr = (addr)&%s[%u]},", tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); -
vurtun revised this gist
May 15, 2017 . 1 changed file with 8 additions and 8 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -650,6 +650,14 @@ update(struct context *ctx, struct layout *ui, XEvent *e) } break;} } api void clear(struct context *ctx) { struct layout *ui = ctx->layout; for (int i = 1; i < ui->comp_cnt; ++i) if (ui->comp[i].surf) surf_del(ui->comp[i].surf); } api void reducer_begin(struct reducer *r, enum layout_type type, void *mem, int sz) { r->mode = type; @@ -895,12 +903,4 @@ End(struct context *ctx) reducer_end(&ctx->red, ui, &ui->requested); ctx->layout = ctx->root; } #endif -
vurtun revised this gist
May 15, 2017 . 1 changed file with 7 additions and 7 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -20,10 +20,10 @@ struct rect {int x,y,w,h;}; #define cast(t,p) ((t)(p)) #define unused(...) unused_impl(0,__VA_ARGS__) #define zero(d,sz) memset(d,0,(size_t)(sz)) #define szof(a) ((int)sizeof(a)) #define cntof(a) ((int)(sizeof(a)/sizeof((a)[0]))) #define copy(d,s,sz) ((int)(((char*)dst+sz)-((char*)memcpy(d,s,(size_t)sz)))) #define fourcc(a,b,c,d) ((unsigned long)(((d)<<24)|((c)<<16)|((b)<<8)|(a))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x) + (mask-1)) & ~(mask-1)))) @@ -825,12 +825,12 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) for (int i = 0; i < ui->comp_cnt; ++i) { const struct definition *d = ui->def + i; char buf[128]; int n = 0; buf[n++] = '0'; if (d->flags & HIDDEN) n += copy(buf+n, "|HIDDEN",12); if (d->flags & INTERACTIVE) n += copy(buf+n, "|INTERACTABLE",18); if (d->flags & PAINTABLE) n += copy(buf+n, "|PAINTABLE",15); if (d->flags & LAYER) n += copy(buf+n, "|LAYER",11); if (d->flags & IS_MOVABLE_X) n += copy(buf+n, "|MOVABLE_X",15); if (d->flags & IS_MOVABLE_Y) n += copy(buf+n, "|MOVABLE_Y",15); buf[n] = 0; fprintf(fp, "%s{tbl(%s,%s,%s), .size={%d,%d,%d,%d}, .flags = %s},\n", tab,d->i, d->p, d->b, d->size.x, d->size.y, d->size.w, d->size.h, buf); -
vurtun revised this gist
May 15, 2017 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -860,8 +860,9 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); } if (!ui->ext_cnt) fputs("0", fp); fputs("};\n",fp); fprintf(fp, "global int %s[cntof(%s)];\n",com->buffer,com->def); fprintf(fp, "global int %s[cntof(%s)];\n",com->seq,com->def); fprintf(fp, "global struct component %s[cntof(%s)];\n", com->comp,ui->comp_cnt,com->def); fprintf(fp, "global struct layout %s = {\n", com->layout); fprintf(fp, "%s.comp_cnt = cntof(%s),\n%s.con_cnt = cntof(%s),\n", tab,com->def,tab,com->con); fprintf(fp, "%s.ext_cnt = cntof(%s)\n,%s.buffer = %s\n",tab,com->ext,tab,com->buffer); -
vurtun revised this gist
May 15, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -861,7 +861,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) } if (!ui->ext_cnt) fputs("0", fp); fputs("};\n",fp); fprintf(fp, "global int %s[%d];\nglobal int %s[%d];\n", com->buffer,ui->comp_cnt,com->seq,ui->comp_cnt); fprintf(fp, "global struct component %s[%d];\n", com->comp,ui->comp_cnt); fprintf(fp, "global struct layout %s = {\n", com->layout); fprintf(fp, "%s.comp_cnt = cntof(%s),\n%s.con_cnt = cntof(%s),\n", tab,com->def,tab,com->con); fprintf(fp, "%s.ext_cnt = cntof(%s)\n,%s.buffer = %s\n",tab,com->ext,tab,com->buffer); -
vurtun revised this gist
May 15, 2017 . 1 changed file with 5 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -201,10 +201,10 @@ struct ext { /* commit */ struct commit { const char *comp, *nodes; const char *con, *def; const char *tree, *ext; const char *buffer, *seq; const char *layout, *tab; const struct extlnk { const char *name; @@ -860,11 +860,12 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); } if (!ui->ext_cnt) fputs("0", fp); fputs("};\n",fp); fprintf(fp, "global int %s[%d];\nglobal int %s[%d];\n", com->buffer,ui->comp_cnt,com->seq,ui->comp_cnt); fprintf(fp, "global struct component %s[%d];\n", com->comp,ui->comp_cn); fprintf(fp, "global struct layout %s = {\n", com->layout); fprintf(fp, "%s.comp_cnt = cntof(%s),\n%s.con_cnt = cntof(%s),\n", tab,com->def,tab,com->con); fprintf(fp, "%s.ext_cnt = cntof(%s)\n,%s.buffer = %s\n",tab,com->ext,tab,com->buffer); fprintf(fp, "%s.comp = %s,\n%s.tree = %s,\n%s.seq = %s,\n", tab,com->comp, tab, com->tree,tab,com->seq); fprintf(fp, "%s.def = %s,\n%s.con = %s,\n%s.ext = %s,\n};\n",tab,com->def,tab,com->con,tab,com->ext); } api void -
vurtun revised this gist
May 15, 2017 . 1 changed file with 6 additions and 6 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -273,11 +273,11 @@ api inline uint lookup(in struct layout*, uint id); /* fold */ api void reducer_begin(struct reducer*, enum layout_type, void *mem, int sz); api void reducer_push(struct reducer*, union reducible*, in void *data, int sz, int ualign); #define reducer_comp(r,ID,def,user) reducer_push(r,&(union reducible){.comp={.tid=ID,._={.type=RED_COMP},.d=def,.usr=user}},0,0,0) #define reducer_con(r,c) reducer_push(r,&(union reducible){.con={._={.type=RED_CON},.con=c}},0,0,0) #define reducer_lnk(r,c,p) reducer_push(r,&(union reducible){.lnk={._={.type=RED_LNK},.child=c,.parent=p}},0,0,0) #define reducer_custom(r,t,p,s,a) reducer_push(r,&(union reducible){.custom={._={.type=RED_CUSTOM},.id=t}},p,s,a) api void reducer_add(struct reducer*, in struct module*, int cnt); api void reducer_end(struct reducer*, in struct layout*, out int *mem); api void fold(out struct layout**, in struct reducer*, in struct layout*, void*mem, int sz, in struct extdef**, int cnt); @@ -658,7 +658,7 @@ reducer_begin(struct reducer *r, enum layout_type type, void *mem, int sz) r->max_ext = r->custom = r->sz = 0; } api void reducer_push(struct reducer *r, union reducible *a, const void *dat, int size, int align) { assert(r->sz + szof(union reducible) + size + align + alignof(union reducible) < r->cap); -
vurtun revised this gist
May 15, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -842,7 +842,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) } fputs("};\n", fp); fprintf(fp, "global const uint %s[] = {\n", com->nodes); for (int i = 0; i < ui->node_cnt; ++i) { if (i && !(i & 31)) fputs("\n", fp); fprintf(fp, "%d,", ui->nodes[i]); } fputs("};\n",fp); for (int i = 0; i < com->cnt; ++i) { -
vurtun revised this gist
May 15, 2017 . 1 changed file with 4 additions and 4 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -127,10 +127,10 @@ struct component { uint flags; int zorder; unsigned pressed:1; unsigned released:1; unsigned hovered:1; unsigned dragged:1; struct v2 off, total; struct surface *surf; -
vurtun revised this gist
May 15, 2017 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -53,7 +53,7 @@ struct layout; struct context; struct component; typedef unsigned long uint; typedef unsigned long long addr; typedef void(*paint_f)(struct context*,struct layout*,struct component*); typedef int(*handle_f)(struct context*,struct layout*,struct component*, XEvent*); -
vurtun revised this gist
May 15, 2017 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -47,7 +47,7 @@ static inline void unused_impl(int dummy,...){(void)dummy;} #define h64(s,i,x) h16(s,i,h16(s,i+16,h16(s,i+32,h16(s,i+48,x)))) #define idx(s,i) ((uint)(h64(s,0,i)^(h64(s,0,i)>>16))) #define id(s) idx(s,42) #define tid(id,off) (((id)&(~(255u<<24u)))|((off&255u)<<24u)) struct layout; struct context; @@ -420,8 +420,8 @@ eval(const struct function *f, int *d, int src) intern void insert(uint *tbl, int tbl_cnt, uint tid, uint val) { #define off(id) (((id)>>24u)&255u) #define key(id) ((id)&(~(255u<<24u))) uint key = key(tid), off = off(tid); if (off) return; uint begin = mod(key, cast(uint, tbl_cnt)), id = begin; -
vurtun revised this gist
May 15, 2017 . 1 changed file with 192 additions and 164 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,7 +2,7 @@ #define UI_INCLUDED_ #include <stdio.h> /* fputs, fprintf */ #include <string.h> /* memcpy, memset */ #define out #define in const @@ -18,16 +18,16 @@ struct rect {int x,y,w,h;}; #define v2(x,y) (struct v2){x,y} #define rect(x,y,w,h) (struct rect){x,y,w,h} #define cast(t,p) ((t)(p)) #define unused(...) unused_impl(0,__VA_ARGS__) #define copy(d,s,sz) memcpy(d,s,(size_t)(sz)) #define zero(d,sz) memset(d,0,(size_t)(sz)) #define szof(a) ((int)sizeof(a)) #define cntof(a) ((int)(sizeof(a)/sizeof((a)[0]))) #define fourcc(a,b,c,d) ((unsigned long)(((d)<<24)|((c)<<16)|((b)<<8)|(a))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x) + (mask-1)) & ~(mask-1)))) #define mod(x,N) ((uint)(((unsigned long long)x*(unsigned long long)N) >> 32)) static inline void unused_impl(int dummy,...){(void)dummy;} #define flag(n) (1<<(n)) @@ -45,13 +45,15 @@ static inline void unused_impl(int dummy,...){(void)dummy;} #define h4(s,i,x) h1(s,i,h1(s,i+1,h1(s,i+2,h1(s,i+3,x)))) #define h16(s,i,x) h4(s,i,h4(s,i+4,h4(s,i+8,h4(s,i+12,x)))) #define h64(s,i,x) h16(s,i,h16(s,i+16,h16(s,i+32,h16(s,i+48,x)))) #define idx(s,i) ((uint)(h64(s,0,i)^(h64(s,0,i)>>16))) #define id(s) idx(s,42) #define tid(id,off) (((id) & (~(31u<<28)))|((off&31)>>28)) struct layout; struct context; struct component; typedef unsigned uint; typedef unsigned long long addr; typedef void(*paint_f)(struct context*,struct layout*,struct component*); typedef int(*handle_f)(struct context*,struct layout*,struct component*, XEvent*); @@ -73,12 +75,14 @@ enum interaction_type { }; struct interaction { enum interaction_type type; union {int i; uint f; signal_f s;} src; void *dst; }; struct interaction_slots { struct interaction left_pressed; struct interaction left_released; struct interaction right_pressed; struct interaction right_released; struct interaction dragged; struct interaction enter; struct interaction leave; @@ -105,25 +109,29 @@ enum component_flags { MOVABLE = IS_MOVABLE|INTERACTIVE, }; struct node { uint id, parent; int sub, cnt; }; struct definition { handle_f handle; paint_f paint; blueprint_f blueprint; struct rect size; uint flags; int zorder; const char *i, *p, *b; }; struct component { uint id; int attr[ATTR_CNT]; uint flags; int zorder; uint pressed:1; uint released:1; uint hovered:1; uint dragged:1; struct v2 off, total; struct surface *surf; struct interaction_slots slot; @@ -139,7 +147,7 @@ enum condition_eq { }; enum constraint_eq {CON_CPY, CON_SET, CON_MIN, CON_MAX}; struct cons {float mul; int off;}; struct var {uint comp; int attr;}; struct function { int eq; struct var dst; @@ -156,29 +164,29 @@ struct constraint { enum reducible_type {RED_COMP, RED_CON, RED_LNK, RED_CUSTOM}; union reducible { struct com {int type, next;} com; struct comp {struct com _; uint tid; struct definition d; addr usr;} comp; struct con {struct com _; struct constraint con;} con; struct lnk {struct com _; uint child, parent;} lnk; struct custom {struct com _; uint id; int align, size, off;} custom; }; struct module { struct definition def; uint tid, parent; #define MODULE_MAX_CON 16 struct constraint con[MODULE_MAX_CON]; int cnt; }; struct reducer { int mode, custom; int max_com, max_con; int max_ext, max_nodes; void *buf; int sz, cap; }; /* extension */ struct extinfo { const char *type; uint id; int size, align; }; struct extdef { @@ -193,37 +201,41 @@ struct ext { /* commit */ struct commit { const char *nodes; const char *con, *def; const char *tree, *ext; const char *comp, *buffer; const char *layout, *tab; const struct extlnk { const char *name; const struct extdef *def; } *ext_list; int cnt; }; /* layout */ enum layout_type {RETAINED,IMMEDIATE}; struct layout { int init; uint active; uint origin; uint hot; const uint *nodes; const struct node *tree; struct component *comp; const struct definition *def; const struct constraint *con; const struct ext *ext; uint *buffer, *tbl, *seq; int comp_cnt, con_cnt; int ext_cnt, tbl_cnt; int node_cnt; int requested; int custom; int size; }; /* context */ @@ -233,45 +245,46 @@ struct context { struct layout *root; struct layout *layout; #define MAX_COMPONENT_DEPTH 32 uint cur, stk[MAX_COMPONENT_DEPTH]; }; /* context */ api void update(struct context*, struct layout*, XEvent*); api void blueprint(struct layout*, struct context*); api void paint(struct context*,struct layout*); api void draw(struct context*, struct layout*, uint root); api void clear(struct context*); /* declaration */ api void Begin(struct context*, struct layout*, enum layout_type, void *mem, int size, struct surface*); #define Bind(ctx, id) (ctx)->stk[(ctx)->cur = 0] = id #define Push(ctx,id) (ctx)->stk[++(ctx)->cur] = (id) #define Peek(ctx) (ctx)->stk[(ctx)->cur] #define Pop(ctx) (ctx)->cur = max((ctx)->cur-1,0); api void End(struct context*); /* layout */ api void layouting(struct layout*); api void reorder(struct layout*, struct component*); api void reposit(FILE*, in struct layout*, in struct commit*); api inline uint lookup(in struct layout*, uint id); #define find(ui,id) ((ui->tbl)?lookup(ui,id):id) #define map(ui,t,e) for((e)=(ui)->ext;(e)<(ui)->ext+(ui)->ext_cnt;++(e)) if((e)->info.id==(t)) #define apply(ui,t,f,u) for(const struct ext *_=(ui)->ext;(_)<(ui)->ext+(ui)->ext_cnt;++(_)) if((_)->info.id==(t)) f(u,(void*)_->addr) /* fold */ api void reducer_begin(struct reducer*, enum layout_type, void *mem, int sz); api void reducer_cons(struct reducer*, union reducible*, in void *data, int sz, int ualign); #define reducer_comp(r,ID,def,user) reducer_cons(r,&(union reducible){.comp={.tid=ID,._={.type=RED_COMP},.d=def,.usr=user}},0,0,0) #define reducer_con(r,c) reducer_cons(r,&(union reducible){.con={._={.type=RED_CON},.con=c}},0,0,0) #define reducer_lnk(r,c,p) reducer_cons(r,&(union reducible){.lnk={._={.type=RED_LNK},.child=c,.parent=p}},0,0,0) #define reducer_custom(r,t,p,s,a) reducer_cons(r,&(union reducible){.custom={._={.type=RED_CUSTOM},.id=t}},p,s,a) api void reducer_add(struct reducer*, in struct module*, int cnt); api void reducer_end(struct reducer*, in struct layout*, out int *mem); api void fold(out struct layout**, in struct reducer*, in struct layout*, void*mem, int sz, in struct extdef**, int cnt); /* component */ api void adjust(struct context*, struct layout*, struct component*, XEvent*, void*); api void dispatch(uint index, struct context*, struct layout*, XEvent*); /* bindings */ #define bind_set(d,v) (struct interaction){INTERACTION_SET, .dst = d, .src = {.i = v}} @@ -283,8 +296,9 @@ api void dispatch(struct component*,struct context*, struct layout*, XEvent*); #define bind_signal(d,u) (struct interaction){INTERACTION_SIGNAL, .dst = (void*)(addr)u, .src = {.s = d}} #endif /* UI_INCLUDED */ #ifdef UI_IMPLEMENTATION #include <assert.h> intern inline int @@ -335,19 +349,11 @@ solve(struct component *c, int lo, int hi, c->attr[center] = c->attr[lo] + (c->attr[len]/2); c->attr[len] = max(c->attr[len], 0); } api void adjust(struct context *ctx, struct layout *ui, struct component *c, XEvent *e, void *usr) { unused(usr); if (c->flags & IS_MOVABLE_X) c->attr[CX] += e->xmotion.x_root; if (c->flags & IS_MOVABLE_Y) @@ -375,7 +381,7 @@ setup(struct component *c, const struct definition *d, struct surface *s) if (!(d->flags & HIDDEN)) c->attr[ACT] = true; if (d->flags & PAINTABLE) c->surf = surf_mk(s->canvas, c->attr[W], c->attr[H]); if (d->flags & IS_MOVABLE) c->slot.dragged = bind_signal(adjust, 0); } @@ -412,38 +418,41 @@ eval(const struct function *f, int *d, int src) *d = max(*d, ceili(f->cons.mul*s)+f->cons.off); } intern void insert(uint *tbl, int tbl_cnt, uint tid, uint val) { #define off(id) (((id) >> 28u) & 31u) #define key(id) ((id) & (~(31u << 28u))) uint key = key(tid), off = off(tid); if (off) return; uint begin = mod(key, cast(uint, tbl_cnt)), id = begin; do {uint index = tbl[id]; if ((id == 0 && val != 0) || index) continue; tbl[id] = val; return; } while ((mod(++id, cast(uint, tbl_cnt))) != begin); } api uint lookup(const struct layout *ui, uint tid) { uint key = key(tid), off = off(tid); uint begin = mod(key, cast(uint, ui->tbl_cnt)), id = begin; do {uint index = ui->tbl[id]; if (!index) return 0; struct component *c = ui->comp + index; if (c->id == id) return id+off; } while ((mod(++id, cast(uint, ui->tbl_cnt))) != begin); return 0; } intern uint at(const struct layout *ui, const struct component *c, int *x, int *y) { loop:; uint *tbl = ui->seq; const struct node *n = ui->tree + find(ui,c->id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[find(ui, ui->nodes[n->sub+i])].zorder] = ui->nodes[n->sub+i]; *x += c->off.x; *y += c->off.y; for (int i = n->cnt-1; i >= 0; --i) { const struct component *sub = ui->comp + find(ui,tbl[i]); if (!sub->attr[ACT] || !(sub->flags & INTERACTIVE)) continue; if (inbox(*x, *y, sub->attr[L], sub->attr[T], sub->attr[W], sub->attr[H])) {c = sub; goto loop;} @@ -455,11 +464,11 @@ reorder(struct layout *ui, struct component *c) { const struct node *n = ui->tree + find(ui,c->id); while (n->parent != n->id) { struct component *p = ui->comp + find(ui,n->parent); if (p->flags & STATIC) goto next; n = ui->tree + find(ui,p->id); for (int i = 0; i < n->cnt; ++i) { struct component *sub = ui->comp + find(ui,ui->nodes[n->sub+i]); if (sub->flags & BACKGROUND) continue; if (sub->zorder > c->zorder) sub->zorder--; @@ -469,11 +478,13 @@ reorder(struct layout *ui, struct component *c) return; } api inline void dispatch(uint id, struct context *ctx, struct layout *ui, XEvent *e) { uint idx; do {idx = find(ui, id); if (ui->def[idx].handle) if (ui->def[idx].handle(ctx,ui,ui->comp+idx,e)) break; } while ((id = ui->tree[idx].parent)); } intern void interact(struct context *ctx, struct layout *ui, struct component *c, @@ -484,9 +495,9 @@ interact(struct context *ctx, struct layout *ui, struct component *c, else if (INTERACTION_SET == i->type) {int *v = (int*)i->dst; *v = i->src.i;} else if (INTERACTION_ENABLE == i->type) {uint *v = (uint*)i->dst; *v |= i->src.f;} else if (INTERACTION_DISABLE == i->type) {uint *v = (uint*)i->dst; *v &= ~i->src.f;} else if (e->type == MotionNotify) { int *d = (int*)i->dst; *d += (i->type == INTERACTION_DRAG_X) ? @@ -506,11 +517,11 @@ paint(struct context *ctx, struct layout *ui) } } api void draw(struct context *ctx, struct layout *ui, uint root_id) { uint head = 0; uint *tbl = ui->seq; uint *stk = ui->buffer; struct component *r = ui->comp + find(ui, root_id); stk[head++] = root_id; @@ -528,7 +539,7 @@ draw(struct context *ctx, struct layout *ui, unsigned root_id) if (!c->attr[ACT] || ((c->flags & LAYER) && (c->id != root_id))) continue; const struct node *n = ui->tree + find(ui, c->id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[find(ui, ui->nodes[n->sub+i])].zorder] = ui->nodes[n->sub+i]; for (int i = n->cnt-1; i >= 0; --i) stk[head++] = tbl[i]; } @@ -537,20 +548,16 @@ draw(struct context *ctx, struct layout *ui, unsigned root_id) api void blueprint(struct layout *ui, struct context *ctx) { uint head = 0, tail = 1; uint *que = ui->buffer; que[tail] = ROOT; while (head < tail) { const struct node *n = ui->tree + find(ui, que[++head]); for (int i = 0; i < n->cnt; ++i) que[++tail] = ui->nodes[n->sub+i]; } for (uint i = tail; i > 0; --i) { const struct definition *d = ui->def + find(ui, que[i]); struct component *c = ui->comp + find(ui, que[i]); if (d->blueprint) d->blueprint(ctx, ui, c); } @@ -579,11 +586,7 @@ api void update(struct context *ctx, struct layout *ui, XEvent *e) { switch (e->type) { default: dispatch(ui->active, ctx, ui, e); break; case Expose: case ConfigureNotify: { /* resize event */ @@ -595,30 +598,33 @@ update(struct context *ctx, struct layout *ui, XEvent *e) blueprint(ctx->layout, ctx); layouting(ui); for (int i = 0; i < ui->comp_cnt; ++i) dispatch(cast(uint,i),ctx,ui,e); } break; case MotionNotify: { /* enter and leave event */ uint last_hot = ui->hot; int mx = e->xmotion.x, my = e->xmotion.y; ui->hot = at(ui, ui->comp, &e->xmotion.x, &e->xmotion.y); if (last_hot != ui->hot) { struct component *prev = ui->comp + last_hot; struct component *cur = ui->comp + ui->hot; prev->hovered = false; e->xmotion.type = Leave; interact(ctx, ui, prev, &prev->slot.leave, e); dispatch(prev->id, ctx, ui, e); cur->hovered = true; e->xmotion.type = Enter; interact(ctx, ui, cur, &cur->slot.enter, e); dispatch(cur->id, ctx, ui, e); } /* dragging event */ if (ui->active == ui->origin) { struct component *a = ui->comp + find(ui,ui->active); interact(ctx,ui, a, &a->slot.dragged, e); e->xmotion.type = Drag; dispatch(a->id,ctx,ui,e); a->dragged = true; } e->xmotion.x = mx, e->xmotion.y = my; e->xmotion.type = MotionNotify; @@ -629,13 +635,18 @@ update(struct context *ctx, struct layout *ui, XEvent *e) ui->active = (down) ? ui->hot: ui->active; ui->origin = (down) ? ui->hot: ROOT; struct component *a = ui->comp + find(ui,ui->active); if (down) a->pressed = true; else a->released = true; if (e->xbutton.button == Button1) { reorder(ui, a); /* Left-Button */ if (down) interact(ctx,ui, a, &a->slot.left_pressed, e); else interact(ctx,ui, a, &a->slot.left_released, e); } else if (e->xbutton.button == Button3){ reorder(ui, a); /* Right-Button */ if (down) interact(ctx,ui, a, &a->slot.right_pressed, e); else interact(ctx,ui, a, &a->slot.right_released, e); } dispatch(a->id,ctx,ui,e); } break;} } api void @@ -659,40 +670,42 @@ reducer_cons(struct reducer *r, union reducible *a, switch (a->com.type) { case RED_COMP: r->max_com++; break; case RED_CON: r->max_con++; break; case RED_LNK: r->max_nodes++; break; case RED_CUSTOM: r->custom += size + a->custom.align; a->custom.off = (int)(usr - end); a->custom.align = align; a->custom.size = size; r->max_ext++; default: break;} copy(end, a, szof(*a)); copy(usr, dat, size); r->sz += a->com.next; } api void reducer_add(struct reducer *r, in struct module *m, int cnt) { for (int i = 0; i < cnt; ++i) { const struct module *c = m + i; reducer_comp(r,c->tid,c->def,0); reducer_lnk(r,c->tid,c->parent); for (int j = 0; j < c->cnt; ++j) reducer_con(r,c->con[j]); } } api void reducer_end(struct reducer *r, in struct layout *ui, out int *mem) { r->max_nodes += ui->node_cnt; r->max_ext += ui->ext_cnt; r->max_com += ui->comp_cnt; r->max_con += ui->con_cnt; *mem = r->max_com * szof(struct node); *mem += r->max_com * szof(struct definition); *mem += r->max_con * szof(struct constraint); *mem += r->max_com * szof(struct component); *mem += r->max_ext * szof(struct ext); *mem += (r->max_com+1) * szof(int) * ((r->mode == RETAINED) ?1:2); *mem += (r->max_nodes) * szof(int) * 2; *mem += szof(struct layout) + alignof(struct layout); *mem += alignof(struct component) + alignof(struct definition); *mem += alignof(struct constraint) + alignof(struct ext); @@ -701,12 +714,20 @@ reducer_end(struct reducer *r, in struct layout *ui, out int *mem) } api void fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, void *mem, int sz, in struct extdef **ed, int cnt) { union reducible *a; struct node *tree; struct definition *def; struct constraint *con; struct ext *ext; uint *nodes; /* 0.) setup temp node memory for stage III and IV */ assert((r->cap - r->sz) > (szof(int) * r->max_com) + alignof(int)); int *tbl = align((char*)r->buf+r->max_nodes, alignof(int)); for (int i = 0; i < ui->comp_cnt; ++i) tbl[i] = ui->tree[i].cnt; /* I.) setup layout in memory block */ struct layout *res = align(mem, alignof(struct layout)); @@ -715,7 +736,9 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, res->tbl = align(res+1, alignof(int)); res->buffer = res->tbl + res->tbl_cnt; } else res->buffer = align(res+1, alignof(int)); res->seq = res->buffer + r->max_com+1; res->nodes = nodes = res->seq + r->max_nodes; res->comp = align(res->nodes + r->max_nodes, alignof(struct component)); res->def = def = align(res->comp + r->max_com, alignof(struct definition)); res->tree = tree = align(res->def + r->max_com, alignof(struct node)); res->con = con = align(res->tree + r->max_com, alignof(struct constraint)); @@ -725,6 +748,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, res->con_cnt = ui->con_cnt; res->ext_cnt = ui->ext_cnt; res->init = True; res->size = sz; void *custom = ext + r->max_ext; *ret = res; @@ -735,31 +759,28 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, copy(con, ui->con, szof(struct constraint)*ui->con_cnt); copy(ext, ui->ext, szof(struct ext)*ui->ext_cnt); for (int i = 0; r->mode == IMMEDIATE && i < ui->comp_cnt; ++i) insert(res->tbl, res->tbl_cnt, ui->comp[i].id, cast(uint,i)); for (int i = 0; i < ui->ext_cnt; ++i) { ext[i] = ui->ext[i]; ext[i].addr = (addr)align(custom, ext[i].info.align); copy((void*)ext[i].addr, (void*)ui->ext[i].addr, ext[i].info.size); custom = (char*)ext[i].addr + ext[i].info.size; } /* III.) add new state */ for (a=r->buf; (char*)a<(char*)r->buf+r->sz; a=(void*)((char*)a+a->com.next)) { if (RED_CON == a->com.type) con[res->con_cnt++] = a->con.con; else if (RED_LNK == a->com.type) tbl[find(ui,a->lnk.parent)]++; else if (RED_COMP == a->com.type) { const uint index = cast(uint, res->comp_cnt++); ui->comp[index].usr = a->comp.usr; def[index] = a->comp.d; if (r->mode == IMMEDIATE) { ui->comp[index].id = tree[index].id = a->comp.tid; insert(res->tbl, res->tbl_cnt, a->comp.tid, index); } else ui->comp[index].id = tree[index].id = index; setup(ui->comp + index, def + index, ui->comp[0].surf); } else if (RED_CUSTOM == a->com.type) { const void *obj = (const void*)((const char*)a + a->custom.off); char *dst = align(custom, a->custom.align); @@ -771,7 +792,16 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, ext[res->ext_cnt].info.align = a->custom.align; ext[res->ext_cnt++].addr = (addr)dst; } } /* IV.) setup tree nodes */ for (int i = 1; i < r->max_com-1; ++i) tree[i+1].sub = tbl[i] + tbl[i-1]; for (int i = 0; i < ui->comp_cnt; ++i) copy(nodes+tree[i].sub, ui->nodes+ui->tree[i].sub, ui->tree[i].cnt*szof(int)); for (a=r->buf; (char*)a<(char*)r->buf+r->sz; a=(void*)((char*)a+a->com.next)) { if (RED_LNK != a->com.type) continue; const uint id = find(res, a->lnk.parent); nodes[tree[id].sub + tree[id].cnt++] = a->lnk.child; } /* V.) setup extension state */ for (int i = 0; i < cnt; ++i) { const struct ext *e = 0; map(ui, ed[i]->info.id, e) @@ -795,31 +825,26 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) for (int i = 0; i < ui->comp_cnt; ++i) { const struct definition *d = ui->def + i; char buf[128]; int n = 0; buf[n++] = '0'; if (d->flags & HIDDEN) {copy(buf+n, "|HIDDEN",12); n += 12;} if (d->flags & INTERACTIVE) {copy(buf+n, "|INTERACTABLE",18); n += 18;} if (d->flags & PAINTABLE) {copy(buf+n, "|PAINTABLE",15); n += 15;} if (d->flags & LAYER) {copy(buf+n, "|LAYER",11); n += 11;} if (d->flags & IS_MOVABLE_X) {copy(buf+n, "|MOVABLE_X",15); n += 15;} if (d->flags & IS_MOVABLE_Y) {copy(buf+n, "|MOVABLE_Y",15); n += 15;} buf[n] = 0; fprintf(fp, "%s{tbl(%s,%s,%s), .size={%d,%d,%d,%d}, .flags = %s},\n", tab,d->i, d->p, d->b, d->size.x, d->size.y, d->size.w, d->size.h, buf); } fputs("};\n", fp); fprintf(fp, "global const struct node %s[] = {\n", com->tree); for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; fprintf(fp, "%s{.id = %u, .parent = %u, .cnt = %d, .sub = %d},",tab, n->id, n->parent, n->cnt, n->sub); } fputs("};\n", fp); fprintf(fp, "global const uint %s[] = {\n", com->nodes); for (int i = 0; i < ui->node_cnt; ++i) { if (i && i & 31) fputs("\n", fp); fprintf(fp, "%d,", ui->nodes[i]); } fputs("};\n",fp); for (int i = 0; i < com->cnt; ++i) { const struct extlnk *lnk = com->ext_list + i; fprintf(fp, "global const %s %s[] = {", lnk->def->info.type, lnk->name); @@ -843,24 +868,26 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) fprintf(fp, "%s.def = %s,\n%s.con = %s,\n%s.ext = %s,\n};\n",tab,com->def,tab,com->con,tab,com->ext); } api void Begin(struct context *ctx, struct layout *ui, enum layout_type type, void *mem, int siz, struct surface *scrn) { ctx->layout = ui; ctx->cur = ctx->stk[0] = 0; reducer_begin(&ctx->red, type, mem, siz); ui->comp[ROOT].surf = scrn; for (int i = 0; i < ui->comp_cnt; ++i) ui->comp[i].pressed = ui->comp[i].released = ui->comp[i].dragged = 0; if (!ui->init) { for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; struct component *c = ui->comp + i; c->id = cast(uint, n->id); setup(c, ui->def + i, scrn); } ui->init = True; } } api void End(struct context *ctx) { struct layout *ui = ctx->layout; reducer_end(&ctx->red, ui, &ui->requested); @@ -874,3 +901,4 @@ clear(struct context *ctx) if (ui->comp[i].surf) surf_del(ui->comp[i].surf); } #endif -
vurtun revised this gist
May 9, 2017 . 1 changed file with 160 additions and 166 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -19,14 +19,15 @@ struct rect {int x,y,w,h;}; #define rect(x,y,w,h) (struct rect){x,y,w,h} #define stringify(x) #x #define cast(t,p) ((t)p) #define unused(...) unused_impl(0,__VA_ARGS__) #define copy(d,s,sz) memcpy(d,s,(size_t)(sz)) #define szof(a) ((int)sizeof(a)) #define cntof(a) ((int)(sizeof(a)/sizeof((a)[0]))) #define fourcc(a,b,c,d) ((unsigned long)(((d)<<24)|((c)<<16)|((b)<<8)|(a))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x) + (mask-1)) & ~(mask-1)))) #define mod(x,N) ((unsigned)(((unsigned long long)x*(unsigned long long)N) >> 32)) static inline void unused_impl(int dummy,...){(void)dummy;} #define flag(n) (1<<(n)) @@ -50,7 +51,6 @@ static inline void unused_impl(int dummy,...){(void)dummy;} struct layout; struct context; struct component; typedef unsigned long long addr; typedef void(*paint_f)(struct context*,struct layout*,struct component*); @@ -85,8 +85,7 @@ struct interaction_slots { }; /* component */ #define tbl(hn,pn,bp) .handle=hn,.paint=pn,.blueprint = bp,.i=#hn, .p=#pn, .b=#bp enum attributes {ANIM, ACT, L, T, R, B, W, H, CX, CY, ATTR_CNT}; enum component_flags { DEFAULT, @@ -115,7 +114,7 @@ struct definition { handle_f handle; paint_f paint; blueprint_f blueprint; struct rect size; unsigned flags; int zorder; const char *i, *p, *b; @@ -132,16 +131,13 @@ struct component { }; /* constraint */ enum condition_eq { COND_TRUE, COND_FALSE, COND_EQ, COND_NEQ, COND_GR, COND_LS, COND_GRE, COND_LSE }; enum constraint_eq {CON_CPY, CON_SET, CON_MIN, CON_MAX}; struct cons {float mul; int off;}; struct var {unsigned comp; int attr;}; struct function { @@ -153,27 +149,24 @@ struct function { struct constraint { struct function self; struct function cond; int anch; }; /* reduce */ enum reducible_type {RED_COMP, RED_CON, RED_LNK, RED_CUSTOM}; union reducible { struct com {int type, next;} com; struct comp {struct com _; unsigned id; struct definition d; addr usr;} comp; struct con {struct com _; struct constraint con;} con; struct lnk {struct com _; unsigned child, parent;} lnk; struct custom {struct com _; unsigned id; int align, size, off;} custom; }; struct module { struct definition def; unsigned id, parent; int cnt; #define MODULE_MAX_CON 16 struct constraint con[MODULE_MAX_CON]; }; struct reducer { int mode; @@ -183,20 +176,28 @@ struct reducer { }; /* extension */ struct extinfo { const char *type; unsigned id; int size, align; }; struct extdef { struct extinfo info; commit_f commit; link_f link; }; struct ext { struct extinfo info; addr addr; }; /* commit */ struct commit { const char *con, *def; const char *tree, *ext; const char *comp, *buffer; const char *layout; const char *tab; int cnt; const struct extlnk { const char *name; @@ -205,35 +206,40 @@ struct commit { }; /* layout */ enum layout_type {RETAINED,IMMEDIATE}; struct layout { int init; unsigned active; unsigned origin; unsigned hot; unsigned *buffer, *tbl; struct component *comp; const struct definition *def; const struct node *tree; const struct constraint *con; const struct ext *ext; int comp_cnt, con_cnt; int ext_cnt, tbl_cnt; int requested; int custom; }; /* context */ #define ROOT 0 struct context { struct reducer red; struct layout *root; struct layout *layout; #define MAX_COMPONENT_DEPTH 32 unsigned cur, stk[MAX_COMPONENT_DEPTH]; }; /* context */ api void begin(struct context*, struct layout*, enum layout_type, void*, int, struct surface*); api void end(struct context*); api void update(struct context*, struct layout*, XEvent*); api void blueprint(struct layout*, struct context*); api void paint(struct context*,struct layout*); api void draw(struct context*, struct layout*, unsigned root); @@ -245,32 +251,29 @@ api void clear(struct context*); /* layout */ api void layouting(struct layout*); api void reorder(struct layout*, struct component*); api void reposit(FILE*, in struct layout*, in struct commit*); api inline unsigned lookup(in struct layout*, unsigned id); #define find(ui,id) ((ui->tbl)?lookup(ui,id):id) #define map(ui,t,e) for((e)=(ui)->ext;(e)<(ui)->ext+(ui)->ext_cnt;++(e)) if((e)->info.id==(t)) #define apply(ui,t,f,u) for(const struct ext *_=(ui)->ext;(_)<(ui)->ext+(ui)->ext_cnt;++(_)) if((_)->info.id==(t)) f(u,(void*)_->addr) /* fold */ api void reducer_begin(struct reducer*, enum layout_type, void *mem, int sz); api void reducer_cons(struct reducer*, union reducible*, in void *data, int sz, int ualign); #define reducer_comp(r,ID,def,user) reducer_cons(r,&(union reducible){.comp={.id=ID,._={.type=RED_COMP},.d=def,.usr=user}},0,0,0) #define reducer_con(r,c) reducer_cons(r,&(union reducible){.con={._={.type=RED_CON},.con=c}},0,0,0) #define reducer_lnk(r,c,p) reducer_cons(r,&(union reducible){.lnk={._={.type=RED_LNK},.child=c,.parent=p}},0,0,0) #define reducer_custom(r,t,p,s,a) reducer_cons(r,&(union reducible){.custom={._={.type=RED_CUSTOM},.id=t}},p,s,a) api void reducer_mod(struct reducer*, in struct module*, int cnt); api void reducer_end(struct reducer*, in struct layout*, out int *mem); api void fold(out struct layout**, in struct reducer*, in struct layout*, out void *mem, in struct extdef**, int cnt); /* component */ api inline unsigned parent(struct layout *ui, unsigned id); api void adjust(struct context*, struct layout*, struct component*, XEvent*, void*); api void dispatch(struct component*,struct context*, struct layout*, XEvent*); /* bindings */ #define bind_set(d,v) (struct interaction){INTERACTION_SET, .dst = d, .src = {.i = v}} #define bind_toggle(d) (struct interaction){INTERACTION_NOT, .dst = d} #define bind_enable(d,v) (struct interaction){INTERACTION_ENABLE, .dst = d, .src = {.f = v}} @@ -280,7 +283,6 @@ api void dispatch(struct component*,struct context*, struct layout*, XEvent*); #define bind_signal(d,u) (struct interaction){INTERACTION_SIGNAL, .dst = (void*)(addr)u, .src = {.s = d}} #endif /* UI_INCLUDED */ #include "ui.h" #include "draw.h" #include <assert.h> @@ -351,17 +353,16 @@ adjust(struct context *ctx, struct layout *ui, if (c->flags & IS_MOVABLE_Y) c->attr[CY] += e->xmotion.y_root; solve(c, L, R, CX, W, CX, W); solve(c, T, B, CY, H, CY, H); blueprint(ui, ctx); layouting(ui); } intern inline void build(struct component *c, int x, int y, int w, int h) { c->attr[L] = x; c->attr[T] = y; c->attr[W] = max(w,0); c->attr[H] = max(h,0); c->attr[R] = x+w; c->attr[B] = y+h; c->attr[CX] = x+(w/2); c->attr[CY] = y+(h/2); } @@ -370,64 +371,65 @@ setup(struct component *c, const struct definition *d, struct surface *s) { c->flags = d->flags; c->zorder = d->zorder; build(c, d->size.x, d->size.y, d->size.w, d->size.h); if (!(d->flags & HIDDEN)) c->attr[ACT] = true; if (d->flags & PAINTABLE) c->surf = surf_mk(s->dpy, s->root, s->scrn, c->attr[W], c->attr[H]); if (d->flags & IS_MOVABLE) c->slot.dragged = bind_signal(adjust, 0); } intern inline int cond(const struct function *f, int d, int src) { float s = (float)src; if (f->eq == COND_TRUE) return 1; else if (f->eq == COND_FALSE) return 0; else if (f->eq == COND_EQ) return d == ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == COND_NEQ) return d != ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == COND_GR) return d > ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == COND_LS) return d < ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == COND_GRE) return d >= ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == COND_LSE) return d <= ceili(f->cons.mul*s)+f->cons.off; return 0; } intern inline void eval(const struct function *f, int *d, int src) { float s = (float)src; if (f->eq == CON_CPY) *d = src; else if (f->eq == CON_SET) *d = ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == CON_MIN) *d = min(*d, ceili(f->cons.mul*s)+f->cons.off); else if (f->eq == CON_MAX) *d = max(*d, ceili(f->cons.mul*s)+f->cons.off); } intern void insert(unsigned *tbl, int tbl_cnt, unsigned key, unsigned val) { unsigned begin = mod(key,cast(unsigned, tbl_cnt)), id = begin; do {unsigned index = tbl[id]; if ((id == 0 && val != 0) || index) continue; tbl[id] = val; return; } while ((mod(++id, cast(unsigned, tbl_cnt))) != begin); } api unsigned lookup(const struct layout *ui, unsigned key) { assert(ui->tbl && "use 'find' instead"); unsigned begin = mod(key,cast(unsigned,ui->tbl_cnt)), id = begin; do {unsigned index = ui->tbl[id]; if (!index) return 0; struct component *c = ui->comp + index; if (c->id == id) return id; } while ((mod(++id, cast(unsigned, ui->tbl_cnt))) != begin); return 0; } intern unsigned @@ -453,17 +455,16 @@ reorder(struct layout *ui, struct component *c) { const struct node *n = ui->tree + find(ui,c->id); while (n->parent != n->id) { struct component *p = ui->comp + find(ui, parent(ui,c->id)); if (p->flags & STATIC) goto next; n = ui->tree + find(ui,p->id); for (int i = 0; i < n->cnt; ++i) { struct component *sub = ui->comp + find(ui,n->sub[i]); if (sub->flags & BACKGROUND) continue; if (sub->zorder > c->zorder) sub->zorder--; } c->zorder = max(n->cnt-1, 0); next: c = p; } return; } @@ -538,7 +539,7 @@ blueprint(struct layout *ui, struct context *ctx) { unsigned head = 0, tail = 1; unsigned *que = ui->buffer; que[tail] = ROOT; while (head < tail) { const struct node *n; n = ui->tree + find(ui, que[++head]); @@ -575,20 +576,18 @@ layouting(struct layout *ui) } } api void update(struct context *ctx, struct layout *ui, XEvent *e) { switch (e->type) { default: { struct component *a; a = ui->comp + find(ui,ui->active); dispatch(a, ctx, ui, e); } break; case Expose: case ConfigureNotify: { /* resize event */ struct component *c = ui->comp + ROOT; int w = (e->type == Expose) ? e->xexpose.width: e->xconfigure.width; int h = (e->type == Expose) ? e->xexpose.height: e->xconfigure.height; build(c, 0, 0, w, h); @@ -601,11 +600,11 @@ update(struct context *ctx, XEvent *e) case MotionNotify: { /* enter and leave event */ int mx = e->xmotion.x, my = e->xmotion.y; unsigned last_hot = ui->hot; ui->hot = at(ui, ui->comp, &e->xmotion.x, &e->xmotion.y); if (last_hot != ui->hot) { struct component *prev = ui->comp + last_hot; struct component *cur = ui->comp + ui->hot; e->xmotion.type = Leave; interact(ctx, ui, prev, &prev->slot.leave, e); @@ -614,10 +613,9 @@ update(struct context *ctx, XEvent *e) e->xmotion.type = Enter; interact(ctx, ui, cur, &cur->slot.enter, e); dispatch(cur,ctx, ui, e); } /* dragging event */ if (ui->active == ui->origin) { struct component *a = ui->comp + find(ui,ui->active); interact(ctx,ui, a, &a->slot.dragged, e); e->xmotion.type = Drag; dispatch(a,ctx,ui,e); @@ -628,17 +626,16 @@ update(struct context *ctx, XEvent *e) case ButtonRelease: case ButtonPress: { int down = e->type == ButtonPress; ui->active = (down) ? ui->hot: ui->active; ui->origin = (down) ? ui->hot: ROOT; struct component *a = ui->comp + find(ui,ui->active); if (e->xbutton.button == Button1 && down) { reorder(ui, a); interact(ctx,ui, a, &a->slot.left, e); } else if (e->xbutton.button == Button3 && down){ reorder(ui, a); interact(ctx,ui, a, &a->slot.right, e); } dispatch(a,ctx,ui,e); } break;} } api void @@ -650,42 +647,40 @@ reducer_begin(struct reducer *r, enum layout_type type, void *mem, int sz) r->max_ext = r->custom = r->sz = 0; } api void reducer_cons(struct reducer *r, union reducible *a, const void *dat, int size, int align) { assert(r->sz + szof(union reducible) + size + align + alignof(union reducible) < r->cap); char *end = (char*)r->buf + r->sz; char *usr = align(end + szof(union reducible), align); char *nxt = end + r->sz + szof(union reducible) + size + align; a->com.next = (int)((char*)(align(nxt, alignof(union reducible))) - end); switch (a->com.type) { case RED_COMP: r->max_com++; break; case RED_CON: r->max_con++; break; case RED_CUSTOM: r->custom = size + a->custom.align; a->custom.off = (int)(usr - end); a->custom.align = align; a->custom.size = size; r->max_ext++; default: break;} copy(end, a, szof(union reducible)); copy(usr, dat, size); r->sz += a->com.next; } api void reducer_mod(struct reducer *r, in struct module *m, int cnt) { for (int i = 0; i < cnt; ++i) { in struct module *c = m + i; reducer_comp(r,c->id,c->def,0); reducer_lnk(r,c->id,c->parent); for (int j = 0; j < c->cnt; ++j) reducer_con(r,c->con[j]); } } api void reducer_end(struct reducer *r, in struct layout *ui, out int *mem) @@ -695,41 +690,41 @@ reducer_end(struct reducer *r, in struct layout *ui, out int *mem) *mem = r->max_com * szof(struct node); *mem += r->max_com * szof(struct definition); *mem += r->max_con * szof(struct constraint); *mem += r->max_com * szof(struct component); *mem += r->max_ext * szof(struct ext); *mem += (r->max_com+1) * szof(int) * ((r->mode == RETAINED) ?1:2); *mem += szof(struct layout) + alignof(struct layout); *mem += alignof(struct component) + alignof(struct definition); *mem += alignof(struct constraint) + alignof(struct ext); *mem += alignof(struct node) + alignof(int); *mem += ui->custom + r->custom; } api void fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, void *mem, in struct extdef **ed, int cnt) { struct node *tree; struct definition *def; struct constraint *con; struct ext *ext; /* I.) setup layout in memory block */ struct layout *res = align(mem, alignof(struct layout)); if (r->mode == IMMEDIATE) { res->tbl_cnt = r->max_com; res->tbl = align(res+1, alignof(int)); res->buffer = res->tbl + res->tbl_cnt; } else res->buffer = align(res+1, alignof(int)); res->comp = align(res->buffer + r->max_com+1, alignof(struct component)); res->def = def = align(res->comp + r->max_com, alignof(struct definition)); res->tree = tree = align(res->def + r->max_com, alignof(struct node)); res->con = con = align(res->tree + r->max_com, alignof(struct constraint)); res->ext = ext = align(res->con + r->max_con, alignof(struct ext)); res->custom = ui->custom + r->custom; res->comp_cnt = ui->con_cnt; res->con_cnt = ui->con_cnt; res->ext_cnt = ui->ext_cnt; res->init = True; void *custom = ext + r->max_ext; *ret = res; @@ -738,7 +733,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, copy(def, ui->def, szof(struct definition)*ui->comp_cnt); copy(tree, ui->tree, szof(struct node)*ui->comp_cnt); copy(con, ui->con, szof(struct constraint)*ui->con_cnt); copy(ext, ui->ext, szof(struct ext)*ui->ext_cnt); for (int i = 0; r->mode == IMMEDIATE && i < ui->comp_cnt; ++i) insert(res->tbl, res->tbl_cnt, ui->comp[i].id, (unsigned)i); for (int i = 0; i < ui->ext_cnt; ++i) { @@ -749,23 +744,23 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, } /* III.) add new state */ char *end = (char*)r->buf + r->sz; for (union reducible *a = r->buf; (char*)a < end; a = (void*)((char*)a + a->com.next)) { if (RED_COMP == a->com.type) { const unsigned id = a->comp.id; const int index = res->comp_cnt++; ui->comp[index].id = tree[index].id = id; ui->comp[index].usr = a->comp.usr; def[index] = a->comp.d; if (r->mode == IMMEDIATE) insert(res->tbl, res->tbl_cnt, id, (unsigned)index); setup(ui->comp + id, def + id, ui->comp[0].surf); } else if (RED_CON == a->com.type) { con[res->con_cnt++] = a->con.con; } else if (RED_LNK == a->com.type) { struct node *n = tree + a->lnk.parent; n->sub[n->cnt] = a->lnk.child; res->comp[a->lnk.child].zorder = n->cnt++; } else if (RED_CUSTOM == a->com.type) { const void *obj = (const void*)((const char*)a + a->custom.off); char *dst = align(custom, a->custom.align); copy(dst, obj, a->custom.size); @@ -778,17 +773,17 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, } } /* IV.) setup extension state */ for (int i = 0; i < cnt; ++i) { const struct ext *e = 0; map(ui, ed[i]->info.id, e) ed[i]->link(res, (void*)e->addr); } } api void reposit(FILE *fp, in struct layout *ui, const struct commit *com) { const char *tab = (!com->tab) ? " ": com->tab; const char *attrs[] = {"0","ACT","L","T","R","B","W","H","CX","CY"}; const char *cons[] = {"CON_CPY", "CON_SET", "CON_MIN", "CON_MAX"}; fprintf(fp,"global const struct constraint %s[] = {\n", com->con); for (int i = 0; i < ui->con_cnt; ++i) { const struct constraint *c = ui->con + i; @@ -814,7 +809,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com, const char *ta {copy(buf+n, "|MOVABLE_Y",15); n += 15;} buf[n] = 0; fprintf(fp, "%s{TBL(%s,%s,%s), .sz={%d,%d,%d,%d}, .flags = %s},\n", tab,d->i, d->p, d->b, d->size.x, d->size.y, d->size.w, d->size.h, buf); } fputs("};\n", fp); fprintf(fp, "global const struct node %s[] = {\n", com->tree); for (int i = 0; i < ui->comp_cnt; ++i) { @@ -833,7 +828,7 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com, const char *ta } fprintf(fp, "global const struct extension %s[] = {", com->ext); for (int i = 0; i < com->cnt; ++i) { const struct ext *e = 0; int cnt = 0; const struct extlnk *lnk = com->ext_list + i; map(ui, lnk->def->info.id, e) fprintf(fp, "\n%s{.id = %d, .size = %d, .align = %d, .addr = (addr)&%s[%u]},", @@ -854,23 +849,22 @@ begin(struct context *ctx, struct layout *ui, enum layout_type type, ctx->layout = ui; ctx->cur = ctx->stk[0] = 0; reducer_begin(&ctx->red, type, mem, siz); ui->comp[ROOT].surf = scrn; if (!ui->init) { for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; struct component *c = ui->comp + i; c->id = cast(unsigned,n->id); setup(c, ui->def + i, scrn); } ui->init = True; } } api void end(struct context *ctx) { struct layout *ui = ctx->layout; reducer_end(&ctx->red, ui, &ui->requested); ctx->layout = ctx->root; } api void clear(struct context *ctx) -
vurtun revised this gist
May 9, 2017 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -26,6 +26,7 @@ struct rect {int x,y,w,h;}; #define fourcc(a,b,c,d) ((unsigned long)(((d)<<24)|((c)<<16)|((b)<<8)|(a))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x) + (mask-1)) & ~(mask-1)))) #define mod(x,N) ((unsigned)(((unsigned long long)x * (unsigned long long)N) >> 32)) static inline void unused_impl(int dummy,...){(void)dummy;} #define flag(n) (1<<(n)) @@ -412,7 +413,7 @@ eval(const struct function *f, int *d, int src) intern void insert(unsigned *tbl, int tbl_cnt, unsigned key, unsigned val) { unsigned begin = mod(key,(unsigned)tbl_cnt), id = begin; do {unsigned index = tbl[id]; if ((id == 0 && val != 0) || index) continue; tbl[id] = val; return; @@ -422,7 +423,7 @@ api unsigned lookup(const struct layout *ui, unsigned id) { assert(ui->tbl && "use 'find' instead"); unsigned begin = mod(id, (unsigned)ui->tbl_cnt), index = begin; do {struct component *c = ui->comp + ui->tbl[index]; if (!c->id) break; if (c->id == id) return index; -
vurtun revised this gist
May 4, 2017 . 1 changed file with 359 additions and 88 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,3 +1,285 @@ #ifndef UI_INCLUDED_ #define UI_INCLUDED_ #include <stdio.h> /* fputs, fprintf */ #include <string.h> /* memcpy */ #define out #define in const #define api extern #define hook static #define intern static #define global static #define storage static enum {false, true}; struct v2 {int x,y;}; struct rect {int x,y,w,h;}; #define v2(x,y) (struct v2){x,y} #define rect(x,y,w,h) (struct rect){x,y,w,h} #define stringify(x) #x #define unused(...) unused_impl(0,__VA_ARGS__) #define copy(d,s,sz) memcpy(d,s,(size_t)(sz)) #define szof(a) ((int)sizeof(a)) #define cntof(a) ((int)(sizeof(a)/sizeof((a)[0]))) #define fourcc(a,b,c,d) ((unsigned long)(((d)<<24)|((c)<<16)|((b)<<8)|(a))) #define alignof(t) ((int)((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)) #define align(x, mask) ((void*)(((long long)((const char*)(x) + (mask-1)) & ~(mask-1)))) static inline void unused_impl(int dummy,...){(void)dummy;} #define flag(n) (1<<(n)) #define min(a,b) ((a)<(b)?(a):(b)) #define max(a,b) ((a)>(b)?(a):(b)) #define min3(a,b,c) min(min(a,b),c) #define max3(a,b,c) max(max(a,b),c) #define clamp(a,v,b) (max(min(b,v),a)) #define between(x,a,b) ((a) <= (x) && (x) <= (b)) #define inbox(px,py,x,y,w,h) (between(px,x,x+w) && between(py,y,y+h)) #define intersect(x0,y0,w0,h0,x1,y1,w1,h1) (!(((x1>(x0+w0))||((x1+w1)<x0)||(y1>(y0+h0))||(y1+h1)<y0))) #define len(s) (cntof(s)-1) #define h1(s,i,x) (x*65599u+(unsigned char)s[(i)<len(s)?len(s)-1-(i):len(s)]) #define h4(s,i,x) h1(s,i,h1(s,i+1,h1(s,i+2,h1(s,i+3,x)))) #define h16(s,i,x) h4(s,i,h4(s,i+4,h4(s,i+8,h4(s,i+12,x)))) #define h64(s,i,x) h16(s,i,h16(s,i+16,h16(s,i+32,h16(s,i+48,x)))) #define idx(s,i) ((unsigned)(h64(s,0,i)^(h64(s,0,i)>>16))) #define id(s) idx(s,0) struct layout; struct context; struct component; struct extension; typedef unsigned long long addr; typedef void(*paint_f)(struct context*,struct layout*,struct component*); typedef int(*handle_f)(struct context*,struct layout*,struct component*, XEvent*); typedef void(*signal_f)(struct context*,struct layout*,struct component*, XEvent*,void *usr); typedef void(*blueprint_f)(struct context*,struct layout*,struct component*); typedef void(*link_f)(struct layout*, void*); typedef void(*commit_f)(FILE*, void*); /* interaction */ enum {Enter = LASTEvent, Leave, Drag}; enum interaction_type { INTERACTION_SET, INTERACTION_SIGNAL, INTERACTION_ENABLE, INTERACTION_DISABLE, INTERACTION_DRAG_X, INTERACTION_DRAG_Y, INTERACTION_CNT, }; struct interaction { enum interaction_type type; union {int i; unsigned f; signal_f s;} src; void *dst; }; struct interaction_slots { struct interaction left; struct interaction right; struct interaction dragged; struct interaction enter; struct interaction leave; }; /* component */ #define COMPONENT_ROOT 0 #define TBL(hn,pn,bp) .handle=hn,.paint=pn,.blueprint = bp,.i=#hn, .p=#pn, .b=#bp enum attributes {ANIM, ACT, L, T, R, B, W, H, CX, CY, ATTR_CNT}; enum component_flags { DEFAULT, HIDDEN = flag(0), INTERACTIVE = flag(1), PAINTABLE = flag(2), LAYER = flag(3), STATIC = flag(4), BACKGROUND = flag(5), IS_MOVABLE_X = flag(6), IS_MOVABLE_Y = flag(7), IS_MOVABLE = IS_MOVABLE_X|IS_MOVABLE_Y, MOVABLE_X = IS_MOVABLE_X|INTERACTIVE, MOVABLE_Y = IS_MOVABLE_Y|INTERACTIVE, MOVABLE = IS_MOVABLE|INTERACTIVE, }; struct node { unsigned id, parent; #define MAX_NODES_PER_NODE 32 unsigned sub[MAX_NODES_PER_NODE]; int cnt; }; struct definition { handle_f handle; paint_f paint; blueprint_f blueprint; struct rect sz; unsigned flags; int zorder; const char *i, *p, *b; }; struct component { unsigned id; int attr[ATTR_CNT]; unsigned flags; int zorder; struct v2 off, total; struct surface *surf; struct interaction_slots slot; addr usr; }; /* constraint */ enum constraint_eq { CONSTRAINT_CPY, CONSTRAINT_SET, CONSTRAINT_MIN, CONSTRAINT_MAX }; enum condition_eq { CONDITION_TRUE, CONDITION_FALSE, CONDITION_EQ, CONDITION_NEQ, CONDITION_GR, CONDITION_LS, CONDITION_GRE, CONDITION_LSE }; struct cons {float mul; int off;}; struct var {unsigned comp; int attr;}; struct function { int eq; struct var dst; struct var src; struct cons cons; }; struct constraint { struct function self; struct function cond; enum attributes anch; }; /* fold */ enum layout_type { RETAINED, IMMEDIATE }; enum action_id { ACTION_MKCOMP, ACTION_MKCON, ACTION_LNKNODE, ACTION_CUSTOM, }; struct common {int type, next;}; union action { struct common com; struct {struct common _; unsigned id; struct definition d; addr usr;} mkcomp; struct {struct common _; struct constraint con;} mkcon; struct {struct common _; unsigned child, parent;} lnknode; struct {struct common _; unsigned id; int align, size, off;} custom; }; struct reducer { int mode; int max_com, max_con; int max_ext, custom; void *buf; int sz, cap; }; /* extension */ struct extinfo {const char *type; unsigned id; int size, align;}; struct extension {struct extinfo info; addr addr;}; struct extdef { struct extinfo info; commit_f commit; link_f link; }; /* commit */ struct commit { const char *con, *def; const char *tree, *ext; const char *comp, *buffer; const char *layout; int cnt; const struct extlnk { const char *name; const struct extdef *def; } *ext_list; }; /* layout */ struct layout { int initialized; unsigned *buffer, *tbl; struct component *comp; const struct definition *def; const struct node *tree; const struct constraint *con; const struct extension *ext; int comp_cnt, con_cnt; int ext_cnt, tbl_cnt; int requested; int custom; }; /* context */ #define MAX_COMPONENT_DEPTH 32 struct context { struct reducer red; struct layout root; struct layout *layout; unsigned cur, stk[MAX_COMPONENT_DEPTH]; unsigned active; unsigned origin; unsigned hot; }; /* context */ api void begin(struct context*, struct layout*, enum layout_type, void*, int, struct surface*); api void end(struct context*); api void update(struct context*, XEvent*); api void blueprint(struct layout*, struct context*); api void paint(struct context*,struct layout*); api void draw(struct context*, struct layout*, unsigned root); api void clear(struct context*); #define push(ctx,id) (ctx)->stk[++(ctx)->cur] = (id) #define peek(ctx) (ctx)->stk[(ctx)->cur] #define pop(ctx) (ctx)->cur = max((ctx)->cur-1,0); /* layout */ api void layouting(struct layout*); api void reorder(struct layout*, struct component*); api void reposit(FILE*, in struct layout*, const struct commit*, const char *tab); api inline unsigned lookup(const struct layout*, unsigned id); #define find(ui,id) ((ui->tbl)?lookup(ui,id):id) #define map(ui,t,e) for((e)=(ui)->ext;(e)<(ui)->ext+(ui)->ext_cnt;++(e)) if((e)->info.id==(t)) #define apply(ui,t,f,u) for(const struct extension *_=(ui)->ext;(_)<(ui)->ext+(ui)->ext_cnt;++(_)) if((_)->info.id==(t)) f(u,(void*)_->addr) /* fold */ api void reducer_begin(struct reducer*, enum layout_type, void *mem, int sz); api void reducer_cons(struct reducer*, union action*, in void *data, int sz, int ualign); api void reducer_push(struct reducer*, in struct layout*); #define mkcomp(r,ID,def,user) reducer_cons(r,&(union action){.mkcomp={.id=ID,.h={.type=ACTION_MKCOMP},.d=def,.usr=user}},0,0,0) #define mkcon(r,c) reducer_cons(r,&(union action){.mkcon={._={.type=ACTION_MKCON},.con=c}},0,0,0) #define lnknode(r,c,p) reducer_cons(r,&(union action){.lnknode={._={.type=ACTION_LNKNODE},.child=c,.parent=p}},0,0,0) #define reducer_add(r,t,p,s,a) reducer_cons(r,&(union action){.custom={._={.type=ACTION_CUSTOM},.id=t}},p,s,a) api void reducer_end(struct reducer*, in struct layout*, out int *mem); api void fold(out struct layout**, in struct reducer*, in struct layout*, out void *mem, const struct extdef**, int cnt); /* component */ api inline struct component* component_parent(struct layout*, unsigned id); api void adjust(struct context*, struct layout*, struct component*, XEvent*, void*); api void dispatch(struct component*,struct context*, struct layout*, XEvent*); #define DECLARATION_BEGIN(name) enum name {__##name##_ROOT_, #define DECLARATION_END }; /* bindings */ #define slot_con(i,f) *(i) = (f) #define bind_set(d,v) (struct interaction){INTERACTION_SET, .dst = d, .src = {.i = v}} #define bind_toggle(d) (struct interaction){INTERACTION_NOT, .dst = d} #define bind_enable(d,v) (struct interaction){INTERACTION_ENABLE, .dst = d, .src = {.f = v}} #define bind_disable(d,v) (struct interaction){INTERACTION_DISABLE, .dst = d, .src = {.f = v}} #define bind_drag_x(d) (struct interaction){INTERACTION_DRAG_X, .dst = d} #define bind_drag_y(d) (struct interaction){INTERACTION_DRAG_Y, .dst = d} #define bind_signal(d,u) (struct interaction){INTERACTION_SIGNAL, .dst = (void*)(addr)u, .src = {.s = d}} #endif /* UI_INCLUDED */ #include "ui.h" #include "draw.h" #include <assert.h> @@ -50,12 +332,12 @@ solve(struct component *c, int lo, int hi, c->attr[center] = c->attr[lo] + (c->attr[len]/2); c->attr[len] = max(c->attr[len], 0); } api inline unsigned parent(struct layout *ui, unsigned id) { const struct node *n = ui->tree + id; if (n->parent != n->id) return n->parent; return 0; } api void @@ -92,7 +374,7 @@ setup(struct component *c, const struct definition *d, struct surface *s) c->attr[ACT] = true; if (d->flags & PAINTABLE) c->surf = surf_mk(s->dpy, s->root, s->scrn, c->attr[W], c->attr[H]); if (d->flags & IS_MOVABLE) slot_con(&c->slot.dragged, bind_signal(adjust, 0)); } intern inline int @@ -154,7 +436,7 @@ at(const struct layout *ui, const struct component *c, int *x, int *y) unsigned tbl[MAX_NODES_PER_NODE]; const struct node *n = ui->tree + find(ui,id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[find(ui,n->sub[i])].zorder] = n->sub[i]; *x += c->off.x; *y += c->off.y; for (int i = n->cnt-1; i >= 0; --i) { @@ -170,13 +452,11 @@ reorder(struct layout *ui, struct component *c) { const struct node *n = ui->tree + find(ui,c->id); while (n->parent != n->id) { struct component *p = ui->comp + find(ui,parent(ui,c->id)); if (p->flags & STATIC) goto nxt; n = ui->tree + find(ui,p->id); for (int i = 0; i < n->cnt; ++i) { struct component *sub = ui->comp + find(ui,n->sub[i]); if (sub->flags & BACKGROUND) continue; if (sub->zorder > c->zorder) sub->zorder--; @@ -187,12 +467,11 @@ reorder(struct layout *ui, struct component *c) return; } api inline void dispatch(struct component *c, struct context *ctx, struct layout *ui, XEvent *e) { do if (ui->def[c->id].handle) if (ui->def[c->id].handle(ctx,ui,c,e)) break; while ((c = ui->comp + parent(ui,c->id))); } intern void interact(struct context *ctx, struct layout *ui, struct component *c, @@ -247,7 +526,7 @@ draw(struct context *ctx, struct layout *ui, unsigned root_id) if (!c->attr[ACT] || ((c->flags & LAYER) && (c->id != root_id))) continue; const struct node *n = ui->tree + find(ui, c->id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[find(ui,n->sub[i])].zorder] = n->sub[i]; for (int i = n->cnt-1; i >= 0; --i) stk[head++] = tbl[i]; } @@ -362,51 +641,50 @@ update(struct context *ctx, XEvent *e) } break;} } api void reducer_begin(struct reducer *r, enum layout_type type, void *mem, int sz) { r->mode = type; r->buf = mem; r->cap = sz; r->max_com = r->max_con = 0; r->max_ext = r->custom = r->sz = 0; } api void reducer_cons(struct reducer *r, union action *a, const void *dat, int sz, int align) { /* calculate buffer offset for current action, next action and user data */ assert(r->sz + szof(union action) + sz + align + alignof(union action) < r->cap); char *end = (char*)r->buf + r->sz; char *usr = align(end + szof(union action), align); char *nxt = end + r->sz + szof(union action) + sz + align; a->com.next = (int)((char*)(align(nxt, alignof(union action))) - end); if (ACTION_CUSTOM == a->com.type) { r->custom = sz + a->custom.align; a->custom.off = (int)(usr - end); a->custom.align = align; a->custom.size = sz; r->max_ext++; } else if (ACTION_MKCOMP == a->com.type) { r->max_com++; } else if (ACTION_MKCON == a->com.type) r->max_con++; /* copy action and userdata to buffer */ copy(end, a, szof(union action)); copy(usr, dat, sz); r->sz += a->com.next; } api void reducer_push(struct reducer *r, in struct layout *ui) { for (int i = 0; i < ui->comp_cnt; ++i) { mkcomp(r, p->id, p->def, 0); lnknode(r, p->id, p->parent); } for (int i = 0; i < ui->con_cnt; ++i) mkcon(r, p->con[j]); for (int i = 0; i < ui->ext_cnt; ++i) reducer_add(r,t,p,s,a) } api void reducer_end(struct reducer *r, in struct layout *ui, out int *mem) @@ -418,7 +696,7 @@ reducer_end(struct reducer *r, in struct layout *ui, out int *mem) *mem += r->max_con * szof(struct constraint); *mem += r->max_ext * szof(struct extension); *mem += r->max_com * szof(struct component); *mem += (r->max_com+1) * szof(int) * ((r->mode == RETAINED) ?1:3); *mem += szof(struct layout) + alignof(struct layout); *mem += alignof(struct component) + alignof(struct definition); *mem += alignof(struct constraint) + alignof(struct extension); @@ -432,13 +710,11 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, struct node *tree; struct definition *def; struct constraint *con; struct extension *ext; /* I.) setup layout in memory block */ struct layout *res = align(mem, alignof(struct layout)); if (r->mode == RETAINED) { res->tbl_cnt = 2 * r->max_com; res->tbl = align(res+1, alignof(int)); res->buffer = res->tbl + res->tbl_cnt; @@ -453,7 +729,7 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, res->con_cnt = ui->con_cnt; res->ext_cnt = ui->ext_cnt; res->initialized = True; void *custom = ext + r->max_ext; *ret = res; /* II.) copy old state */ @@ -462,59 +738,61 @@ fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, copy(tree, ui->tree, szof(struct node)*ui->comp_cnt); copy(con, ui->con, szof(struct constraint)*ui->con_cnt); copy(ext, ui->ext, szof(struct extension)*ui->ext_cnt); for (int i = 0; r->mode == IMMEDIATE && i < ui->comp_cnt; ++i) insert(res->tbl, res->tbl_cnt, ui->comp[i].id, (unsigned)i); for (int i = 0; i < ui->ext_cnt; ++i) { ext[i] = ui->ext[i]; ext[i].addr = (addr)align(custom, ext[i].info.align); copy((void*)ext[i].addr, (void*)ui->ext[i].addr, ext[i].info.size); custom = (char*)ext[i].addr + ext[i].info.size; } /* III.) add new state */ char *end = (char*)r->buf + r->sz; for (union action *a = r->buf; (char*)a < end; a = (void*)((char*)a + a->com.next)) { if (ACTION_MKCOMP == a->com.type) { const unsigned id = a->mkcomp.id; const int index = res->comp_cnt++; ui->comp[index].id = tree[index].id = id; ui->comp[index].usr = a->mkcomp.usr; def[index] = a->mkcomp.d; if (r->mode == IMMEDIATE) insert(res->tbl, res->tbl_cnt, id, (unsigned)index); setup(ui->comp + id, def + id, ui->comp[0].surf); } else if (ACTION_MKCON == a->com.type) { con[res->con_cnt++] = a->mkcon.con; } else if (ACTION_LNKNODE == a->com.type) { struct node *n = tree + a->lnknode.parent; n->sub[n->cnt] = a->lnknode.child; res->comp[a->lnknode.child].zorder = n->cnt++; } else if (ACTION_CUSTOM == a->com.type) { const void *obj = (const void*)((const char*)a + a->custom.off); char *dst = align(custom, a->custom.align); copy(dst, obj, a->custom.size); custom = dst + a->custom.size; ext[res->ext_cnt].info.id = a->custom.id; ext[res->ext_cnt].info.size = a->custom.size; ext[res->ext_cnt].info.align = a->custom.align; ext[res->ext_cnt++].addr = (addr)dst; } } /* IV.) setup extension state */ for (int i = 0; i < cnt; ++i) { const struct extension *e = 0; map(ui, ed[i]->info.id, e) ed[i]->link(res, (void*)e->addr); } } api void reposit(FILE *fp, in struct layout *ui, const struct commit *com, const char *tab) { tab = (!tab) ? " ": tab; const char *attrs[] = {"0","ACT","L","T","R","B","W","H","CX","CY"}; const char *cons[] = {"CONSTRAINT_CPY", "CONSTRAINT_SET", "CONSTRAINT_MIN", "CONSTRAINT_MAX"}; fprintf(fp,"global const struct constraint %s[] = {\n", com->con); for (int i = 0; i < ui->con_cnt; ++i) { const struct constraint *c = ui->con + i; fprintf(fp, "%s{{.eq = %s, .dst = {%u,%s}, .src = {%u,%s}, .cons = {.mul = %.2ff, .off = %d}}, .anch = %s},\n", tab,cons[c->self.eq], c->self.dst.comp, attrs[c->self.dst.attr], c->self.src.comp, attrs[c->self.src.attr], (double)c->self.cons.mul, c->self.cons.off, attrs[c->anch]); } fputs("};\n", fp); fprintf(fp, "global const struct definition %s[] = {\n", com->def); @@ -534,55 +812,47 @@ reposit(FILE *fp, in struct layout *ui, const struct commit *com) if (d->flags & IS_MOVABLE_Y) {copy(buf+n, "|MOVABLE_Y",15); n += 15;} buf[n] = 0; fprintf(fp, "%s{TBL(%s,%s,%s), .sz={%d,%d,%d,%d}, .flags = %s},\n", tab,d->i, d->p, d->b, d->sz.x, d->sz.y, d->sz.w, d->sz.h, buf); } fputs("};\n", fp); fprintf(fp, "global const struct node %s[] = {\n", com->tree); for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; fprintf(fp, "%s{.id = %u, .parent = %u, .cnt = %d, .sub = {",tab, n->id, n->parent, n->cnt); for (int j = 0; j < n->cnt; ++j) fprintf(fp, "%u,", n->sub[j]); if (!n->cnt) fputs("0", fp); fputs("}},\n", fp); } fputs("};\n", fp); for (int i = 0; i < com->cnt; ++i) { const struct extlnk *lnk = com->ext_list + i; fprintf(fp, "global const %s %s[] = {", lnk->def->info.type, lnk->name); apply(ui, lnk->def->info.id, lnk->def->commit, fp); fputs("};\n",fp); } fprintf(fp, "global const struct extension %s[] = {", com->ext); for (int i = 0; i < com->cnt; ++i) { const struct extension *e = 0; int cnt = 0; const struct extlnk *lnk = com->ext_list + i; map(ui, lnk->def->info.id, e) fprintf(fp, "\n%s{.id = %d, .size = %d, .align = %d, .addr = (addr)&%s[%u]},", tab,e->info.id, e->info.size, e->info.align, lnk->name, cnt++); } if (!ui->ext_cnt) fputs("0", fp); fputs("};\n",fp); fprintf(fp, "global int %s;\nglobal struct component %s;\n", com->buffer,com->comp); fprintf(fp, "global struct layout %s = {\n", com->layout); fprintf(fp, "%s.comp_cnt = cntof(%s),\n%s.con_cnt = cntof(%s),\n", tab,com->def,tab,com->con); fprintf(fp, "%s.ext_cnt = cntof(%s)\n,%s.buffer = %s\n",tab,com->ext,tab,com->buffer); fprintf(fp, "%s.comp = %s,\n%s.tree = %s,\n", tab,com->comp, tab, com->tree); fprintf(fp, "%s.def = %s,\n%s.con = %s,\n%s.ext = %s,\n};\n",tab,com->def,tab,com->con,tab,com->ext); } api void begin(struct context *ctx, struct layout *ui, enum layout_type type, void *mem, int siz, struct surface *scrn) { ctx->layout = ui; ctx->cur = ctx->stk[0] = 0; reducer_begin(&ctx->red, type, mem, siz); ui->comp[COMPONENT_ROOT].surf = scrn; if (!ui->initialized) { ui->initialized = True; @@ -597,14 +867,15 @@ begin(struct context *ctx, struct layout *ui, void *mem, int siz, struct surface api void end(struct context *ctx) { struct layout *ui = ctx->layout; reducer_end(&ctx->red, ui, &ui->requested); ctx->layout = &ctx->root; } api void clear(struct context *ctx) { struct layout *ui = ctx->layout; for (int i = 1; i < ui->comp_cnt; ++i) if (ui->comp[i].surf) surf_del(ui->comp[i].surf); } -
vurtun revised this gist
May 2, 2017 . No changes.There are no files selected for viewing
-
vurtun renamed this gist
May 2, 2017 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
vurtun revised this gist
May 2, 2017 . 1 changed file with 323 additions and 568 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,287 +1,17 @@ #include "ui.h" #include "draw.h" #include <assert.h> intern inline int ceili(float x) { if (x >= 0) return (int)x; int t = (int)x; float r = x - (float)t; return (r > 0.0f) ? t+1: t; } intern inline void solve(struct component *c, int lo, int hi, int center, int len, int mod, int an) { if (mod == lo) { @@ -318,538 +48,563 @@ qk_solve(struct qk_component *c, int lo, int hi, } } c->attr[center] = c->attr[lo] + (c->attr[len]/2); c->attr[len] = max(c->attr[len], 0); } api inline struct component* component_parent(struct layout *ui, unsigned id) { const struct node *n = ui->tree + id; if (n->parent != n->id) return ui->comp + n->parent; return 0; } api void adjust(struct context *ctx, struct layout *ui, struct component *c, XEvent *e, void *usr) { unused(ctx,ui,usr); if (c->flags & IS_MOVABLE_X) c->attr[CX] += e->xmotion.x_root; if (c->flags & IS_MOVABLE_Y) c->attr[CY] += e->xmotion.y_root; solve(c, L, R, CX, W, L, W); solve(c, T, B, CY, H, T, H); blueprint(ui, ctx); layouting(ui); } intern inline void build(struct component *c, int x, int y, int w, int h) { c->attr[L] = x; c->attr[T] = y; c->attr[W] = max(w,0); c->attr[H] = max(h,0); c->attr[R] = x+w; c->attr[B] = y+h; c->attr[CX] = x+(w/2); c->attr[CY] = y+(h/2); } intern void setup(struct component *c, const struct definition *d, struct surface *s) { c->flags = d->flags; c->zorder = d->zorder; build(c, d->sz.x, d->sz.y, d->sz.w, d->sz.h); if (!(d->flags & HIDDEN)) c->attr[ACT] = true; if (d->flags & PAINTABLE) c->surf = surf_mk(s->dpy, s->root, s->scrn, c->attr[W], c->attr[H]); if ((d->flags & IS_MOVABLE)) slot_con(&c->slot.dragged, bind_signal(adjust, 0)); } intern inline int cond(const struct function *f, int d, int src) { float s = (float)src; if (f->eq == CONDITION_TRUE) return 1; else if (f->eq == CONDITION_FALSE) return 0; else if (f->eq == CONDITION_EQ) return d == ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == CONDITION_NEQ) return d != ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == CONDITION_GR) return d > ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == CONDITION_LS) return d < ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == CONDITION_GRE) return d >= ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == CONDITION_LSE) return d <= ceili(f->cons.mul*s)+f->cons.off; return 0; } intern inline void eval(const struct function *f, int *d, int src) { float s = (float)src; if (f->eq == CONSTRAINT_CPY) *d = src; else if (f->eq == CONSTRAINT_SET) *d = ceili(f->cons.mul*s)+f->cons.off; else if (f->eq == CONSTRAINT_MIN) *d = min(*d, ceili(f->cons.mul*s)+f->cons.off); else if (f->eq == CONSTRAINT_MAX) *d = max(*d, ceili(f->cons.mul*s)+f->cons.off); } intern void insert(unsigned *tbl, int tbl_cnt, unsigned key, unsigned val) { unsigned begin = key % (unsigned)tbl_cnt, id = begin; do {unsigned index = tbl[id]; if ((id == 0 && val != 0) || index) continue; tbl[id] = val; return; } while ((++id % (unsigned)tbl_cnt) != begin); } api unsigned lookup(const struct layout *ui, unsigned id) { assert(ui->tbl && "use 'find' instead"); unsigned begin = id % (unsigned)ui->tbl_cnt, index = begin; do {struct component *c = ui->comp + ui->tbl[index]; if (!c->id) break; if (c->id == id) return index; } while ((++index % (unsigned)ui->tbl_cnt) != begin); return 0; } intern unsigned at(const struct layout *ui, const struct component *c, int *x, int *y) { loop:; unsigned id = c->id; unsigned tbl[MAX_NODES_PER_NODE]; const struct node *n = ui->tree + find(ui,id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[n->sub[i]].zorder] = n->sub[i]; *x += c->off.x; *y += c->off.y; for (int i = n->cnt-1; i >= 0; --i) { const struct component *sub = ui->comp + find(ui, tbl[i]); if (!sub->attr[ACT] || !(sub->flags & INTERACTIVE)) continue; if (inbox(*x, *y, sub->attr[L], sub->attr[T], sub->attr[W], sub->attr[H])) {c = sub; goto loop;} } return c->id; } api void reorder(struct layout *ui, struct component *c) { const struct node *n = ui->tree + find(ui,c->id); while (n->parent != n->id) { struct component *p; p = component_parent(ui, c->id); if (p->flags & STATIC) goto nxt; n = ui->tree + find(ui,p->id); for (int i = 0; i < n->cnt; ++i) { struct component *sub; sub = ui->comp + find(ui, n->sub[i]); if (sub->flags & BACKGROUND) continue; if (sub->zorder > c->zorder) sub->zorder--; } c->zorder = max(n->cnt-1, 0); nxt: c = p; } return; } api inline void dispatch(struct component *c, struct context *ctx, struct layout *ui, XEvent *e) { do if (ui->def[c->id].handle) if (ui->def[c->id].handle(ctx,ui,c,e)) break; while ((c = component_parent(ui,c->id))); } intern void interact(struct context *ctx, struct layout *ui, struct component *c, struct interaction *i, XEvent *e) { if (INTERACTION_SIGNAL == i->type) i->src.s(ctx, ui, c, e, i->dst); else if (INTERACTION_SET == i->type) {int *v = (int*)i->dst; *v = i->src.i;} else if (INTERACTION_ENABLE == i->type) {unsigned *v = (unsigned*)i->dst; *v |= i->src.f;} else if (INTERACTION_DISABLE == i->type) {unsigned *v = (unsigned*)i->dst; *v &= ~i->src.f;} else if (e->type == MotionNotify) { int *d = (int*)i->dst; *d += (i->type == INTERACTION_DRAG_X) ? e->xmotion.x_root: e->xmotion.y_root; } } api void paint(struct context *ctx, struct layout *ui) { for (int i = 0; i < ui->comp_cnt; ++i) { struct component *c = ui->comp + i; surf_resize(c->surf, c->attr[W], c->attr[H]); if (!(c->flags & PAINTABLE) || (c->flags & LAYER)) continue; if (ui->def[i].paint) ui->def[i].paint(ctx,ui,c); } } api void draw(struct context *ctx, struct layout *ui, unsigned root_id) { unsigned head = 0; unsigned *stk = ui->buffer; unsigned tbl[MAX_NODES_PER_NODE]; struct component *r = ui->comp + find(ui, root_id); stk[head++] = root_id; while (head > 0) { struct component *c = ui->comp + find(ui, stk[--head]); if (c->surf && c->attr[ACT] && c->id != root_id) { if ((c->flags & LAYER) && (c->flags & PAINTABLE)) { ui->buffer = stk + head; if (ui->def[c->id].paint) ui->def[c->id].paint(ctx,ui,c); } surf_blit(r->surf, c->surf, c->attr[L] - r->attr[L] - r->off.x, c->attr[T] - r->attr[T] - r->off.y, 0, 0, c->attr[W], c->attr[H]); } if (!c->attr[ACT] || ((c->flags & LAYER) && (c->id != root_id))) continue; const struct node *n = ui->tree + find(ui, c->id); for (int i = 0; i < n->cnt; ++i) tbl[ui->comp[n->sub[i]].zorder] = n->sub[i]; for (int i = n->cnt-1; i >= 0; --i) stk[head++] = tbl[i]; } ui->buffer = stk; } api void blueprint(struct layout *ui, struct context *ctx) { unsigned head = 0, tail = 1; unsigned *que = ui->buffer; que[tail] = COMPONENT_ROOT; while (head < tail) { const struct node *n; n = ui->tree + find(ui, que[++head]); for (int i = 0; i < n->cnt; ++i) que[++tail] = n->sub[i]; } for (unsigned i = tail; i > 0; --i) { const struct definition *d; struct component *c; d = ui->def + find(ui, que[i]); c = ui->comp + find(ui, que[i]); if (d->blueprint) d->blueprint(ctx, ui, c); } } api void layouting(struct layout *ui) { for (int i = 0; i < ui->con_cnt; ++i) { const struct constraint *con = ui->con + i; const struct function *co = &con->cond; struct component *cd, *cs, *d, *s; cd = ui->comp + find(ui, co->dst.comp); cs = ui->comp + find(ui, co->src.comp); d = ui->comp + find(ui, con->self.dst.comp); s = ui->comp + find(ui, con->self.src.comp); if (cond(co, cd->attr[co->dst.attr], cs->attr[co->src.attr])) { eval(&con->self, d->attr+con->self.dst.attr, s->attr[con->self.src.attr]); solve(d, L, R, CX, W, con->self.dst.attr, con->anch); solve(d, T, B, CY, H, con->self.dst.attr, con->anch); } } } api void update(struct context *ctx, XEvent *e) { struct layout *ui; ui = ctx->layout; switch (e->type) { default: { struct component *a; a = ui->comp + ctx->active; dispatch(a, ctx, ui, e); } break; case Expose: case ConfigureNotify: { /* resize event */ struct component *c = ui->comp + COMPONENT_ROOT; int w = (e->type == Expose) ? e->xexpose.width: e->xconfigure.width; int h = (e->type == Expose) ? e->xexpose.height: e->xconfigure.height; build(c, 0, 0, w, h); surf_resize(c->surf, w, h); blueprint(ctx->layout, ctx); layouting(ui); for (int i = 0; i < ui->comp_cnt; ++i) dispatch(ui->comp + i,ctx,ui,e); } break; case MotionNotify: { /* enter and leave event */ int mx = e->xmotion.x, my = e->xmotion.y; unsigned last_hot = ctx->hot; ctx->hot = at(ui, ui->comp, &e->xmotion.x, &e->xmotion.y); if (last_hot != ctx->hot) { struct component *prev = ui->comp + last_hot; struct component *cur = ui->comp + ctx->hot; e->xmotion.type = Leave; interact(ctx, ui, prev, &prev->slot.leave, e); dispatch(prev,ctx, ui, e); e->xmotion.type = Enter; interact(ctx, ui, cur, &cur->slot.enter, e); dispatch(cur,ctx, ui, e); e->xmotion.type = MotionNotify; } /* dragging event */ if (ctx->active == ctx->origin) { struct component *a = ui->comp + find(ui,ctx->active); interact(ctx,ui, a, &a->slot.dragged, e); e->xmotion.type = Drag; dispatch(a,ctx,ui,e); } e->xmotion.x = mx, e->xmotion.y = my; e->xmotion.type = MotionNotify; } break; case ButtonRelease: case ButtonPress: { int down = e->type == ButtonPress; ctx->active = (down) ? ctx->hot: ctx->active; ctx->origin = (down) ? ctx->hot: COMPONENT_ROOT; struct component *a = ui->comp + find(ui,ctx->active); if (e->xbutton.button == Button1 && down) { reorder(ui, a); interact(ctx,ui, a, &a->slot.left, e); } else if (e->xbutton.button == Button3 && down){ reorder(ui, a); interact(ctx,ui, a, &a->slot.right, e); } dispatch(a,ctx,ui,e); } break;} } api void reducer_begin(struct reducer *r, enum fold_mode mode, void *mem, int sz) { r->mode = mode; r->buf = mem; r->cap = sz; r->max_com = r->max_con = 0; r->max_ext = r->custom = r->sz = 0; } api void reducer_cons(struct reducer *r, union action *a, const void *dat, int sz, int ualign) { storage const int align = alignof(union action); storage const int asz = szof(union action); assert((r->sz + asz + sz + ualign + align) < r->cap); char *end = (char*)r->buf + r->sz; char *nxt = align(end + r->sz + asz + sz + ualign, align); char *usr = align(end + asz, ualign); a->h.nxt = (int)(nxt - end); if (ACTION_CUSTOM == a->h.type) { r->custom = sz + a->custom.align; a->custom.off = (int)(usr - end); a->custom.align = ualign; a->custom.sz = sz; r->max_ext++; } else if (ACTION_MKCOMP == a->h.type) r->max_com++; else if (ACTION_MKCON == a->h.type) r->max_con++; copy(end, a, asz); copy(usr, dat, sz); r->sz += a->h.nxt; } api void reducer_push(struct reducer *r, in struct module *m, int cnt) { for (int i = 0; i < cnt; ++i) { const struct module *p = m + i; mkcomp(r, p->id, p->def, 0); lnknode(r, p->id, p->parent); for (int j = 0; j < p->cnt; ++j) mkcon(r, p->con[j]); } } api void reducer_end(struct reducer *r, in struct layout *ui, out int *mem) { r->max_ext += ui->ext_cnt; r->max_com += ui->comp_cnt; r->max_con += ui->con_cnt; *mem = r->max_com * szof(struct node); *mem += r->max_com * szof(struct definition); *mem += r->max_con * szof(struct constraint); *mem += r->max_ext * szof(struct extension); *mem += r->max_com * szof(struct component); *mem += (r->max_com+1) * szof(int) * ((r->mode == FOLD_RETAINED) ?1:3); *mem += szof(struct layout) + alignof(struct layout); *mem += alignof(struct component) + alignof(struct definition); *mem += alignof(struct constraint) + alignof(struct extension); *mem += alignof(struct node) + alignof(int); *mem += ui->custom + r->custom; } api void fold(out struct layout **ret, in struct reducer *r, in struct layout *ui, void *mem, const struct extdef **ed, int cnt) { struct node *tree; struct definition *def; struct constraint *con; struct layout *res; struct extension *ext; void *custom; /* I.) setup layout in memory block */ res = align(mem, alignof(struct layout)); if (r->mode == FOLD_RETAINED) { res->tbl_cnt = 2 * r->max_com; res->tbl = align(res+1, alignof(int)); res->buffer = res->tbl + res->tbl_cnt; } else res->buffer = align(res+1, alignof(int)); res->comp = align(res->buffer + r->max_com+1, alignof(struct component)); res->def = def = align(res->comp + r->max_com, alignof(struct definition)); res->tree = tree = align(res->def + r->max_com, alignof(struct node)); res->con = con = align(res->tree + r->max_com, alignof(struct constraint)); res->ext = ext = align(res->con + r->max_con, alignof(struct extension)); res->custom = ui->custom + r->custom; res->comp_cnt = ui->con_cnt; res->con_cnt = ui->con_cnt; res->ext_cnt = ui->ext_cnt; res->initialized = True; custom = ext + r->max_ext; *ret = res; /* II.) copy old state */ copy(res->comp, ui->comp, szof(struct component)*ui->comp_cnt); copy(def, ui->def, szof(struct definition)*ui->comp_cnt); copy(tree, ui->tree, szof(struct node)*ui->comp_cnt); copy(con, ui->con, szof(struct constraint)*ui->con_cnt); copy(ext, ui->ext, szof(struct extension)*ui->ext_cnt); for (int i = 0; r->mode == FOLD_IMMEDIATE && i < ui->comp_cnt; ++i) insert(res->tbl, res->tbl_cnt, ui->comp[i].id, (unsigned)i); for (int i = 0; i < ui->ext_cnt; ++i) { ext[i] = ui->ext[i]; ext[i].addr = (addr)align(custom, ext[i].info.algn); copy((void*)ext[i].addr, (void*)ui->ext[i].addr, ext[i].info.sz); custom = (char*)ext[i].addr + ext[i].info.sz; } /* III.) add new state */ char *end = (char*)r->buf + r->sz; for (union action *a = r->buf; (char*)a < end; a = (void*)((char*)a + a->h.nxt)) { if (ACTION_MKCOMP == a->h.type) { const unsigned id = a->mkcomp.id; const int index = res->comp_cnt++; ui->comp[index].id = tree[index].id = id; ui->comp[index].usr = a->mkcomp.usr; def[index] = a->mkcomp.d; if (r->mode == FOLD_IMMEDIATE) insert(res->tbl, res->tbl_cnt, id, (unsigned)index); setup(ui->comp + id, def + id, ui->comp[0].surf); } else if (ACTION_MKCON == a->h.type) { con[res->con_cnt++] = a->mkcon.con; } else if (ACTION_LNKNODE == a->h.type) { struct node *n = tree + a->lnknode.parent; n->sub[n->cnt] = a->lnknode.child; res->comp[a->lnknode.child].zorder = n->cnt++; } else if (ACTION_CUSTOM == a->h.type) { const void *obj = (const void*)((const char*)a + a->custom.off); char *dst = align(custom, a->custom.align); copy(dst, obj, a->custom.sz); custom = dst + a->custom.sz; ext[res->ext_cnt].info.sz = a->custom.sz; ext[res->ext_cnt].info.type = a->custom.type; ext[res->ext_cnt].info.algn = a->custom.align; ext[res->ext_cnt++].addr = (addr)dst; } } /* IV.) setup extension state */ for (int i = 0; i < cnt; ++i) { const struct extension *e = 0; map(ui, ed[i]->info.type, e) ed[i]->link(res, (void*)e->addr); } } api void reposit(FILE *fp, in struct layout *ui, const struct commit *com) { const char *attrs[] = {"0","ACT","L","T","R","B","W","H","CX","CY"}; const char *cons[] = {"CONSTRAINT_CPY", "CONSTRAINT_SET", "CONSTRAINT_MIN", "CONSTRAINT_MAX"}; fprintf(fp,"global const struct constraint %s[] = {\n", com->con); for (int i = 0; i < ui->con_cnt; ++i) { const struct constraint *c = ui->con + i; fprintf(fp, " {{.eq = %s, .dst = {%u,%s}, .src = {%u,%s}, .cons = {.mul = %.2ff, .off = %d}}, .anch = %s},\n", cons[c->self.eq], c->self.dst.comp, attrs[c->self.dst.attr], c->self.src.comp, attrs[c->self.src.attr], (double)c->self.cons.mul, c->self.cons.off, attrs[c->anch]); } fputs("};\n", fp); fprintf(fp, "global const struct definition %s[] = {\n", com->def); for (int i = 0; i < ui->comp_cnt; ++i) { const struct definition *d = ui->def + i; char buf[128]; int n = 0; buf[n++] = '0'; if (d->flags & HIDDEN) {copy(buf+n, "|HIDDEN",12); n += 12;} if (d->flags & INTERACTIVE) {copy(buf+n, "|INTERACTABLE",18); n += 18;} if (d->flags & PAINTABLE) {copy(buf+n, "|PAINTABLE",15); n += 15;} if (d->flags & LAYER) {copy(buf+n, "|LAYER",11); n += 11;} if (d->flags & IS_MOVABLE_X) {copy(buf+n, "|MOVABLE_X",15); n += 15;} if (d->flags & IS_MOVABLE_Y) {copy(buf+n, "|MOVABLE_Y",15); n += 15;} buf[n] = 0; fprintf(fp, " {TBL(%s,%s,%s), .sz={%d,%d,%d,%d}, .flags = %s},\n", d->i, d->p, d->b, d->sz.x, d->sz.y, d->sz.w, d->sz.h, buf); } fputs("};\n", fp); fprintf(fp, "global const struct node %s[] = {\n", com->tree); for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; fprintf(fp, " {.id = %u, .parent = %u, .cnt = %d, .sub = {", n->id, n->parent, n->cnt); for (int j = 0; j < n->cnt; ++j) fprintf(fp, "%u,", n->sub[j]); if (!n->cnt) fputs("0", fp); fputs("}},\n", fp); } fputs("};\n", fp); for (int i = 0; i < com->cnt; ++i) { const struct extlnk *lnk = com->ext_list + i; fprintf(fp, "global const %s %s[] = {", lnk->type, lnk->name); apply(ui, lnk->def->info.type, lnk->def->commit, fp); fputs("};\n",fp); } fprintf(fp, "global const struct extension %s[] = {", com->ext); for (int i = 0; i < com->cnt; ++i) { const struct extension *e = 0; int cnt = 0; const struct extlnk *lnk = com->ext_list + i; map(ui, lnk->def->info.type, e) fprintf(fp, "\n {.type = %d, .sz = %d, .algn = %d, .addr = (addr)&%s[%u]},", e->info.type, e->info.sz, e->info.algn, lnk->type, cnt++); } if (!ui->ext_cnt) fputs("0", fp); fputs("};\n",fp); fprintf(fp, "global int %s;\n", com->buffer); fprintf(fp, "global struct component %s;\n", com->comp); fprintf(fp, "global struct layout %s = {\n", com->layout); fprintf(fp, " .comp_cnt = cntof(%s),\n", com->def); fprintf(fp, " .con_cnt = cntof(%s),\n", com->con); fprintf(fp, " .ext_cnt = cntof(%s),\n", com->ext); fprintf(fp, " .buffer = %s\n", com->buffer); fprintf(fp, " .comp = %s,\n", com->comp); fprintf(fp, " .tree = %s,\n", com->tree); fprintf(fp, " .def = %s,\n", com->def); fprintf(fp, " .con = %s,\n", com->con); fprintf(fp, " .ext = %s,\n", com->ext); fputs("};\n",fp); } api void begin(struct context *ctx, struct layout *ui, void *mem, int siz, struct surface *scrn) { ctx->layout = ui; ctx->buf.mem = mem; ctx->buf.siz = siz; ctx->cur = ctx->stk[0] = 0; ui->comp[COMPONENT_ROOT].surf = scrn; if (!ui->initialized) { ui->initialized = True; for (int i = 0; i < ui->comp_cnt; ++i) { const struct node *n = ui->tree + i; struct component *c = ui->comp + i; c->id = (unsigned int)n->id; setup(c, ui->def + i, scrn); } } } api void end(struct context *ctx) { ctx->layout = 0; } api void clear(struct context *ctx) { struct layout *ui = ctx->layout; for (int i = COMPONENT_ROOT+1; i < ui->comp_cnt; ++i) { if (ui->comp[i].surf) surf_del(ui->comp[i].surf); } }
NewerOlder