ref: 5409ad54228242e20aed847acba4d10582b1191c
dir: /libwidget/base.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <keyboard.h>
#include <String.h>
#include <widget.h>
#include "w-internal.h"
void (*werror)(char*, ...) = sysfatal;
int
nextid(void)
{
static int curid;
return curid++;
}
void
widgetmain(Widgetctl* ctl)
{
Mouse mouse;
Rune rune;
Alt chans[] =
{
{ ctl->mouse->c, &mouse, CHANRCV },
{ ctl->kbd->c, &rune, CHANRCV },
{ nil, nil, CHANEND }
};
enum
{
MOUSE, KEYBOARD
};
for(;;)
{
while(ctl->root == nil)
yield();
switch(alt(chans))
{
case MOUSE:
mouseevent(ctl->root, ctl->image, ctl->image->r, mouse, ctl->c);
break;
case KEYBOARD:
kbdevent(ctl->root, ctl->image, ctl->image->r, rune, ctl->c);
break;
}
flushimage(ctl->image->display, 1);
}
}
Widgetctl*
initwidget(Image *img, Keyboardctl *kbd, Mousectl *mouse, Widget *root)
{
Widgetctl *ctl;
if((ctl = malloc(sizeof(*ctl))) == nil)
return nil;
ctl->image = img;
ctl->mouse = mouse;
ctl->root = root;
ctl->kbd = kbd;
ctl->c = chancreate(sizeof(Widgetmsg), 16);
ctl->resizec = mouse->resizec;
threadcreate((void(*)(void*))widgetmain, ctl, 16384);
redrawwidget(root, img, img->r);
flushimage(img->display, 1);
return ctl;
}
/* TODO set clipr */
Point
redrawwidget(Widget *w, Image *dst, Rectangle r)
{
return w->redraw(w, dst, r);
}
int
kbdevent(Widget *w, Image *img, Rectangle rect, Rune r, Channel *c)
{
if(w->kbdevent != nil)
return w->kbdevent(w, img, rect, r, c);
return 0;
}
int
mouseevent(Widget *w, Image *img, Rectangle rect, Mouse m, Channel *c)
{
if(w->mouseevent != nil)
return w->mouseevent(w, img, rect, m, c);
return 0;
}
void
freewidget(Widget *w)
{
w->cleanup(w);
}
void
wdefaults(Widget *w)
{
w->id = nextid();
w->bg = display->white;
w->fg = display->black;
w->kbdevent = nil;
w->mouseevent = nil;
w->cleanup = (void(*)(Widget*))free;
}
Widgetmsg*
newmsg(Widget* w, u32int what)
{
Widgetmsg *msg;
msg = emalloc(sizeof(*msg));
msg->sender = w;
msg->what = what;
return msg;
}