BUTTON_RELEASE: capture selection before popDownMenu clears insideMenu/highlightedItem

popDownMenu() resets insideMenu=0 and highlightedItem=-1. When called before
the selection logic, the guard (insideMenu && highlightedItem >= 0) is always
false, so WMSetPopUpButtonSelectedItem is never called and the closed-button
display never updates.

Fix: capture the selection state (insideMenu, highlightedItem, enabled item)
into local variables BEFORE calling popDownMenu. Apply the selection
(WMSetPopUpButtonSelectedItem + action callback) AFTER popDownMenu.
This commit is contained in:
lkn 2026-06-07 17:38:05 +02:00
parent 874f9b1ae0
commit cfddd2ebfc
1 changed files with 37 additions and 25 deletions

View File

@ -751,48 +751,60 @@ static void handleActionEvents(WMEvent * event, void *data)
}
bPtr->view->screen->viewBackend->pointer_ungrab(
bPtr->view->screen->viewBackendCtx, event->u.button.time);
/* Only close on release from menu view (drag-select) or insideMenu active.
* A plain click on the button without entering the menu keeps it open. */
if (!bPtr->flags.pullsDown
&& (event->window == bPtr->menuView->window
|| bPtr->flags.insideMenu))
popDownMenu(bPtr);
if (bPtr->timer) {
WMDeleteTimerHandler(bPtr->timer);
bPtr->timer = NULL;
}
/* Capture selection state BEFORE popDownMenu clears it. */
int do_select = (bPtr->flags.insideMenu
&& bPtr->highlightedItem >= 0
&& !bPtr->flags.pullsDown);
int sel_index = bPtr->highlightedItem;
int has_sel_item = 0;
WMMenuItem *sel_item = NULL;
if (do_select) {
int count = WMGetArrayItemCount(bPtr->items);
if (sel_index >= 0 && sel_index < count) {
WMMenuItem *mi = WMGetPopUpButtonMenuItem(bPtr, sel_index);
if (mi && WMGetMenuItemEnabled(mi)) {
do_select = 1;
sel_item = mi;
has_sel_item = 1;
}
}
}
if (bPtr->flags.insideMenu && bPtr->highlightedItem >= 0) {
WMMenuItem *item;
/* Only close on release from menu view (drag-select) or insideMenu active.
* A plain click on the button without entering the menu keeps it open. */
if (event->window == bPtr->menuView->window
|| bPtr->flags.insideMenu)
popDownMenu(bPtr);
item = WMGetPopUpButtonMenuItem(bPtr, bPtr->highlightedItem);
if (bPtr->timer) {
WMDeleteTimerHandler(bPtr->timer);
bPtr->timer = NULL;
}
if (WMGetMenuItemEnabled(item)) {
int i;
WMSetPopUpButtonSelectedItem(bPtr, bPtr->highlightedItem);
/* Apply selection after popDownMenu (which resets insideMenu/highlightedItem). */
if (has_sel_item) {
WMSetPopUpButtonSelectedItem(bPtr, sel_index);
if (bPtr->flags.pullsDown) {
int i;
for (i = 0; i < MENU_BLINK_COUNT; i++) {
paintMenuEntry(bPtr, bPtr->highlightedItem, False);
paintMenuEntry(bPtr, sel_index, False);
bPtr->view->screen->viewBackend->flush(bPtr->view->screen->viewBackendCtx);
wusleep(MENU_BLINK_DELAY);
paintMenuEntry(bPtr, bPtr->highlightedItem, True);
paintMenuEntry(bPtr, sel_index, True);
bPtr->view->screen->viewBackend->flush(bPtr->view->screen->viewBackendCtx);
wusleep(MENU_BLINK_DELAY);
}
}
paintMenuEntry(bPtr, bPtr->highlightedItem, False);
paintMenuEntry(bPtr, sel_index, False);
popDownMenu(bPtr);
if (bPtr->action)
(*bPtr->action) (bPtr, bPtr->clientData);
}
}
if (bPtr->menuView->flags.mapped
&& (event->window == bPtr->menuView->window
|| bPtr->flags.insideMenu))
popDownMenu(bPtr);
break;
if (bPtr->menuView->flags.mapped && !has_sel_item)
popDownMenu(bPtr);
break;
}
}