]> git.mdlowis.com Git - proto/labwc.git/commitdiff
src/menu: Attach view to menu and use it when executing actions
authorConsolatis <35009135+Consolatis@users.noreply.github.com>
Thu, 9 Jun 2022 15:10:36 +0000 (17:10 +0200)
committerJohan Malm <johanmalm@users.noreply.github.com>
Thu, 9 Jun 2022 21:09:40 +0000 (22:09 +0100)
This fixes #380

include/menu/menu.h
src/action.c
src/cursor.c
src/menu/menu.c
src/view.c

index f6333bca40768a7624767f0ad9705b673830ced2..75252d80df4f740465aeb170bdaf21f5004cfa51 100644 (file)
@@ -4,7 +4,12 @@
 
 #include <wayland-server.h>
 
+/* 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);
index 07539ecb2b495696c4098cca80ff8f9a4b04d425..4089d680f19e64cb74924dee1eec3622cd191e22 100644 (file)
@@ -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);
 }
 
index b248d083482361799b3a528b33dc10876e71ed83..4489eb33579d697552ad8d4c7b4c9498414c1c50 100644 (file)
@@ -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;
index 6b7581faadd89deb30583de18bdb47097f0a2253..8790b27e1f7d0f08bdc3a2e88de9584402bad351 100644 (file)
@@ -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
index 668b711e7fd70133e696dce02fd48049e761c601..e11610bc1c2e38f57e694778fb4074f1fb3e113e 100644 (file)
@@ -5,6 +5,7 @@
 #include <xcb/xcb_icccm.h>
 #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);