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)) {