shithub: widget

Download patch

ref: b57b54c2d8223debedae9844098b89c6b5475637
parent: 1d84452255fa2d3c41ac2596f39d61d7e3b27b12
author: Tevo <estevan.cps@gmail.com>
date: Sun Jan 10 22:53:47 EST 2021

Root menus

--- a/cmd/factory/factory.c
+++ b/cmd/factory/factory.c
@@ -19,6 +19,7 @@
 {
 	Widgetctl *wctl;
 	Widgetmsg *msg;
+	Menumsg mmsg;
 	Box *root;
 	Rune rune;
 
@@ -30,8 +31,25 @@
 	if(initdraw(nil, nil, "widget factory") < 0)
 		sysfatal("initdraw: %r");
 
-	root = newbox(
-		newtextbutton(nil, "hello, world!"), 0
+	enum
+	{
+		MIDDLE_EXIT
+	};
+
+	char *mentries[] =
+	{
+		[MIDDLE_EXIT] = "exit",
+		nil,
+	};
+
+	Menu middle =
+	{
+		.item		= mentries,
+		.lasthit	= -1
+	};
+
+	root = newcenterbox(
+		newtextbutton(nil, "hello, world!")
 	);
 
 	root->maxsize = Pt(256, 128);
@@ -39,9 +57,11 @@
 	if((wctl = initwidget(screen, nil, nil, root, FORWARD_KBD)) == nil)
 		sysfatal("initwidget: %r");
 
+	wctl->middle = &middle;
+
 	enum
 	{
-		MESSAGE, RESIZE, KEYBOARD
+		MESSAGE, RESIZE, KEYBOARD, MENU
 	};
 
 	Alt chans[] = 
@@ -49,6 +69,7 @@
 		{ wctl->c,			&msg,	CHANRCV },
 		{ wctl->resizec,	nil,	CHANRCV },
 		{ wctl->kbdc,		&rune,	CHANRCV },
+		{ wctl->menuc,		&mmsg,	CHANRCV },
 
 		{ nil,				nil,	CHANEND }
 	};
@@ -71,6 +92,18 @@
 		case KEYBOARD:
 			if(rune == '')
 				goto end;
+			break;
+		case MENU:
+			switch(mmsg.button)
+			{
+			case M_MIDDLE:
+				switch(mmsg.hit)
+				{
+				case MIDDLE_EXIT:
+					goto end;
+				}
+				break;
+			}
 			break;
 		case RESIZE:
 			if(getwindow(display, Refnone) < 0)
--- a/libwidget/base.c
+++ b/libwidget/base.c
@@ -19,6 +19,22 @@
 }
 
 void
+handlemenu(Widgetctl *ctl, Menu *menu, int button)
+{
+	Menumsg msg =
+	{
+		.menu	= menu,
+		.button	= button,
+	};
+
+	msg.hit = menuhit(button, ctl->mouse, menu, ctl->image->screen);
+
+	redrawwctl(ctl);
+
+	send(ctl->menuc, &msg);
+}
+
+void
 widgetmain(Widgetctl *ctl)
 {
 	Mouse mouse;
@@ -47,9 +63,29 @@
 		switch(alt(chans))
 		{
 		case MOUSE:
-			if(!mouseevent(ctl->root, ctl->image, ctl->image->r, mouse, ctl->c) 
-				&& ctl->flags & FORWARD_MOUSE)
-				send(ctl->mousec, &mouse);
+			if(!mouseevent(ctl->root, ctl->image, ctl->image->r, mouse, ctl->c))
+			{
+				if((mouse.buttons & M_LEFT) && ctl->left != nil)
+				{
+					handlemenu(ctl, ctl->left, M_LEFT);
+					break;
+				}
+
+				if((mouse.buttons & M_MIDDLE) && ctl->middle != nil)
+				{
+					handlemenu(ctl, ctl->middle, M_MIDDLE);
+					break;
+				}
+
+				if((mouse.buttons & M_RIGHT) && ctl->right != nil)
+				{
+					handlemenu(ctl, ctl->right, M_RIGHT);
+					break;
+				}
+
+				if(ctl->flags & FORWARD_MOUSE)
+					send(ctl->mousec, &mouse);
+			}
 			break;
 		case KEYBOARD:
 			if(!kbdevent(ctl->root, ctl->image, ctl->image->r, rune, ctl->c)
@@ -94,6 +130,7 @@
 	ctl->kbd = kbd;
 	ctl->c = chancreate(sizeof(Widgetmsg*), 16);
 	ctl->kbdc = chancreate(sizeof(Rune), 20);
+	ctl->menuc = chancreate(sizeof(Menumsg), 16);
 	ctl->mousec = chancreate(sizeof(Mouse), 16);
 	ctl->resizec = mouse->resizec;
 	ctl->flags = flags;
@@ -111,6 +148,7 @@
 {
 	chanclose(ctl->c);
 	chanclose(ctl->kbdc);
+	chanclose(ctl->menuc);
 	chanclose(ctl->mousec);
 	chanclose(ctl->resizec);
 
--- a/libwidget/base.h
+++ b/libwidget/base.h
@@ -4,6 +4,8 @@
 typedef struct Widgetctl Widgetctl;
 typedef struct Widgetmsg Widgetmsg;
 
+typedef struct Menumsg Menumsg;
+
 struct Widget
 {
 	int id;
@@ -24,9 +26,10 @@
 
 struct Widgetctl
 {
-	Channel *c;			/* chan(Widgetmsg*)[16] */
-	Channel *kbdc;		/* chan(Rune)[20] */
-	Channel *mousec;	/* chan(Mouse)[16] */
+	Channel *c;			/* chan(Widgetmsg*)[16]	*/
+	Channel *kbdc;		/* chan(Rune)[20]		*/
+	Channel *menuc;		/* chan(Menumsg)[16]	*/
+	Channel *mousec;	/* chan(Mouse)[16]		*/
 	Channel *resizec;
 	/* NOTE user retains ownership of the root widget */
 	Widget *root;
@@ -58,6 +61,12 @@
 	M_MIDDLE	= 1<<1,
 	M_RIGHT		= 1<<2
 	/* TODO add scroll up/down */
+};
+
+struct Menumsg
+{
+	Menu *menu;
+	int button, hit;
 };
 
 struct Widgetmsg