shithub: widget

Download patch

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
+};