diff --git a/src/menu.c b/src/menu.c index 4edb1dc..293c3d6 100644 --- a/src/menu.c +++ b/src/menu.c @@ -1109,73 +1109,49 @@ static void selectEntry(WMenu * menu, int entry_no) } } +/* Recursively walk a menu and all of its descendants checking whether + * the pointer is over the entries area. Updates *deepest_p to the + * deepest mapped menu under (x,y) so that sub-sub-menus (cascade-of- + * cascade-...) are reachable. + */ +static void findMenuWalk(WMenu *m, int x, int y, + WMenu **deepest_p, int *dx_p, int *dy_p) +{ + if (!m) return; + if (m->flags.mapped && + x >= m->frame_x && x < m->frame_x + MENUW(m) && + y >= m->frame_y && y < m->frame_y + MENUH(m)) { + *deepest_p = m; + *dx_p = x - m->frame_x; + *dy_p = y - m->frame_y - m->frame->top_width; + } + if (m->brother) + findMenuWalk(m->brother, x, y, deepest_p, dx_p, dy_p); + for (int i = 0; i < m->cascade_no; i++) + findMenuWalk(m->cascades[i], x, y, deepest_p, dx_p, dy_p); +} + static WMenu *findMenu(WScreen * scr, int *x_ret, int *y_ret) { - WMenu *menu; int x, y; + WMenu *deepest = NULL; + int dx = 0, dy = 0; wm_backend->pointer_get_position(&x, &y); - /* Helper: check if (x,y) is inside a mapped menu */ -#define CHECK_MENU(m) do { \ - if ((m) && (m)->flags.mapped && \ - x >= (m)->frame_x && x < (m)->frame_x + MENUW(m) && \ - y >= (m)->frame_y && y < (m)->frame_y + MENUH(m)) { \ - *x_ret = x - (m)->frame_x; \ - *y_ret = y - (m)->frame_y - (m)->frame->top_width; \ - return (m); \ - } \ -} while(0) + findMenuWalk(scr->root_menu, x, y, &deepest, &dx, &dy); + findMenuWalk(scr->switch_menu, x, y, &deepest, &dx, &dy); + findMenuWalk(scr->window_menu, x, y, &deepest, &dx, &dy); + findMenuWalk(scr->dock ? scr->dock->menu : NULL, + x, y, &deepest, &dx, &dy); + findMenuWalk(scr->clip_menu, x, y, &deepest, &dx, &dy); + findMenuWalk(scr->dock_pos_menu, x, y, &deepest, &dx, &dy); - /* Check root menu, its brother, and cascades */ - menu = scr->root_menu; - if (menu) { - CHECK_MENU(menu); - CHECK_MENU(menu->brother); - for (int i = 0; i < menu->cascade_no; i++) { - CHECK_MENU(menu->cascades[i]); - if (menu->cascades[i]) - CHECK_MENU(menu->cascades[i]->brother); - } + if (deepest) { + *x_ret = dx; + *y_ret = dy; + return deepest; } - - /* Check switch menu */ - menu = scr->switch_menu; - CHECK_MENU(menu); - if (menu) CHECK_MENU(menu->brother); - - /* Check window menu */ - menu = scr->window_menu; - if (menu) { - CHECK_MENU(menu); - CHECK_MENU(menu->brother); - for (int i = 0; i < menu->cascade_no; i++) { - CHECK_MENU(menu->cascades[i]); - if (menu->cascades[i]) - CHECK_MENU(menu->cascades[i]->brother); - } - } - - /* Check dock menu */ - menu = scr->dock ? scr->dock->menu : NULL; - if (menu) { - CHECK_MENU(menu); - for (int i = 0; i < menu->cascade_no; i++) - CHECK_MENU(menu->cascades[i]); - } - - /* Check clip menu */ - menu = scr->clip_menu; - if (menu) { - CHECK_MENU(menu); - for (int i = 0; i < menu->cascade_no; i++) - CHECK_MENU(menu->cascades[i]); - } - - /* Check dock position menu */ - CHECK_MENU(scr->dock_pos_menu); - -#undef CHECK_MENU return NULL; }