swaywm / sway

i3-compatible Wayland compositor
https://swaywm.org
MIT License
14.45k stars 1.1k forks source link

Add --no-wrap flag to next/prev[_on_output] #6750

Open Lykos153 opened 2 years ago

Lykos153 commented 2 years ago
ammgws commented 2 years ago

It's been "accepted" by i3 so if someone does the work to implement it there then it can be accepted over here as well for i3-compat reasons. Still requires someone to do the work though, but it might be trivial enough for you to give it ago.

https://github.com/i3/i3/issues/3900

minus7 commented 2 years ago

I quickly hacked it in, but getting it in there properly as --no-wrap will require some refactoring

untested patch ```patch From 9b0393234beb5b6bc872cdc0577c9bedaa4dd692 Mon Sep 17 00:00:00 2001 From: minus Date: Sun, 21 Aug 2022 15:56:00 +0200 Subject: [PATCH] Add prev/next_on_output no-wrap variants --- common/util.c | 6 ++++++ include/sway/tree/workspace.h | 4 ++-- include/util.h | 5 +++++ sway/tree/workspace.c | 28 +++++++++++++++++----------- 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/common/util.c b/common/util.c index 5d4c0673..5f676d8b 100644 --- a/common/util.c +++ b/common/util.c @@ -14,6 +14,12 @@ int wrap(int i, int max) { return ((i % max) + max) % max; } +int clamp(int i, int max) { + if (i < 0) return 0; + else if (i > max) return max; + else return i; +} + bool parse_color(const char *color, uint32_t *result) { if (color[0] == '#') { ++color; diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index b3d93a81..5f43c8a0 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -69,11 +69,11 @@ struct sway_workspace *workspace_by_number(const char* name); struct sway_workspace *workspace_by_name(const char*); -struct sway_workspace *workspace_output_next(struct sway_workspace *current); +struct sway_workspace *workspace_output_next(struct sway_workspace *current, bool wraparound); struct sway_workspace *workspace_next(struct sway_workspace *current); -struct sway_workspace *workspace_output_prev(struct sway_workspace *current); +struct sway_workspace *workspace_output_prev(struct sway_workspace *current, bool wraparound); struct sway_workspace *workspace_prev(struct sway_workspace *current); diff --git a/include/util.h b/include/util.h index f887d489..2e8fbc88 100644 --- a/include/util.h +++ b/include/util.h @@ -34,6 +34,11 @@ int parse_movement_amount(int argc, char **argv, */ int wrap(int i, int max); +/** + * Clamp i into the range [0, max] + */ +int clamp(int i, int max); + /** * Given a string that represents an RGB(A) color, result will be set to a * uint32_t version of the color, as long as it is valid. If it is invalid, diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index c84320bd..bd103fd8 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -361,11 +361,15 @@ struct sway_workspace *workspace_by_name(const char *name) { if (current && strcmp(name, "prev") == 0) { return workspace_prev(current); } else if (current && strcmp(name, "prev_on_output") == 0) { - return workspace_output_prev(current); + return workspace_output_prev(current, true); + } else if (current && strcmp(name, "prev_on_output_nowrap") == 0) { + return workspace_output_prev(current, false); } else if (current && strcmp(name, "next") == 0) { return workspace_next(current); } else if (current && strcmp(name, "next_on_output") == 0) { - return workspace_output_next(current); + return workspace_output_next(current, true); + } else if (current && strcmp(name, "next_on_output_nowrap") == 0) { + return workspace_output_next(current, false); } else if (strcmp(name, "current") == 0) { return current; } else if (strcasecmp(name, "back_and_forth") == 0) { @@ -523,12 +527,12 @@ struct sway_workspace *workspace_next(struct sway_workspace *workspace) { } /** - * Get the previous or next workspace on the specified output. Wraps around at - * the end and beginning. If next is false, the previous workspace is returned, - * otherwise the next one is returned. + * Get the previous or next workspace on the specified output. Stops at the + * first and last workspace if wraparound is false, otherwise wraps around at + * the end and beginning. */ static struct sway_workspace *workspace_output_prev_next_impl( - struct sway_output *output, int dir) { + struct sway_output *output, int dir, bool wraparound) { struct sway_seat *seat = input_manager_current_seat(); struct sway_workspace *workspace = seat_get_focused_workspace(seat); if (!workspace) { @@ -538,17 +542,19 @@ static struct sway_workspace *workspace_output_prev_next_impl( } int index = list_find(output->workspaces, workspace); - size_t new_index = wrap(index + dir, output->workspaces->length); + size_t new_index = wraparound + ? wrap(index + dir, output->workspaces->length) + : clamp(index + dir, output->workspaces->length); return output->workspaces->items[new_index]; } -struct sway_workspace *workspace_output_next(struct sway_workspace *current) { - return workspace_output_prev_next_impl(current->output, 1); +struct sway_workspace *workspace_output_next(struct sway_workspace *current, bool wraparound) { + return workspace_output_prev_next_impl(current->output, 1, wraparound); } -struct sway_workspace *workspace_output_prev(struct sway_workspace *current) { - return workspace_output_prev_next_impl(current->output, -1); +struct sway_workspace *workspace_output_prev(struct sway_workspace *current, bool wraparound) { + return workspace_output_prev_next_impl(current->output, -1, wraparound); } struct sway_workspace *workspace_auto_back_and_forth( -- 2.37.2 ```
Inc0n commented 1 year ago

for reference, in i3 one can use focus_wrapping no to disable focus wrapping

Vladimir-csp commented 5 months ago

It would be great to have some way of separate wrapping control for directional and sequential (previous/next) focus changes. Wrapping control on focus command itself would be even more universal solution.