mirror of
https://github.com/labwc/labwc.git
synced 2026-03-11 05:33:49 -04:00
Convert menu to node_descriptors
This commit is contained in:
parent
eb7645d0e0
commit
8444ba4075
6 changed files with 75 additions and 68 deletions
|
|
@ -23,6 +23,7 @@ struct menu_scene {
|
||||||
|
|
||||||
struct menuitem {
|
struct menuitem {
|
||||||
struct wl_list actions;
|
struct wl_list actions;
|
||||||
|
struct menu *parent;
|
||||||
struct menu *submenu;
|
struct menu *submenu;
|
||||||
struct menu_scene normal;
|
struct menu_scene normal;
|
||||||
struct menu_scene selected;
|
struct menu_scene selected;
|
||||||
|
|
@ -75,15 +76,19 @@ void menu_open(struct menu *menu, int x, int y);
|
||||||
* - handles hover effects
|
* - handles hover effects
|
||||||
* - may open/close submenus
|
* - may open/close submenus
|
||||||
*/
|
*/
|
||||||
void menu_process_cursor_motion(struct menu *menu, struct wlr_scene_node *node);
|
void menu_process_cursor_motion(struct wlr_scene_node *node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* menu_call_actions - call actions associated with a menu entry
|
* menu_call_actions - call actions associated with a menu node
|
||||||
*
|
*
|
||||||
* If actions are found, server->menu_current will be closed and set to NULL
|
* If menuitem connected to @node does not just open a submenu:
|
||||||
* Returns true if handled
|
* - associated actions will be called
|
||||||
|
* - server->menu_current will be closed
|
||||||
|
* - server->menu_current will be set to NULL
|
||||||
|
*
|
||||||
|
* Returns true if actions have actually been executed
|
||||||
*/
|
*/
|
||||||
bool menu_call_actions(struct menu *menu, struct wlr_scene_node *node);
|
bool menu_call_actions(struct wlr_scene_node *node);
|
||||||
|
|
||||||
/* menu_close - close menu */
|
/* menu_close - close menu */
|
||||||
void menu_close(struct menu *menu);
|
void menu_close(struct menu *menu);
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
struct view;
|
struct view;
|
||||||
struct lab_layer_surface;
|
struct lab_layer_surface;
|
||||||
struct lab_layer_popup;
|
struct lab_layer_popup;
|
||||||
|
struct menuitem;
|
||||||
|
|
||||||
enum node_descriptor_type {
|
enum node_descriptor_type {
|
||||||
LAB_NODE_DESC_NODE = 0,
|
LAB_NODE_DESC_NODE = 0,
|
||||||
|
|
@ -13,6 +14,7 @@ enum node_descriptor_type {
|
||||||
LAB_NODE_DESC_XDG_POPUP,
|
LAB_NODE_DESC_XDG_POPUP,
|
||||||
LAB_NODE_DESC_LAYER_SURFACE,
|
LAB_NODE_DESC_LAYER_SURFACE,
|
||||||
LAB_NODE_DESC_LAYER_POPUP,
|
LAB_NODE_DESC_LAYER_POPUP,
|
||||||
|
LAB_NODE_DESC_MENUITEM,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node_descriptor {
|
struct node_descriptor {
|
||||||
|
|
@ -54,4 +56,11 @@ struct lab_layer_surface *node_layer_surface_from_node(
|
||||||
struct lab_layer_popup *node_layer_popup_from_node(
|
struct lab_layer_popup *node_layer_popup_from_node(
|
||||||
struct wlr_scene_node *wlr_scene_node);
|
struct wlr_scene_node *wlr_scene_node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* node_menuitem_from_node - return menuitem struct from node
|
||||||
|
* @wlr_scene_node: wlr_scene_node from which to return data
|
||||||
|
*/
|
||||||
|
struct menuitem *node_menuitem_from_node(
|
||||||
|
struct wlr_scene_node *wlr_scene_node);
|
||||||
|
|
||||||
#endif /* __LABWC_NODE_DESCRIPTOR_H */
|
#endif /* __LABWC_NODE_DESCRIPTOR_H */
|
||||||
|
|
|
||||||
|
|
@ -233,7 +233,7 @@ process_cursor_motion(struct server *server, uint32_t time)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (view_area == LAB_SSD_MENU) {
|
if (view_area == LAB_SSD_MENU) {
|
||||||
menu_process_cursor_motion(server->menu_current, node);
|
menu_process_cursor_motion(node);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -677,8 +677,8 @@ cursor_button(struct wl_listener *listener, void *data)
|
||||||
if (view_area != LAB_SSD_MENU) {
|
if (view_area != LAB_SSD_MENU) {
|
||||||
/* We close the menu on release so we don't leak a stray release */
|
/* We close the menu on release so we don't leak a stray release */
|
||||||
close_menu = true;
|
close_menu = true;
|
||||||
} else if (menu_call_actions(server->menu_current, node)) {
|
} else if (menu_call_actions(node)) {
|
||||||
/* Action was successfull, may fail if item contains a submenu */
|
/* Action was successfull, may fail if item just opens a submenu */
|
||||||
close_menu = true;
|
close_menu = true;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -284,9 +284,9 @@ desktop_node_and_view_at(struct server *server, double lx, double ly,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
struct wlr_scene_node *osd = &server->osd_tree->node;
|
struct wlr_scene_node *osd = &server->osd_tree->node;
|
||||||
struct wlr_scene_node *menu = &server->menu_tree->node;
|
|
||||||
while (node) {
|
while (node) {
|
||||||
struct node_descriptor *desc = node->data;
|
struct node_descriptor *desc = node->data;
|
||||||
|
/* TODO: convert to switch() */
|
||||||
if (desc) {
|
if (desc) {
|
||||||
if (desc->type == LAB_NODE_DESC_VIEW) {
|
if (desc->type == LAB_NODE_DESC_VIEW) {
|
||||||
goto has_view_data;
|
goto has_view_data;
|
||||||
|
|
@ -299,13 +299,16 @@ desktop_node_and_view_at(struct server *server, double lx, double ly,
|
||||||
*view_area = LAB_SSD_CLIENT;
|
*view_area = LAB_SSD_CLIENT;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (desc->type == LAB_NODE_DESC_MENUITEM) {
|
||||||
|
/* Always return the top scene node for menu items */
|
||||||
|
*scene_node = node;
|
||||||
|
*view_area = LAB_SSD_MENU;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (node == osd) {
|
if (node == osd) {
|
||||||
*view_area = LAB_SSD_OSD;
|
*view_area = LAB_SSD_OSD;
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (node == menu) {
|
|
||||||
*view_area = LAB_SSD_MENU;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
node = node->parent;
|
node = node->parent;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
#include "theme.h"
|
#include "theme.h"
|
||||||
#include "action.h"
|
#include "action.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
|
#include "node.h"
|
||||||
|
|
||||||
#define MENUWIDTH (110)
|
#define MENUWIDTH (110)
|
||||||
#define MENU_ITEM_PADDING_Y (4)
|
#define MENU_ITEM_PADDING_Y (4)
|
||||||
|
|
@ -82,6 +83,7 @@ item_create(struct menu *menu, const char *text)
|
||||||
if (!menuitem) {
|
if (!menuitem) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
menuitem->parent = menu;
|
||||||
struct server *server = menu->server;
|
struct server *server = menu->server;
|
||||||
struct theme *theme = server->theme;
|
struct theme *theme = server->theme;
|
||||||
struct font font = {
|
struct font font = {
|
||||||
|
|
@ -117,6 +119,12 @@ item_create(struct menu *menu, const char *text)
|
||||||
menuitem->selected.text = &wlr_scene_buffer_create(
|
menuitem->selected.text = &wlr_scene_buffer_create(
|
||||||
menuitem->selected.background, &menuitem->selected.buffer->base)->node;
|
menuitem->selected.background, &menuitem->selected.buffer->base)->node;
|
||||||
|
|
||||||
|
/* Node descriptors for top scene nodes of menuitem */
|
||||||
|
node_descriptor_create(menuitem->normal.background,
|
||||||
|
LAB_NODE_DESC_MENUITEM, menuitem);
|
||||||
|
node_descriptor_create(menuitem->selected.background,
|
||||||
|
LAB_NODE_DESC_MENUITEM, menuitem);
|
||||||
|
|
||||||
/* Center font nodes */
|
/* Center font nodes */
|
||||||
y = (menu->item_height - menuitem->normal.buffer->base.height) / 2;
|
y = (menu->item_height - menuitem->normal.buffer->base.height) / 2;
|
||||||
x = MENU_ITEM_PADDING_X;
|
x = MENU_ITEM_PADDING_X;
|
||||||
|
|
@ -132,7 +140,7 @@ item_create(struct menu *menu, const char *text)
|
||||||
/* Hide selected state */
|
/* Hide selected state */
|
||||||
wlr_scene_node_set_enabled(menuitem->selected.background, false);
|
wlr_scene_node_set_enabled(menuitem->selected.background, false);
|
||||||
|
|
||||||
/* Update menu extends */
|
/* Update menu extents */
|
||||||
menu->size.height = (item_count + 1) * menu->item_height;
|
menu->size.height = (item_count + 1) * menu->item_height;
|
||||||
|
|
||||||
wl_list_insert(&menu->menuitems, &menuitem->link);
|
wl_list_insert(&menu->menuitems, &menuitem->link);
|
||||||
|
|
@ -516,74 +524,47 @@ menu_open(struct menu *menu, int x, int y)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
menu_process_cursor_motion(struct menu *menu, struct wlr_scene_node *node)
|
menu_process_cursor_motion(struct wlr_scene_node *node)
|
||||||
{
|
{
|
||||||
if (!node) {
|
assert(node && node->data);
|
||||||
wlr_log(WLR_ERROR, "%s() node == NULL", __func__);
|
struct menuitem *item = node_menuitem_from_node(node);
|
||||||
|
|
||||||
|
if (node == item->selected.background) {
|
||||||
|
/* We are on an already selected item */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
assert(menu);
|
|
||||||
|
|
||||||
/* TODO: this would be much easier if we could use node->data */
|
/* We are on an item that has new mouse-focus */
|
||||||
|
menu_set_selection(item->parent, item);
|
||||||
struct menuitem *item;
|
if (item->parent->selection.menu) {
|
||||||
wl_list_for_each (item, &menu->menuitems, link) {
|
/* Close old submenu tree */
|
||||||
if (node == item->selected.background
|
menu_close(item->parent->selection.menu);
|
||||||
|| node->parent == item->selected.background) {
|
|
||||||
/* We are on an already selected item */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (node == item->normal.background
|
|
||||||
|| node->parent == item->normal.background) {
|
|
||||||
/* We are on an item that has new mouse-focus */
|
|
||||||
menu_set_selection(menu, item);
|
|
||||||
if (menu->selection.menu) {
|
|
||||||
/* Close old submenu tree */
|
|
||||||
menu_close(menu->selection.menu);
|
|
||||||
}
|
|
||||||
if (item->submenu) {
|
|
||||||
/* And open the new one */
|
|
||||||
wlr_scene_node_set_enabled(
|
|
||||||
&item->submenu->scene_tree->node, true);
|
|
||||||
}
|
|
||||||
menu->selection.menu = item->submenu;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (item->submenu && item->submenu == menu->selection.menu) {
|
|
||||||
menu_process_cursor_motion(item->submenu, node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (item->submenu) {
|
||||||
|
/* And open the new one */
|
||||||
|
wlr_scene_node_set_enabled(
|
||||||
|
&item->submenu->scene_tree->node, true);
|
||||||
|
}
|
||||||
|
item->parent->selection.menu = item->submenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
menu_call_actions(struct menu *menu, struct wlr_scene_node *node)
|
menu_call_actions(struct wlr_scene_node *node)
|
||||||
{
|
{
|
||||||
/* TODO: this would be much easier if we could use node->data */
|
assert(node && node->data);
|
||||||
|
struct menuitem *item = node_menuitem_from_node(node);
|
||||||
|
|
||||||
if (!menu->selection.item) {
|
if (item->submenu) {
|
||||||
/* No item selected in current menu */
|
/* We received a click on an item that just opens a submenu */
|
||||||
wlr_log(WLR_ERROR, "No item on menu_action_selected");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
struct wlr_scene_node *menu_node =
|
|
||||||
menu->selection.item->selected.background;
|
actions_run(NULL, item->parent->server, &item->actions, 0);
|
||||||
if (node == menu_node || node->parent == menu_node) {
|
menu_close(item->parent->server->menu_current);
|
||||||
/* We found the correct menu item */
|
item->parent->server->menu_current = NULL;
|
||||||
if (menu->selection.item->submenu) {
|
return true;
|
||||||
/* ..but it just opens a submenu */
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
actions_run(NULL, menu->server, &menu->selection.item->actions, 0);
|
|
||||||
menu_close(menu->server->menu_current);
|
|
||||||
menu->server->menu_current = NULL;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (menu->selection.menu) {
|
|
||||||
return menu_call_actions(menu->selection.menu, node);
|
|
||||||
}
|
|
||||||
wlr_log(WLR_ERROR, "No match on menu_action_selected");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -64,3 +64,12 @@ node_layer_popup_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||||
assert(node_descriptor->type == LAB_NODE_DESC_LAYER_POPUP);
|
assert(node_descriptor->type == LAB_NODE_DESC_LAYER_POPUP);
|
||||||
return (struct lab_layer_popup *)node_descriptor->data;
|
return (struct lab_layer_popup *)node_descriptor->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct menuitem *
|
||||||
|
node_menuitem_from_node(struct wlr_scene_node *wlr_scene_node)
|
||||||
|
{
|
||||||
|
assert(wlr_scene_node->data);
|
||||||
|
struct node_descriptor *node_descriptor = wlr_scene_node->data;
|
||||||
|
assert(node_descriptor->type == LAB_NODE_DESC_MENUITEM);
|
||||||
|
return (struct menuitem *)node_descriptor->data;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue