From: Droc Date: Tue, 17 Sep 2024 11:52:10 +0000 (-0500) Subject: menu: support client-list-combined-menu X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=71b2b5a;p=proto%2Flabwc.git menu: support client-list-combined-menu ...showing windows across all workspaces. --- diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 443268e8..7092a44c 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -114,9 +114,10 @@ Actions are used in menus and keyboard/mouse bindings. ** Show a menu. - *menu* The name of the menu to show. The menus "root-menu" and - "client-menu" are guaranteed to exist, but others may be defined - explicitly. See labwc-menu(5) for more information. + *menu* The name of the menu to show. The menus "root-menu", + "client-menu", and "client-list-combined-menu" are guaranteed to exist, + but others may be defined explicitly. See labwc-menu(5) for more + information. *atCursor* [yes|no] When opening a menu, open the menu at the location of the mouse cursor. When set to no, the menu will appear at the diff --git a/docs/labwc-menu.5.scd b/docs/labwc-menu.5.scd index a50fa254..f017d986 100644 --- a/docs/labwc-menu.5.scd +++ b/docs/labwc-menu.5.scd @@ -48,6 +48,8 @@ The menu file must be entirely enclosed within and ShowMenu action. Default identifiers are - "root-menu" for the root window context menu - "client-menu" for a window's titlebar context menu + - "client-list-combined-menu" for a list of all windows across + all workspaces *menu.id* (when nested under other ** element) Link to a submenu defined elsewhere (by a ** at toplevel) diff --git a/include/menu/menu.h b/include/menu/menu.h index 980eaa7c..424d47f9 100644 --- a/include/menu/menu.h +++ b/include/menu/menu.h @@ -47,6 +47,7 @@ struct menuitem { struct menu_scene normal; struct menu_scene selected; struct menu_pipe_context *pipe_ctx; + struct view *client_list_view; /* used by internal client-list */ struct wl_list link; /* menu.menuitems */ }; @@ -135,4 +136,6 @@ void menu_close_root(struct server *server); /* menu_reconfigure - reload theme and content */ void menu_reconfigure(struct server *server); +void update_client_list_combined_menu(struct server *server); + #endif /* LABWC_MENU_H */ diff --git a/src/action.c b/src/action.c index 73ef48a5..493ba734 100644 --- a/src/action.c +++ b/src/action.c @@ -665,6 +665,11 @@ show_menu(struct server *server, struct view *view, return; } + /* Need to refresh to show current windows and recalculate width */ + if (!strcasecmp(menu_name, "client-list-combined-menu")) { + update_client_list_combined_menu(menu->server); + } + int x = server->seat.cursor->x; int y = server->seat.cursor->y; diff --git a/src/menu/menu.c b/src/menu/menu.c index f8653d64..321826f5 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -23,6 +23,8 @@ #include "common/string-helpers.h" #include "labwc.h" #include "menu/menu.h" +#include "workspaces.h" +#include "view.h" #include "node.h" #include "theme.h" @@ -908,6 +910,73 @@ menu_hide_submenu(struct server *server, const char *id) } } +static void +init_client_list_combined_menu(struct server *server) +{ + /* Just create placeholder. Contents will be created when launched */ + menu_create(server, "client-list-combined-menu", ""); +} + +/* + * This is client-list-combined-menu an internal menu similar to root-menu and + * client-menu. + * + * This will look at workspaces and produce a menu with the workspace name as a + * separator label and the titles of the view, if any, below each workspace + * name. Active view is indicated by "*" preceeding title. + */ +void +update_client_list_combined_menu(struct server *server) +{ + struct menu *menu = menu_get_by_id(server, "client-list-combined-menu"); + + if (!menu) { + /* Menu is created on compositor startup/reconfigure */ + wlr_log(WLR_ERROR, "client-list-combined-menu does not exist"); + return; + } + + struct menuitem *item, *next; + wl_list_for_each_safe(item, next, &menu->menuitems, link) { + item_destroy(item); + } + + menu->size.height = 0; + + struct workspace *workspace; + struct view *view; + struct buf buffer = BUF_INIT; + + wl_list_for_each(workspace, &server->workspaces, link) { + buf_add_fmt(&buffer, workspace == server->workspace_current ? ">%s<" : "%s", + workspace->name); + current_item = separator_create(menu, buffer.data); + buf_clear(&buffer); + + wl_list_for_each(view, &server->views, link) { + if (view->workspace == workspace) { + if (view == server->active_view) { + buf_add(&buffer, "*"); + } + buf_add(&buffer, view_get_string_prop(view, "title")); + + current_item = item_create(menu, buffer.data, /*show arrow*/ false); + current_item->id = xstrdup(menu->id); + current_item->client_list_view = view; + fill_item("name.action", "Focus"); + fill_item("name.action", "Raise"); + buf_clear(&buffer); + } + } + current_item = item_create(menu, _("Go there..."), /*show arrow*/ false); + current_item->id = xstrdup(menu->id); + fill_item("name.action", "GoToDesktop"); + fill_item("to.action", workspace->name); + } + buf_reset(&buffer); + menu_update_width(menu); +} + static void init_rootmenu(struct server *server) { @@ -986,6 +1055,7 @@ menu_init(struct server *server) parse_xml("menu.xml", server); init_rootmenu(server); init_windowmenu(server); + init_client_list_combined_menu(server); post_processing(server); validate(server); } @@ -1467,7 +1537,13 @@ menu_execute_item(struct menuitem *item) * menu_close() and destroy_pipemenus() which we have to handle * before/after action_run() respectively. */ - actions_run(item->parent->triggered_by_view, server, &item->actions, 0); + if (item->id && !strcmp(item->id, "client-list-combined-menu") + && item->client_list_view) { + actions_run(item->client_list_view, server, &item->actions, 0); + } else { + actions_run(item->parent->triggered_by_view, server, + &item->actions, 0); + } server->menu_current = NULL; destroy_pipemenus(server);