ref: b57b54c2d8223debedae9844098b89c6b5475637
parent: 1d84452255fa2d3c41ac2596f39d61d7e3b27b12
author: Tevo <[email protected]>
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