wayland fix
All checks were successful
pyrite-dev/milsko/pipeline/head This commit looks good

This commit is contained in:
IoIxD 2026-09-27 07:49:49 +09:00 • committed by IoI_xD
commit a71d5529d7
3 changed files with 41 additions and 19 deletions

View file

@ -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);

View file

@ -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));

View file

@ -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;