#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 {
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);
*/
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);
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);
}
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;
}
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;
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)
{
}
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);
}
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
#include <xcb/xcb_icccm.h>
#include "labwc.h"
#include "ssd.h"
+#include "menu/menu.h"
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
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);