This commit is contained in:
parent
56acbaa787
commit
a71d5529d7
3 changed files with 41 additions and 19 deletions
|
|
@ -777,7 +777,8 @@ static void mouse_dispatch(MwLL self, MwMouse p, MwU32 state) {
|
||||||
|
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case WL_POINTER_BUTTON_STATE_PRESSED:
|
case WL_POINTER_BUTTON_STATE_PRESSED:
|
||||||
MwLLDispatch(target, down, &p);
|
/* otherwise the recursion below reaches the target and dispatches it there */
|
||||||
|
if(target == self) MwLLDispatch(target, down, &p);
|
||||||
break;
|
break;
|
||||||
case WL_POINTER_BUTTON_STATE_RELEASED:
|
case WL_POINTER_BUTTON_STATE_RELEASED:
|
||||||
MwLLDispatch(target, up, &p);
|
MwLLDispatch(target, up, &p);
|
||||||
|
|
|
||||||
|
|
@ -45,9 +45,22 @@ static void recursive_free(MwMenu m) {
|
||||||
free(m);
|
free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* submenus are freed after us and would otherwise touch the entries we are about to free */
|
||||||
|
static void detach_submenus(MwWidget handle) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i = 0; i < arrlen(handle->children); i++) {
|
||||||
|
if(handle->children[i]->widget_class != MwSubMenuClass) continue;
|
||||||
|
|
||||||
|
handle->children[i]->internal = NULL;
|
||||||
|
detach_submenus(handle->children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void destroy(MwWidget handle) {
|
static void destroy(MwWidget handle) {
|
||||||
MwMenu m = handle->internal;
|
MwMenu m = handle->internal;
|
||||||
|
|
||||||
|
detach_submenus(handle);
|
||||||
recursive_free(m);
|
recursive_free(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,15 +105,25 @@ static void destroy(MwWidget handle) {
|
||||||
p.x += tw / 2 + 5; \
|
p.x += tw / 2 + 5; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* some backends (e.g. Wayland) dispatch input while creating a widget, which can re-enter these
|
||||||
|
* handlers; if a submenu for this item appeared meanwhile, drop ours instead of orphaning that one.
|
||||||
|
* a release handled during creation saw no submenu yet, so keep it open as mouse_up would have */
|
||||||
#define NEW_SUBMENU \
|
#define NEW_SUBMENU \
|
||||||
MwPoint p2; \
|
MwPoint p2; \
|
||||||
|
MwWidget sw; \
|
||||||
\
|
\
|
||||||
p2.x = p.x - 5 - tw / 2; \
|
p2.x = p.x - 5 - tw / 2; \
|
||||||
p2.y = p.y + th / 2 + 5; \
|
p2.y = p.y + th / 2 + 5; \
|
||||||
\
|
\
|
||||||
m->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, MwGetInteger(handle, MwNheight), 0, 0); \
|
sw = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, MwGetInteger(handle, MwNheight), 0, 0); \
|
||||||
MwSubMenuAppear(m->sub[i]->wsub, m->sub[i], &p2, 0); \
|
if(sw != NULL && m->sub[i]->wsub != NULL) { \
|
||||||
m->sub[i]->cleaned = 0;
|
MwDestroyWidget(sw); \
|
||||||
|
} else if(sw != NULL) { \
|
||||||
|
m->sub[i]->wsub = sw; \
|
||||||
|
m->sub[i]->keep = handle->pressed ? 0 : 1; \
|
||||||
|
m->sub[i]->cleaned = 0; \
|
||||||
|
MwSubMenuAppear(sw, m->sub[i], &p2, 0); \
|
||||||
|
}
|
||||||
|
|
||||||
static void draw(MwWidget handle) {
|
static void draw(MwWidget handle) {
|
||||||
MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground));
|
MwColor base = MwParseColor(handle, MwGetString(handle, MwNbackground));
|
||||||
|
|
|
||||||
|
|
@ -13,19 +13,10 @@ static int wcreate(MwWidget handle) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void null_all(MwMenu menu) {
|
|
||||||
int i;
|
|
||||||
for(i = 0; i < arrlen(menu->sub); i++) {
|
|
||||||
null_all(menu->sub[i]);
|
|
||||||
}
|
|
||||||
menu->wsub = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void destroy(MwWidget handle) {
|
static void destroy(MwWidget handle) {
|
||||||
MwMenu menu = handle->internal;
|
MwMenu menu = handle->internal;
|
||||||
|
|
||||||
menu->wsub = NULL;
|
if(menu != NULL && menu->wsub == handle) menu->wsub = NULL;
|
||||||
null_all(menu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw(MwWidget handle) {
|
static void draw(MwWidget handle) {
|
||||||
|
|
@ -127,6 +118,7 @@ static void click(MwWidget handle) {
|
||||||
if(MwGetInteger(handle, MwNleftPadding) <= handle->mouse_point.x && rc.y <= handle->mouse_point.y && handle->mouse_point.y <= (int)(rc.y + rc.height)) {
|
if(MwGetInteger(handle, MwNleftPadding) <= handle->mouse_point.x && rc.y <= handle->mouse_point.y && handle->mouse_point.y <= (int)(rc.y + rc.height)) {
|
||||||
if(menu->sub[i]->wsub == NULL && arrlen(menu->sub[i]->sub) > 0) {
|
if(menu->sub[i]->wsub == NULL && arrlen(menu->sub[i]->sub) > 0) {
|
||||||
MwPoint p;
|
MwPoint p;
|
||||||
|
MwWidget sw;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for(j = 0; j < arrlen(menu->sub); j++) {
|
for(j = 0; j < arrlen(menu->sub); j++) {
|
||||||
|
|
@ -137,8 +129,14 @@ static void click(MwWidget handle) {
|
||||||
p.x = MwGetInteger(handle, MwNwidth);
|
p.x = MwGetInteger(handle, MwNwidth);
|
||||||
p.y = rc.y - 3;
|
p.y = rc.y - 3;
|
||||||
|
|
||||||
menu->sub[i]->wsub = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0);
|
/* some backends (e.g. Wayland) dispatch input while creating a widget, which can re-enter this handler */
|
||||||
MwSubMenuAppear(menu->sub[i]->wsub, menu->sub[i], &p, 0);
|
sw = MwCreateWidget(MwSubMenuClass, "submenu", handle, 0, 0, 0, 0);
|
||||||
|
if(sw != NULL && (menu->sub[i]->wsub != NULL || handle->destroyed)) {
|
||||||
|
MwDestroyWidget(sw);
|
||||||
|
} else if(sw != NULL) {
|
||||||
|
menu->sub[i]->wsub = sw;
|
||||||
|
MwSubMenuAppear(sw, menu->sub[i], &p, 0);
|
||||||
|
}
|
||||||
i = -1;
|
i = -1;
|
||||||
} else if(menu->sub[i]->wsub != NULL && arrlen(menu->sub[i]->sub) > 0) {
|
} else if(menu->sub[i]->wsub != NULL && arrlen(menu->sub[i]->sub) > 0) {
|
||||||
while(w->parent->widget_class == MwSubMenuClass) w = w->parent;
|
while(w->parent->widget_class == MwSubMenuClass) w = w->parent;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue