From 33b98b19aa543b5b16f258d70b8f2b01ee7a34b9 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Sun, 26 Mar 2023 10:57:53 +0100 Subject: [PATCH] action: support SendToDesktop 'follow' option Make follow 'true' by default as per Openbox 3.6 specification. Note: this is an interface change. Fixes: issue #841 --- docs/labwc-actions.5.scd | 16 +++++++++---- docs/menu.xml | 2 -- include/action.h | 3 +++ src/action.c | 50 +++++++++++++++++++++++++++++++++++----- src/config/rcxml.c | 5 ++++ src/menu/menu.c | 8 +++---- 6 files changed, 67 insertions(+), 17 deletions(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index b5e7d2bc..164f1540 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -86,13 +86,19 @@ Actions are used in menus and keyboard/mouse bindings. any windows, the cursor is centered on the given output. ** - Switch to workspace. Supported values are "last", "left", "right" or the - full name of a workspace or its index (starting at 1) as configured in - rc.xml. + Switch to workspace. -** + *to* The workspace to switch to. Supported values are "last", "left", + "right" or the full name of a workspace or its index (starting at 1) + as configured in rc.xml. + +** Send active window to workspace. - Supported values are the same as for GoToDesktop. + + *to* The workspace to send the window to. Supported values are the same + as for GoToDesktop. + + *follow* [yes|no] Also switch to the specified workspace. Default yes. ** If used as the only action for a binding: clear an earlier defined binding. diff --git a/docs/menu.xml b/docs/menu.xml index 87f4ed82..01b96037 100644 --- a/docs/menu.xml +++ b/docs/menu.xml @@ -25,11 +25,9 @@ - - diff --git a/include/action.h b/include/action.h index 96697597..c26f15a8 100644 --- a/include/action.h +++ b/include/action.h @@ -19,7 +19,10 @@ struct action { }; struct action *action_create(const char *action_name); + void action_arg_add_str(struct action *action, char *key, const char *value); +void action_arg_add_bool(struct action *action, char *key, bool value); + void action_arg_from_xml_node(struct action *action, char *nodename, char *content); bool actions_contain_toggle_keybinds(struct wl_list *action_list); diff --git a/src/action.c b/src/action.c index bea2d896..c8b92b6a 100644 --- a/src/action.c +++ b/src/action.c @@ -7,6 +7,7 @@ #include #include #include "action.h" +#include "common/get-bool.h" #include "common/list.h" #include "common/mem.h" #include "common/spawn.h" @@ -20,6 +21,7 @@ enum action_arg_type { LAB_ACTION_ARG_STR = 0, + LAB_ACTION_ARG_BOOL, }; struct action_arg { @@ -34,6 +36,11 @@ struct action_arg_str { char *value; }; +struct action_arg_bool { + struct action_arg base; + bool value; +}; + enum action_type { ACTION_TYPE_INVALID = 0, ACTION_TYPE_NONE, @@ -117,7 +124,10 @@ action_arg_from_xml_node(struct action *action, char *nodename, char *content) action_arg_add_str(action, NULL, content); } else if (!strcmp(nodename, "to.action")) { /* GoToDesktop, SendToDesktop */ - action_arg_add_str(action, NULL, content); + action_arg_add_str(action, "to", content); + } else if (!strcmp(nodename, "follow.action")) { + /* SendToDesktop */ + action_arg_add_bool(action, "follow", get_bool(content)); } else if (!strcmp(nodename, "region.action")) { /* SnapToRegion */ action_arg_add_str(action, NULL, content); @@ -134,6 +144,13 @@ action_str_from_arg(struct action_arg *arg) return ((struct action_arg_str *)arg)->value; } +static bool +action_bool_from_arg(struct action_arg *arg) +{ + assert(arg->type == LAB_ACTION_ARG_BOOL); + return ((struct action_arg_bool *)arg)->value; +} + static struct action_arg * action_get_first_arg(struct action *action) { @@ -442,16 +459,25 @@ actions_run(struct view *activator, struct server *server, } break; case ACTION_TYPE_SEND_TO_DESKTOP: - if (!arg) { - wlr_log(WLR_ERROR, "Missing argument for SendToDesktop"); - break; - } if (view) { + struct action_arg *arg; + char *target_name = NULL; struct workspace *target; - char *target_name = action_str_from_arg(arg); + bool follow = true; + + wl_list_for_each(arg, &action->args, link) { + if (!strcmp("to", arg->key)) { + target_name = action_str_from_arg(arg); + } else if (!strcmp("follow", arg->key)) { + follow = action_bool_from_arg(arg); + } + } target = workspaces_find(view->workspace, target_name); if (target) { view_move_to_workspace(view, target); + if (follow) { + workspaces_switch_to(target); + } } } break; @@ -517,3 +543,15 @@ action_arg_add_str(struct action *action, char *key, const char *value) arg->value = xstrdup(value); wl_list_append(&action->args, &arg->base.link); } + +void +action_arg_add_bool(struct action *action, char *key, bool value) +{ + struct action_arg_bool *arg = znew(*arg); + arg->base.type = LAB_ACTION_ARG_BOOL; + if (key) { + arg->base.key = xstrdup(key); + } + arg->value = value; + wl_list_append(&action->args, &arg->base.link); +} diff --git a/src/config/rcxml.c b/src/config/rcxml.c index d0321d3d..78515e69 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -120,6 +120,11 @@ fill_keybind(char *nodename, char *content) wlr_log(WLR_ERROR, "expect element first. " "nodename: '%s' content: '%s'", nodename, content); } else { + /* + * Here we deal with action sub-elements such as , , + * , and so on. This is common to key- and + * mousebinds. + */ action_arg_from_xml_node(current_keybind_action, nodename, content); } } diff --git a/src/menu/menu.c b/src/menu/menu.c index 3bc74a62..9ad4a153 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -664,15 +664,15 @@ init_windowmenu(struct server *server) /* Workspace sub-menu */ struct menu *workspace_menu = menu_create(server, "workspaces", ""); current_item = item_create(workspace_menu, _("Move left"), false); + /* + * is true by default so + * GoToDesktop will be called as part of the action. + */ fill_item("name.action", "SendToDesktop"); fill_item("to.action", "left"); - fill_item("name.action", "GoToDesktop"); - fill_item("to.action", "left"); current_item = item_create(workspace_menu, _("Move right"), false); fill_item("name.action", "SendToDesktop"); fill_item("to.action", "right"); - fill_item("name.action", "GoToDesktop"); - fill_item("to.action", "right"); current_item = item_create(menu, _("Workspace"), true); current_item->submenu = workspace_menu; -- 2.52.0