ref: b9f2b8c6a28c2d4744119c7254767a0f1b51ed2e
parent: 5409ad54228242e20aed847acba4d10582b1191c
author: Tevo <estevan.cps@gmail.com>
date: Sat Jan 9 21:18:02 EST 2021
Unhandled mouse/keyboard forwarding and default initialization
--- a/cmd/factory/factory.c
+++ b/cmd/factory/factory.c
@@ -17,11 +17,10 @@
void
threadmain(int argc, char **argv)
{
- Keyboardctl *kbctl;
- Mousectl *mctl;
- Button *root;
Widgetctl *wctl;
Widgetmsg *msg;
+ Button *root;
+ Rune rune;
ARGBEGIN {
default:
@@ -31,20 +30,14 @@
if(initdraw(nil, nil, "widget factory") < 0)
sysfatal("initdraw: %r");
- if((mctl = initmouse(nil, screen)) == nil)
- sysfatal("initmouse: %r");
-
- if((kbctl = initkeyboard(nil)) == nil)
- sysfatal("initkeyboard: %r");
-
root = newtextbutton(nil, "hello, world!");
- if((wctl = initwidget(screen, kbctl, mctl, root)) == nil)
+ if((wctl = initwidget(screen, nil, nil, root, FORWARD_KBD)) == nil)
sysfatal("initwidget: %r");
enum
{
- MESSAGE, RESIZE
+ MESSAGE, RESIZE, KEYBOARD
};
Alt chans[] =
@@ -51,6 +44,7 @@
{
{ wctl->c, &msg, CHANRCV },
{ wctl->resizec, nil, CHANRCV },
+ { wctl->kbdc, &rune, CHANRCV },
{ nil, nil, CHANEND }
};
@@ -63,6 +57,10 @@
print("got message for %d!\n", msg->what);
free(msg);
break;
+ case KEYBOARD:
+ if(rune == '')
+ goto end;
+ break;
case RESIZE:
if(getwindow(display, Refnone) < 0)
sysfatal("getwindow: cannot resize: %r");
@@ -74,8 +72,7 @@
}
end:
- closemouse(mctl);
- closekeyboard(kbctl);
+ closewidget(wctl);
freewidget(root);
exits(0);
--- a/libwidget/base.c
+++ b/libwidget/base.c
@@ -45,10 +45,14 @@
switch(alt(chans))
{
case MOUSE:
- mouseevent(ctl->root, ctl->image, ctl->image->r, mouse, ctl->c);
+ if(!mouseevent(ctl->root, ctl->image, ctl->image->r, mouse, ctl->c)
+ && ctl->flags & FORWARD_MOUSE)
+ send(ctl->mousec, &mouse);
break;
case KEYBOARD:
- kbdevent(ctl->root, ctl->image, ctl->image->r, rune, ctl->c);
+ if(!kbdevent(ctl->root, ctl->image, ctl->image->r, rune, ctl->c)
+ && ctl->flags & FORWARD_KBD)
+ send(ctl->kbdc, &rune);
break;
}
flushimage(ctl->image->display, 1);
@@ -56,19 +60,41 @@
}
Widgetctl*
-initwidget(Image *img, Keyboardctl *kbd, Mousectl *mouse, Widget *root)
+initwidget(Image *img, Keyboardctl *kbd, Mousectl *mouse, Widget *root, int flags)
{
Widgetctl *ctl;
- if((ctl = malloc(sizeof(*ctl))) == nil)
+ if((ctl = mallocz(sizeof(*ctl), 1)) == nil)
return nil;
+ if(mouse == nil)
+ if((mouse = initmouse(nil, img)) == nil)
+ {
+ free(ctl);
+ return nil;
+ }
+ else
+ ctl->pflags |= OURMOUSE;
+
+ if(kbd == nil)
+ if((kbd = initkeyboard(nil)) == nil)
+ {
+ free(ctl);
+ closemouse(mouse);
+ return nil;
+ }
+ else
+ ctl->pflags |= OURKBD;
+
ctl->image = img;
ctl->mouse = mouse;
ctl->root = root;
ctl->kbd = kbd;
ctl->c = chancreate(sizeof(Widgetmsg), 16);
+ ctl->kbdc = chancreate(sizeof(Rune), 20);
+ ctl->mousec = chancreate(sizeof(Mouse), 16);
ctl->resizec = mouse->resizec;
+ ctl->flags = flags;
threadcreate((void(*)(void*))widgetmain, ctl, 16384);
@@ -76,6 +102,20 @@
flushimage(img->display, 1);
return ctl;
+}
+
+void
+closewidget(Widgetctl *ctl)
+{
+ if(ctl->pflags & OURKBD)
+ closekeyboard(ctl->kbd);
+
+ if(ctl->pflags & OURMOUSE)
+ closemouse(ctl->mouse);
+
+ /* TODO cleanup chans, close threads, etc */
+
+ free(ctl);
}
/* TODO set clipr */
--- a/libwidget/base.h
+++ b/libwidget/base.h
@@ -24,7 +24,9 @@
struct Widgetctl
{
- Channel *c; /* chan(Widgetmsg*)[16] */
+ Channel *c; /* chan(Widgetmsg*)[16] */
+ Channel *kbdc; /* chan(Rune)[20] */
+ Channel *mousec; /* chan(Mouse)[16] */
Channel *resizec;
Widget *root;
@@ -32,8 +34,19 @@
Mousectl *mouse;
Image *image;
+
+ int flags;
+
+ /* user shouln't care about anything below this point */
+ int pflags;
};
+enum /* flags */
+{
+ FORWARD_KBD = 1<<0,
+ FORWARD_MOUSE = 1<<1
+};
+
struct Widgetmsg
{
Widget *sender;
@@ -46,7 +59,8 @@
extern void (*werror)(char*, ...);
-Widgetctl* initwidget(Image*, Keyboardctl*, Mousectl*, Widget *root);
+Widgetctl* initwidget(Image*, Keyboardctl*, Mousectl*, Widget *root, int flags);
+void closewidget(Widgetctl*);
void wdefaults(Widget*);
--- a/libwidget/button.h
+++ b/libwidget/button.h
@@ -14,4 +14,8 @@
Button* newbutton(Widget*);
Button* newtextbutton(Font*, char *content);
-static const u32int M_BUTTON_PRESSED = C2I('b', 't', 'n', 'p');
+enum
+{
+ M_BUTTON_PRESSED = C2I('b', 't', 'n', 'p')
+};
+
--- a/libwidget/w-internal.h
+++ b/libwidget/w-internal.h
@@ -9,3 +9,10 @@
setmalloctag(p, getcallerpc(&sz));
return p;
}
+
+/* Widgetctl->flags */
+enum
+{
+ OURKBD = 1<<0,
+ OURMOUSE = 1<<1
+};