From 5a4c5de332aad603f032036d5059984a67cc5937 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Thu, 9 Jun 2022 17:10:36 +0200 Subject: [PATCH] src/menu: Attach view to menu and use it when executing actions This fixes #380 --- include/menu/menu.h | 19 +++++++++++++++++-- src/action.c | 2 ++ src/cursor.c | 19 ++++--------------- src/menu/menu.c | 46 ++++++++++++++++++++++++++++++++------------- src/view.c | 7 +++++++ 5 files changed, 63 insertions(+), 30 deletions(-) diff --git a/include/menu/menu.h b/include/menu/menu.h index f6333bca..75252d80 100644 --- a/include/menu/menu.h +++ b/include/menu/menu.h @@ -4,7 +4,12 @@ #include +/* forward declare arguments */ +struct view; +struct server; +struct wl_list; struct lab_data_buffer; +struct wlr_scene_tree; struct wlr_scene_node; enum menu_align { @@ -49,6 +54,9 @@ struct menu { struct menuitem *item; } selection; struct wlr_scene_tree *scene_tree; + + /* Used to match a window-menu to the view that triggered it. */ + struct view *triggered_by_view; /* may be NULL */ }; void menu_init_rootmenu(struct server *server); @@ -92,8 +100,15 @@ void menu_process_cursor_motion(struct wlr_scene_node *node); */ bool menu_call_actions(struct wlr_scene_node *node); -/* menu_close - close menu */ -void menu_close(struct menu *menu); +/** + * menu_close_root- close root menu + * + * This function will close server->menu_current and set it to NULL. + * Asserts that server->input_mode is set to LAB_INPUT_STATE_MENU. + * + * Additionally, server->input_mode wil be set to LAB_INPUT_STATE_PASSTHROUGH. + */ +void menu_close_root(struct server *server); /* menu_reconfigure - reload theme and content */ void menu_reconfigure(struct server *server); diff --git a/src/action.c b/src/action.c index 07539ecb..4089d680 100644 --- a/src/action.c +++ b/src/action.c @@ -121,6 +121,8 @@ show_menu(struct server *server, struct view *view, const char *menu_name) x = server->seat.cursor->x; y = server->seat.cursor->y; } + /* Replaced by next show_menu() or cleaned on view_destroy() */ + menu->triggered_by_view = view; menu_open(menu, x, y); } diff --git a/src/cursor.c b/src/cursor.c index b248d083..4489eb33 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -718,13 +718,8 @@ cursor_button(struct wl_listener *listener, void *data) seat->pressed.surface = NULL; if (server->input_mode == LAB_INPUT_STATE_MENU) { if (close_menu) { - if (server->menu_current) { - menu_close(server->menu_current); - server->menu_current = NULL; - } - server->input_mode = LAB_INPUT_STATE_PASSTHROUGH; - cursor_rebase(&server->seat, - event->time_msec, false); + menu_close_root(server); + cursor_rebase(&server->seat, event->time_msec, false); close_menu = false; } return; @@ -755,17 +750,11 @@ cursor_button(struct wl_listener *listener, void *data) } if (server->input_mode == LAB_INPUT_STATE_MENU) { + /* We are closing the menu on RELEASE to not leak a stray release */ if (view_area != LAB_SSD_MENU) { - /* - * We close the menu on release so we don't leak a stray - * release - */ close_menu = true; } else if (menu_call_actions(node)) { - /* - * Action was successfull, may fail if item just opens a - * submenu - */ + /* Action was successfull, may fail if item just opens a submenu */ close_menu = true; } return; diff --git a/src/menu/menu.c b/src/menu/menu.c index 6b7581fa..8790b27e 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -548,6 +548,21 @@ close_all_submenus(struct menu *menu) menu->selection.menu = NULL; } +static void +menu_close(struct menu *menu) +{ + if (!menu) { + wlr_log(WLR_ERROR, "Trying to close non exiting menu"); + return; + } + wlr_scene_node_set_enabled(&menu->scene_tree->node, false); + menu_set_selection(menu, NULL); + if (menu->selection.menu) { + menu_close(menu->selection.menu); + menu->selection.menu = NULL; + } +} + void menu_open(struct menu *menu, int x, int y) { @@ -582,7 +597,9 @@ menu_process_cursor_motion(struct wlr_scene_node *node) } if (item->submenu) { - /* And open the new one */ + /* Sync the triggering view */ + item->submenu->triggered_by_view = item->parent->triggered_by_view; + /* And open the new submenu tree */ wlr_scene_node_set_enabled( &item->submenu->scene_tree->node, true); } @@ -600,26 +617,29 @@ menu_call_actions(struct wlr_scene_node *node) return false; } - actions_run(NULL, item->parent->server, &item->actions, 0); + actions_run(item->parent->triggered_by_view, + item->parent->server, &item->actions, 0); + + /** + * We close the menu here to provide a faster feedback to the user. + * We do that without resetting the input state so src/cursor.c + * can do its own clean up on the following RELEASE event. + */ menu_close(item->parent->server->menu_current); item->parent->server->menu_current = NULL; + return true; } void -menu_close(struct menu *menu) +menu_close_root(struct server *server) { - if (!menu) { - wlr_log(WLR_ERROR, "Trying to close non exiting menu"); - return; - } - /* TODO: Maybe reset input state here instead of in cursor.c ? */ - wlr_scene_node_set_enabled(&menu->scene_tree->node, false); - menu_set_selection(menu, NULL); - if (menu->selection.menu) { - menu_close(menu->selection.menu); - menu->selection.menu = NULL; + assert(server->input_mode == LAB_INPUT_STATE_MENU); + if (server->menu_current) { + menu_close(server->menu_current); + server->menu_current = NULL; } + server->input_mode = LAB_INPUT_STATE_PASSTHROUGH; } void diff --git a/src/view.c b/src/view.c index 668b711e..e11610bc 100644 --- a/src/view.c +++ b/src/view.c @@ -5,6 +5,7 @@ #include #include "labwc.h" #include "ssd.h" +#include "menu/menu.h" #define MAX(a, b) (((a) > (b)) ? (a) : (b)) @@ -756,6 +757,12 @@ view_destroy(struct view *view) wlr_scene_node_set_enabled(&output->layer_tree[top]->node, true); } + /* If we spawned a window menu, close it */ + if (server->menu_current + && server->menu_current->triggered_by_view == view) { + menu_close_root(server); + } + /* Remove view from server->views */ wl_list_remove(&view->link); free(view);