#include "lib9.h"#include "interp.h"#include "isa.h"#include "runt.h"#include "draw.h"#include "tk.h"#include "tkmod.h"#include "pool.h"#include "drawif.h"#include "keyboard.h"#include "raise.h"#include "kernel.h" extern void tkfreetop(Heap*, int);Type* fakeTkTop;static uchar TktypeMap[] = Tk_Toplevel_map;int tkstylus;void (*tkwiretap)(void*, char*, char*, void*, Rectangle*); static void tktopimagedptr(TkTop*, Draw_Image*);static char*tkputwinimage(Tk*, Draw_Image*, int); static voidlockctxt(TkCtxt *ctxt){ libqlock(ctxt->lock);} static voidunlockctxt(TkCtxt *ctxt){ libqunlock(ctxt->lock);} static voidtkmarktop(Type *t, void *vw){ Heap *h; TkVar *v; TkPanelimage *di; TkTop *top; Tk *w, *next; TkWin *tkw; markheap(t, vw); top = vw; // XXX do we need to lock context here?? for(v = top->vars; v; v = v->link) { if(v->type == TkVchan) { h = D2H(v->value); Setmark(h); } } for (di = top->panelimages; di != nil; di = di->link) { h = D2H(di->image); Setmark(h); } for(w = top->windows; w != nil; w = next){ tkw = TKobj(TkWin, w); if(tkw->image != nil){ h = D2H(tkw->di); Setmark(h); } next = tkw->next; }} voidtkmodinit(void){ builtinmod("$Tk", Tkmodtab, Tkmodlen); fmtinstall('v', tkeventfmt); /* XXX */ fakeTkTop = dtype(tkfreetop, sizeof(TkTop), TktypeMap, sizeof(TktypeMap)); fakeTkTop->mark = tkmarktop; tksorttable();} voidTk_toplevel(void *a){ Tk *tk; Heap *h; TkTop *t; TkWin *tkw; TkCtxt *ctxt; Display *disp; F_Tk_toplevel *f = a; void *r; r = *f->ret; *f->ret = H; destroy(r); disp = checkdisplay(f->d); h = heapz(fakeTkTop); t = H2D(TkTop*, h); poolimmutable(h); t->dd = f->d; D2H(t->dd)->ref++; t->execdepth = -1; t->display = disp; tk = tknewobj(t, TKframe, sizeof(Tk)+sizeof(TkWin)); if(tk == nil) { destroy(t); return; } tk->act.x = 0; tk->act.y = 0; tk->act.width = 1; /* XXX why not zero? */ tk->act.height = 1; tk->flag |= Tkwindow; tkw = TKobj(TkWin, tk); tkw->di = H; tktopopt(tk, string2c(f->arg)); tk->geom = tkmoveresize; tk->name = tkmkname("."); if(tk->name == nil) { tkfreeobj(tk); destroy(t); return; } ctxt = tknewctxt(disp); if(ctxt == nil) { tkfreeobj(tk); destroy(t); return; } t->ctxt = ctxt; t->screenr = disp->image->r; tkw->next = t->windows; t->windows = tk; t->root = tk; Setmark(h); poolmutable(h); t->wreq = cnewc(&Tptr, movp, 8); *f->ret = (Tk_Toplevel*)t;} voidTk_cmd(void *a){ TkTop *t; char *val, *e; F_Tk_cmd *f = a; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop) { retstr(TkNotop, f->ret); return; } lockctxt(t->ctxt); val = nil; e = tkexec(t, string2c(f->arg), &val); unlockctxt(t->ctxt); if(e == TkNomem){ free(val); error(exNomem); /* what about f->ret? */ } if(e != nil && t->errx[0] != '\0'){ char *s = tkerrstr(t, e); retstr(s, f->ret); free(s); } else retstr(e == nil ? val : e, f->ret); if(tkwiretap != nil) tkwiretap(t, string2c(f->arg), val, nil, nil); free(val);} voidTk_color(void *fp){ ulong rgba; F_Tk_color *f = fp; if(tkparsecolor(string2c(f->col), &rgba) != nil) *f->ret = DNotacolor; else *f->ret = rgba;} voidTk_rect(void *fp){ F_Tk_rect *f = fp; Tk *tk; TkTop *t; Rectangle r; TkGeom *g; Point o; int bd, flags; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop){ *(Rectangle *)f->ret = ZR; return; } lockctxt(t->ctxt); tk = tklook(t, string2c(f->name), 0); if(tk == nil){ *(Rectangle *)f->ret = ZR; unlockctxt(t->ctxt); return; } o = tkposn(tk); flags = f->flags; if(flags & Tk_Local) o = subpt(o, tkposn(tk->env->top->root)); bd = tk->borderwidth; g = (flags & Tk_Required) ? &tk->req : &tk->act; if(flags & Tk_Border){ r.min = o; r.max.x = r.min.x + g->width + bd + bd; r.max.y = r.min.y + g->height + bd + bd; } else { r.min.x = o.x + bd; r.min.y = o.y + bd; r.max.x = r.min.x + g->width; r.max.y = r.min.y + g->height; } *(Rectangle *)f->ret = r; unlockctxt(t->ctxt);} inttkdescendant(Tk *p, Tk *c){ int n; if(c == nil || p->env->top != c->env->top) return 0; if (p->name != nil && c->name != nil) { n = strlen(p->name->name); if(strncmp(p->name->name, c->name->name, n) == 0) return 1; } return 0;} voidtkenterleave(TkTop *t){ Tk *fw, *ent; TkMouse m; TkTop *t1, *t2; TkCtxt *c; c = t->ctxt; m = c->mstate; if (c->mgrab != nil && (c->mgrab->flag & Tknograb)) { fw = tkfindfocus(t, m.x, m.y, 1); if (fw != c->mgrab && fw != nil && (fw->flag & Tknograb) == 0) fw = nil; } else if (c->focused) { fw = tkfindfocus(t, m.x, m.y, 1); if (fw != c->mfocus) fw = nil; } else if (c->mgrab != nil) { fw = tkfindfocus(t, m.x, m.y, 1); if (fw != nil) { if (!tkdescendant(c->mgrab, fw) && !(fw->flag & c->mgrab->flag & Tknograb)) fw = nil; } } else if (m.b == 0) fw = tkfindfocus(t, m.x, m.y, 0); else if (tkfindfocus(t, m.x, m.y, 1) == c->entered) return; else fw = nil; if (c->entered == fw) return; t1 = t2 = nil; if (c->entered != nil) { ent = c->entered; t1 = ent->env->top; c->entered = nil; tkdeliver(ent, TkLeave, nil); } if (fw != nil) { t2 = fw->env->top; c->entered = fw; tkdeliver(fw, TkEnter, &m); } if (t1 != nil) tkupdate(t1); if (t2 != nil && t1 != t2) tkupdate(t2);} voidTk_pointer(void *a){ static int buttonr[] = {TkButton1R, TkButton2R, TkButton3R, TkButton4R, TkButton5R, TkButton6R}; static int buttonp[] = {TkButton1P, TkButton2P, TkButton3P, TkButton4P, TkButton5P, TkButton6P}; Tk *fw, *target, *dest, *ent; TkMouse m; TkCtxt *c; TkTop *t, *ot; int d, dtype, etype; F_Tk_pointer *f = a; int b, lastb, inside; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop) return; c = t->ctxt; /* ignore no-button-motion for emulated stylus input */ if(tkstylus && c->mstate.b == 0 && (f->p.buttons&0x1f)==0) return; lockctxt(c);//if (f->p.buttons != 0 || c->mstate.b != 0)//print("tkmouse %d [%d %d], focused %d[%s], grab %s, entered %s\n",// f->p.buttons, f->p.xy.x, f->p.xy.y, c->focused, tkname(c->mfocus), tkname(c->mgrab), tkname(c->entered)); /* * target is the widget that we're deliver the mouse event to. * inside is true if the mouse point is located inside target. */ inside = 1; if (c->mgrab != nil && (c->mgrab->flag & Tknograb)) { fw = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 1); if (fw != nil && (fw->flag & Tknograb)) target = fw; else { target = c->mgrab; inside = 0; } } else if (c->focused) { if (c->mfocus != nil) { fw = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 1); if (fw != c->mfocus) inside = 0; } target = c->mfocus; } else if (c->mgrab != nil && (c->mgrab->flag & Tkdisabled) == 0) { /* * XXX this isn't quite right, as perhaps we should do a tkinwindow() * (below the grab). * so that events to containers underneath the grab arrive * via the containers (as is usual) */ fw = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 1); if (fw != nil && tkdescendant(c->mgrab, fw)) target = fw; else { target = c->mgrab; inside = 0; } } else target = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 0); lastb = c->mstate.b; c->mstate.x = f->p.xy.x; c->mstate.y = f->p.xy.y; c->mstate.b = f->p.buttons & 0x1f; /* Just the buttons */ m = c->mstate; /* XXX if the mouse is being moved with the buttons held down * and we've no mfocus and no mgrab then ignore * the event as our original target has gone away (or never existed) */ if (lastb && m.b && !c->focused && c->mgrab == nil) target = nil; if (target != c->entered || (c->entered != nil && !inside)) { if (c->entered != nil) { fw = c->entered; c->entered = nil; tkdeliver(fw, TkLeave, nil); if (target == nil || fw->env->top != target->env->top) tkupdate(fw->env->top); } if (inside) { c->entered = target; tkdeliver(target, TkEnter, &m); } } dest = nil; if (target != nil) { etype = 0; dtype = 0; if(f->p.buttons & (1<<8)) /* Double */ dtype = TkDouble; d = lastb ^ m.b; if (d) { /* cancel any autorepeat, notifying existing client */ tkrepeat(nil, nil, nil, 0, 0); if (d & ~lastb & 1) /* button 1 potentially takes the focus */ tkdeliver(target, TkTakefocus|TkButton1P, &m); } for(b=0; b<nelem(buttonp); b++){ if(d & (1<<b)){ etype = buttonr[b]; if(m.b & (1<<b)) etype = buttonp[b]|dtype; dest = tkdeliver(target, etype, &m); } } if(tkstylus && m.b==0) { if ((ent = c->entered) != nil) { c->entered = nil; ot = ent->env->top; tkdeliver(ent, TkLeave, nil); if (ot != target->env->top) tkupdate(ot); } } else if(etype == 0) { etype = TkMotion; for(b = 0; b<nelem(buttonp); b++) if (m.b & (1<<b)) etype |= buttonp[b]; tkdeliver(target, etype, &m); } if (m.b != 0) { if (lastb == 0 && !c->focused) { /* (some deliver might have grabbed it...) */ if (dest == nil) dest = target; if ((dest->flag & Tknograb) == 0) { c->focused = 1; c->mfocus = dest; } } } else { c->focused = 0; c->mfocus = nil; if (lastb != 0) tkenterleave(t); } tkupdate(target->env->top); } else if (c->focused && m.b == 0) { c->focused = 0; tkenterleave(t); } unlockctxt(c);} voidTk_keyboard(void *a){ Tk *grab; TkTop *t; TkCtxt *c; F_Tk_keyboard *f = a; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop) return; c = t->ctxt; if (c == nil) return; lockctxt(c); if (c->tkmenu != nil) grab = c->tkmenu; else grab = c->tkkeygrab; if(grab == nil){ unlockctxt(c); return; } t = grab->env->top; tkdeliver(grab, TkKey|TKKEY(f->key), nil); tkupdate(t); unlockctxt(c);} TkVar*tkmkvar(TkTop *t, char *name, int type){ TkVar *v; for(v = t->vars; v; v = v->link) if(strcmp(v->name, name) == 0) return v; if(type == 0) return nil; Lines 1–500 of 1295. Load more
#include "lib9.h" #include "interp.h" #include "isa.h" #include "runt.h" #include "draw.h" #include "tk.h" #include "tkmod.h" #include "pool.h" #include "drawif.h" #include "keyboard.h" #include "raise.h" #include "kernel.h" extern void tkfreetop(Heap*, int); Type* fakeTkTop; static uchar TktypeMap[] = Tk_Toplevel_map; int tkstylus; void (*tkwiretap)(void*, char*, char*, void*, Rectangle*); static void tktopimagedptr(TkTop*, Draw_Image*); static char*tkputwinimage(Tk*, Draw_Image*, int); static void lockctxt(TkCtxt *ctxt) { libqlock(ctxt->lock); } static void unlockctxt(TkCtxt *ctxt) { libqunlock(ctxt->lock); } static void tkmarktop(Type *t, void *vw) { Heap *h; TkVar *v; TkPanelimage *di; TkTop *top; Tk *w, *next; TkWin *tkw; markheap(t, vw); top = vw; // XXX do we need to lock context here?? for(v = top->vars; v; v = v->link) { if(v->type == TkVchan) { h = D2H(v->value); Setmark(h); } } for (di = top->panelimages; di != nil; di = di->link) { h = D2H(di->image); Setmark(h); } for(w = top->windows; w != nil; w = next){ tkw = TKobj(TkWin, w); if(tkw->image != nil){ h = D2H(tkw->di); Setmark(h); } next = tkw->next; } } void tkmodinit(void) { builtinmod("$Tk", Tkmodtab, Tkmodlen); fmtinstall('v', tkeventfmt); /* XXX */ fakeTkTop = dtype(tkfreetop, sizeof(TkTop), TktypeMap, sizeof(TktypeMap)); fakeTkTop->mark = tkmarktop; tksorttable(); } void Tk_toplevel(void *a) { Tk *tk; Heap *h; TkTop *t; TkWin *tkw; TkCtxt *ctxt; Display *disp; F_Tk_toplevel *f = a; void *r; r = *f->ret; *f->ret = H; destroy(r); disp = checkdisplay(f->d); h = heapz(fakeTkTop); t = H2D(TkTop*, h); poolimmutable(h); t->dd = f->d; D2H(t->dd)->ref++; t->execdepth = -1; t->display = disp; tk = tknewobj(t, TKframe, sizeof(Tk)+sizeof(TkWin)); if(tk == nil) { destroy(t); return; } tk->act.x = 0; tk->act.y = 0; tk->act.width = 1; /* XXX why not zero? */ tk->act.height = 1; tk->flag |= Tkwindow; tkw = TKobj(TkWin, tk); tkw->di = H; tktopopt(tk, string2c(f->arg)); tk->geom = tkmoveresize; tk->name = tkmkname("."); if(tk->name == nil) { tkfreeobj(tk); destroy(t); return; } ctxt = tknewctxt(disp); if(ctxt == nil) { tkfreeobj(tk); destroy(t); return; } t->ctxt = ctxt; t->screenr = disp->image->r; tkw->next = t->windows; t->windows = tk; t->root = tk; Setmark(h); poolmutable(h); t->wreq = cnewc(&Tptr, movp, 8); *f->ret = (Tk_Toplevel*)t; } void Tk_cmd(void *a) { TkTop *t; char *val, *e; F_Tk_cmd *f = a; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop) { retstr(TkNotop, f->ret); return; } lockctxt(t->ctxt); val = nil; e = tkexec(t, string2c(f->arg), &val); unlockctxt(t->ctxt); if(e == TkNomem){ free(val); error(exNomem); /* what about f->ret? */ } if(e != nil && t->errx[0] != '\0'){ char *s = tkerrstr(t, e); retstr(s, f->ret); free(s); } else retstr(e == nil ? val : e, f->ret); if(tkwiretap != nil) tkwiretap(t, string2c(f->arg), val, nil, nil); free(val); } void Tk_color(void *fp) { ulong rgba; F_Tk_color *f = fp; if(tkparsecolor(string2c(f->col), &rgba) != nil) *f->ret = DNotacolor; else *f->ret = rgba; } void Tk_rect(void *fp) { F_Tk_rect *f = fp; Tk *tk; TkTop *t; Rectangle r; TkGeom *g; Point o; int bd, flags; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop){ *(Rectangle *)f->ret = ZR; return; } lockctxt(t->ctxt); tk = tklook(t, string2c(f->name), 0); if(tk == nil){ *(Rectangle *)f->ret = ZR; unlockctxt(t->ctxt); return; } o = tkposn(tk); flags = f->flags; if(flags & Tk_Local) o = subpt(o, tkposn(tk->env->top->root)); bd = tk->borderwidth; g = (flags & Tk_Required) ? &tk->req : &tk->act; if(flags & Tk_Border){ r.min = o; r.max.x = r.min.x + g->width + bd + bd; r.max.y = r.min.y + g->height + bd + bd; } else { r.min.x = o.x + bd; r.min.y = o.y + bd; r.max.x = r.min.x + g->width; r.max.y = r.min.y + g->height; } *(Rectangle *)f->ret = r; unlockctxt(t->ctxt); } int tkdescendant(Tk *p, Tk *c) { int n; if(c == nil || p->env->top != c->env->top) return 0; if (p->name != nil && c->name != nil) { n = strlen(p->name->name); if(strncmp(p->name->name, c->name->name, n) == 0) return 1; } return 0; } void tkenterleave(TkTop *t) { Tk *fw, *ent; TkMouse m; TkTop *t1, *t2; TkCtxt *c; c = t->ctxt; m = c->mstate; if (c->mgrab != nil && (c->mgrab->flag & Tknograb)) { fw = tkfindfocus(t, m.x, m.y, 1); if (fw != c->mgrab && fw != nil && (fw->flag & Tknograb) == 0) fw = nil; } else if (c->focused) { fw = tkfindfocus(t, m.x, m.y, 1); if (fw != c->mfocus) fw = nil; } else if (c->mgrab != nil) { fw = tkfindfocus(t, m.x, m.y, 1); if (fw != nil) { if (!tkdescendant(c->mgrab, fw) && !(fw->flag & c->mgrab->flag & Tknograb)) fw = nil; } } else if (m.b == 0) fw = tkfindfocus(t, m.x, m.y, 0); else if (tkfindfocus(t, m.x, m.y, 1) == c->entered) return; else fw = nil; if (c->entered == fw) return; t1 = t2 = nil; if (c->entered != nil) { ent = c->entered; t1 = ent->env->top; c->entered = nil; tkdeliver(ent, TkLeave, nil); } if (fw != nil) { t2 = fw->env->top; c->entered = fw; tkdeliver(fw, TkEnter, &m); } if (t1 != nil) tkupdate(t1); if (t2 != nil && t1 != t2) tkupdate(t2); } void Tk_pointer(void *a) { static int buttonr[] = {TkButton1R, TkButton2R, TkButton3R, TkButton4R, TkButton5R, TkButton6R}; static int buttonp[] = {TkButton1P, TkButton2P, TkButton3P, TkButton4P, TkButton5P, TkButton6P}; Tk *fw, *target, *dest, *ent; TkMouse m; TkCtxt *c; TkTop *t, *ot; int d, dtype, etype; F_Tk_pointer *f = a; int b, lastb, inside; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop) return; c = t->ctxt; /* ignore no-button-motion for emulated stylus input */ if(tkstylus && c->mstate.b == 0 && (f->p.buttons&0x1f)==0) return; lockctxt(c); //if (f->p.buttons != 0 || c->mstate.b != 0) //print("tkmouse %d [%d %d], focused %d[%s], grab %s, entered %s\n", // f->p.buttons, f->p.xy.x, f->p.xy.y, c->focused, tkname(c->mfocus), tkname(c->mgrab), tkname(c->entered)); /* * target is the widget that we're deliver the mouse event to. * inside is true if the mouse point is located inside target. */ inside = 1; if (c->mgrab != nil && (c->mgrab->flag & Tknograb)) { fw = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 1); if (fw != nil && (fw->flag & Tknograb)) target = fw; else { target = c->mgrab; inside = 0; } } else if (c->focused) { if (c->mfocus != nil) { fw = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 1); if (fw != c->mfocus) inside = 0; } target = c->mfocus; } else if (c->mgrab != nil && (c->mgrab->flag & Tkdisabled) == 0) { /* * XXX this isn't quite right, as perhaps we should do a tkinwindow() * (below the grab). * so that events to containers underneath the grab arrive * via the containers (as is usual) */ fw = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 1); if (fw != nil && tkdescendant(c->mgrab, fw)) target = fw; else { target = c->mgrab; inside = 0; } } else target = tkfindfocus(t, f->p.xy.x, f->p.xy.y, 0); lastb = c->mstate.b; c->mstate.x = f->p.xy.x; c->mstate.y = f->p.xy.y; c->mstate.b = f->p.buttons & 0x1f; /* Just the buttons */ m = c->mstate; /* XXX if the mouse is being moved with the buttons held down * and we've no mfocus and no mgrab then ignore * the event as our original target has gone away (or never existed) */ if (lastb && m.b && !c->focused && c->mgrab == nil) target = nil; if (target != c->entered || (c->entered != nil && !inside)) { if (c->entered != nil) { fw = c->entered; c->entered = nil; tkdeliver(fw, TkLeave, nil); if (target == nil || fw->env->top != target->env->top) tkupdate(fw->env->top); } if (inside) { c->entered = target; tkdeliver(target, TkEnter, &m); } } dest = nil; if (target != nil) { etype = 0; dtype = 0; if(f->p.buttons & (1<<8)) /* Double */ dtype = TkDouble; d = lastb ^ m.b; if (d) { /* cancel any autorepeat, notifying existing client */ tkrepeat(nil, nil, nil, 0, 0); if (d & ~lastb & 1) /* button 1 potentially takes the focus */ tkdeliver(target, TkTakefocus|TkButton1P, &m); } for(b=0; b<nelem(buttonp); b++){ if(d & (1<<b)){ etype = buttonr[b]; if(m.b & (1<<b)) etype = buttonp[b]|dtype; dest = tkdeliver(target, etype, &m); } } if(tkstylus && m.b==0) { if ((ent = c->entered) != nil) { c->entered = nil; ot = ent->env->top; tkdeliver(ent, TkLeave, nil); if (ot != target->env->top) tkupdate(ot); } } else if(etype == 0) { etype = TkMotion; for(b = 0; b<nelem(buttonp); b++) if (m.b & (1<<b)) etype |= buttonp[b]; tkdeliver(target, etype, &m); } if (m.b != 0) { if (lastb == 0 && !c->focused) { /* (some deliver might have grabbed it...) */ if (dest == nil) dest = target; if ((dest->flag & Tknograb) == 0) { c->focused = 1; c->mfocus = dest; } } } else { c->focused = 0; c->mfocus = nil; if (lastb != 0) tkenterleave(t); } tkupdate(target->env->top); } else if (c->focused && m.b == 0) { c->focused = 0; tkenterleave(t); } unlockctxt(c); } void Tk_keyboard(void *a) { Tk *grab; TkTop *t; TkCtxt *c; F_Tk_keyboard *f = a; t = (TkTop*)f->t; if(t == H || D2H(t)->t != fakeTkTop) return; c = t->ctxt; if (c == nil) return; lockctxt(c); if (c->tkmenu != nil) grab = c->tkmenu; else grab = c->tkkeygrab; if(grab == nil){ unlockctxt(c); return; } t = grab->env->top; tkdeliver(grab, TkKey|TKKEY(f->key), nil); tkupdate(t); unlockctxt(c); } TkVar* tkmkvar(TkTop *t, char *name, int type) { TkVar *v; for(v = t->vars; v; v = v->link) if(strcmp(v->name, name) == 0) return v; if(type == 0) return nil;