From f2c3f83041fce356165bd4124fd4f388bf06570d Mon Sep 17 00:00:00 2001 From: Tomi Ollila Date: Sun, 14 May 2023 20:44:59 +0300 Subject: [PATCH] action: support {Go,Send}ToDesktop 'wrap' option Make wrap 'true' by default for both GoToDesktop and SendToDesktop, in order to default to the current behaviour, and to stay consistent with Openbox behaviour. --- docs/labwc-actions.5.scd | 10 ++++++++-- docs/rc.xml.all | 4 ++-- include/workspaces.h | 3 ++- src/action.c | 21 +++++++++++++++------ src/workspaces.c | 22 +++++++++++++++------- 5 files changed, 42 insertions(+), 18 deletions(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 75595591..0e47d8bb 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -91,14 +91,17 @@ Actions are used in menus and keyboard/mouse bindings. to the center of the window. If the given output does not contain any windows, the cursor is centered on the given output. -** +** 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. -** + *wrap* [yes|no] Wrap around from last desktop to first, and vice + versa. Default yes. + +** Send active window to workspace. *to* The workspace to send the window to. Supported values are the same @@ -106,6 +109,9 @@ Actions are used in menus and keyboard/mouse bindings. *follow* [yes|no] Also switch to the specified workspace. Default yes. + *wrap* [yes|no] Wrap around from last desktop to first, and vice + versa. Default yes. + ** If used as the only action for a binding: clear an earlier defined binding. diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 8ee88024..d4883ed0 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -340,10 +340,10 @@ - + - + diff --git a/include/workspaces.h b/include/workspaces.h index a8a4ee7b..e533f7f9 100644 --- a/include/workspaces.h +++ b/include/workspaces.h @@ -23,6 +23,7 @@ void workspaces_init(struct server *server); void workspaces_switch_to(struct workspace *target); void workspaces_destroy(struct server *server); void workspaces_osd_hide(struct seat *seat); -struct workspace *workspaces_find(struct workspace *anchor, const char *name); +struct workspace *workspaces_find(struct workspace *anchor, const char *name, + bool wrap); #endif /* LABWC_WORKSPACES_H */ diff --git a/src/action.c b/src/action.c index f9b67979..0134270a 100644 --- a/src/action.c +++ b/src/action.c @@ -179,6 +179,10 @@ action_arg_from_xml_node(struct action *action, char *nodename, char *content) action_arg_add_str(action, argument, content); goto cleanup; } + if (!strcmp(argument, "wrap")) { + action_arg_add_bool(action, argument, parse_bool(content, true)); + goto cleanup; + } break; case ACTION_TYPE_SNAP_TO_REGION: if (!strcmp(argument, "region")) { @@ -546,18 +550,21 @@ actions_run(struct view *activator, struct server *server, resize_edges); } break; - case ACTION_TYPE_GO_TO_DESKTOP: - if (!arg) { - wlr_log(WLR_ERROR, "Missing argument for GoToDesktop"); + case ACTION_TYPE_GO_TO_DESKTOP: { + const char *to = get_arg_value_str(action, "to", NULL); + if (!to) { + wlr_log(WLR_ERROR, + "Missing 'to' argument for GoToDesktop"); break; } + bool wrap = get_arg_value_bool(action, "wrap", true); struct workspace *target; - const char *target_name = action_str_from_arg(arg); - target = workspaces_find(server->workspace_current, target_name); + target = workspaces_find(server->workspace_current, to, wrap); if (target) { workspaces_switch_to(target); } break; + } case ACTION_TYPE_SEND_TO_DESKTOP: if (view) { const char *to = get_arg_value_str(action, "to", NULL); @@ -567,7 +574,9 @@ actions_run(struct view *activator, struct server *server, break; } bool follow = get_arg_value_bool(action, "follow", true); - struct workspace *target = workspaces_find(view->workspace, to); + bool wrap = get_arg_value_bool(action, "wrap", true); + struct workspace *target; + target = workspaces_find(view->workspace, to, wrap); if (target) { view_move_to_workspace(view, target); if (follow) { diff --git a/src/workspaces.c b/src/workspaces.c index 193fd6da..b9560fd0 100644 --- a/src/workspaces.c +++ b/src/workspaces.c @@ -172,22 +172,30 @@ add_workspace(struct server *server, const char *name) } static struct workspace * -get_prev(struct workspace *current, struct wl_list *workspaces) +get_prev(struct workspace *current, struct wl_list *workspaces, bool wrap) { struct wl_list *target_link = current->link.prev; if (target_link == workspaces) { - /* Current workspace is the first one, roll over */ + /* Current workspace is the first one */ + if (!wrap) { + return NULL; + } + /* Roll over */ target_link = target_link->prev; } return wl_container_of(target_link, current, link); } static struct workspace * -get_next(struct workspace *current, struct wl_list *workspaces) +get_next(struct workspace *current, struct wl_list *workspaces, bool wrap) { struct wl_list *target_link = current->link.next; if (target_link == workspaces) { - /* Current workspace is the last one, roll over */ + /* Current workspace is the last one */ + if (!wrap) { + return NULL; + } + /* Roll over */ target_link = target_link->next; } return wl_container_of(target_link, current, link); @@ -304,7 +312,7 @@ workspaces_osd_hide(struct seat *seat) } struct workspace * -workspaces_find(struct workspace *anchor, const char *name) +workspaces_find(struct workspace *anchor, const char *name, bool wrap) { assert(anchor); if (!name) { @@ -324,9 +332,9 @@ workspaces_find(struct workspace *anchor, const char *name) } else if (!strcasecmp(name, "last")) { return anchor->server->workspace_last; } else if (!strcasecmp(name, "left")) { - return get_prev(anchor, workspaces); + return get_prev(anchor, workspaces, wrap); } else if (!strcasecmp(name, "right")) { - return get_next(anchor, workspaces); + return get_next(anchor, workspaces, wrap); } else { wl_list_for_each(target, workspaces, link) { if (!strcasecmp(target->name, name)) { -- 2.52.0