From 69e1a421fc2ccecd93f79c9dd0537671138bb0a9 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Tue, 31 Jul 2018 11:38:34 +0100 Subject: commands: complete move implementation --- sway/tree/view.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sway/tree') diff --git a/sway/tree/view.c b/sway/tree/view.c index 9465b3a1..48bd7ac0 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -891,6 +891,15 @@ static bool find_by_mark_iterator(struct sway_container *con, return con->type == C_VIEW && view_has_mark(con->sway_view, mark); } +struct sway_view *view_find_mark(char *mark) { + struct sway_container *container = container_find(&root_container, + find_by_mark_iterator, mark); + if (!container) { + return NULL; + } + return container->sway_view; +} + bool view_find_and_unmark(char *mark) { struct sway_container *container = container_find(&root_container, find_by_mark_iterator, mark); -- cgit v1.2.3 From 356063b6c084a7c2d4e3e654fe48ec79a102294b Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Wed, 1 Aug 2018 16:03:37 +0100 Subject: commands: fix layout implementation (also better name for previous split layout) --- include/sway/tree/container.h | 2 +- sway/commands/layout.c | 43 ++++++++++++++++++++++++++----------------- sway/tree/layout.c | 4 ++-- sway/tree/workspace.c | 2 +- 4 files changed, 30 insertions(+), 21 deletions(-) (limited to 'sway/tree') diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 44ff9f7d..16a180f8 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -113,7 +113,7 @@ struct sway_container { enum sway_container_type type; enum sway_container_layout layout; - enum sway_container_layout prev_layout; + enum sway_container_layout prev_split_layout; bool is_sticky; diff --git a/sway/commands/layout.c b/sway/commands/layout.c index ec170591..f4e4dda9 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -42,19 +42,16 @@ struct cmd_results *cmd_layout(int argc, char **argv) { parent = parent->parent; } - if (strcasecmp(argv[0], "default") == 0) { - parent->layout = parent->prev_layout; - } else { - if (parent->layout != L_TABBED && parent->layout != L_STACKED) { - parent->prev_layout = parent->layout; - } - - bool assigned_directly = parse_layout_string(argv[0], &parent->layout); - if (!assigned_directly && strcasecmp(argv[0], "toggle") == 0) { + enum sway_container_layout prev = parent->layout; + bool assigned_directly = parse_layout_string(argv[0], &parent->layout); + if (!assigned_directly) { + if (strcasecmp(argv[0], "default") == 0) { + parent->layout = parent->prev_split_layout; + } else if (strcasecmp(argv[0], "toggle") == 0) { if (argc == 1) { parent->layout = parent->layout == L_STACKED ? L_TABBED : - parent->layout == L_TABBED ? parent->prev_layout : L_STACKED; + parent->layout == L_TABBED ? parent->prev_split_layout : L_STACKED; } else if (argc == 2) { if (strcasecmp(argv[1], "all") == 0) { parent->layout = @@ -62,17 +59,20 @@ struct cmd_results *cmd_layout(int argc, char **argv) { parent->layout == L_VERT ? L_STACKED : parent->layout == L_STACKED ? L_TABBED : L_HORIZ; } else if (strcasecmp(argv[1], "split") == 0) { - parent->layout = parent->layout == L_VERT ? L_HORIZ : L_VERT; + parent->layout = + parent->layout == L_HORIZ ? L_VERT : + parent->layout == L_VERT ? L_HORIZ : parent->prev_split_layout; } else { return cmd_results_new(CMD_INVALID, "layout", expected_syntax); } } else { - bool valid; enum sway_container_layout parsed_layout; int curr = 1; for (; curr < argc; curr++) { - valid = parse_layout_string(argv[curr], &parsed_layout); - if (valid && parsed_layout == parent->layout) { + bool valid = parse_layout_string(argv[curr], &parsed_layout); + if ((valid && parsed_layout == parent->layout) || + (strcmp(argv[curr], "split") == 0 && + (parent->layout == L_VERT || parent->layout == L_HORIZ))) { break; } } @@ -83,6 +83,11 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } if (parse_layout_string(argv[i], &parent->layout)) { break; + } else if (strcmp(argv[i], "split") == 0) { + parent->layout = + parent->layout == L_HORIZ ? L_VERT : + parent->layout == L_VERT ? L_HORIZ : parent->prev_split_layout; + break; } // invalid layout strings are silently ignored } } @@ -93,9 +98,13 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if (parent->layout == L_NONE) { parent->layout = container_get_default_layout(parent); } - - container_notify_subtree_changed(parent); - arrange_windows(parent); + if (prev != parent->layout) { + if (prev != L_TABBED && prev != L_STACKED) { + parent->prev_split_layout = prev; + } + container_notify_subtree_changed(parent); + arrange_windows(parent); + } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 07de9664..28cdc71e 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -859,7 +859,7 @@ struct sway_container *container_split(struct sway_container *child, } if (child->type == C_WORKSPACE && child->children->length == 0) { // Special case: this just behaves like splitt - child->prev_layout = child->layout; + child->prev_split_layout = child->layout; child->layout = layout; return child; } @@ -870,7 +870,7 @@ struct sway_container *container_split(struct sway_container *child, remove_gaps(child); - cont->prev_layout = L_NONE; + cont->prev_split_layout = L_NONE; cont->width = child->width; cont->height = child->height; cont->x = child->x; diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index cc225e79..250d5ba7 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -59,7 +59,7 @@ struct sway_container *workspace_create(struct sway_container *output, workspace->width = output->width; workspace->height = output->height; workspace->name = !name ? NULL : strdup(name); - workspace->prev_layout = L_NONE; + workspace->prev_split_layout = L_NONE; workspace->layout = container_get_default_layout(output); struct sway_workspace *swayws = calloc(1, sizeof(struct sway_workspace)); -- cgit v1.2.3 From 85ae121caad02265b95ecea66fa864607575eb31 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 5 Aug 2018 00:05:48 +0100 Subject: commands: complete workspace implementation Allow optional --no-auto-back-and-forth flag, as well as refactoring some logic --- include/sway/tree/workspace.h | 4 +++- sway/commands/workspace.c | 54 ++++++++++++++++++------------------------- sway/sway.5.scd | 5 +++- sway/tree/workspace.c | 42 ++++++++++++++++++++++----------- 4 files changed, 59 insertions(+), 46 deletions(-) (limited to 'sway/tree') diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h index 3337f2c8..239cbbdb 100644 --- a/include/sway/tree/workspace.h +++ b/include/sway/tree/workspace.h @@ -1,6 +1,7 @@ #ifndef _SWAY_WORKSPACE_H #define _SWAY_WORKSPACE_H +#include #include "sway/tree/container.h" struct sway_view; @@ -17,7 +18,8 @@ extern char *prev_workspace_name; char *workspace_next_name(const char *output_name); -bool workspace_switch(struct sway_container *workspace); +bool workspace_switch(struct sway_container *workspace, + bool no_auto_back_and_forth); struct sway_container *workspace_by_number(const char* name); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index e8b37182..f32ede1e 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -17,17 +17,6 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { int output_location = -1; - struct sway_container *current_container = config->handler_context.current_container; - struct sway_container *old_workspace = NULL, *old_output = NULL; - if (current_container) { - if (current_container->type == C_WORKSPACE) { - old_workspace = current_container; - } else { - old_workspace = container_parent(current_container, C_WORKSPACE); - } - old_output = container_parent(current_container, C_OUTPUT); - } - for (int i = 0; i < argc; ++i) { if (strcasecmp(argv[i], "output") == 0) { output_location = i; @@ -57,39 +46,42 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, "workspace", NULL); } + + bool no_auto_back_and_forth = false; + while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) { + no_auto_back_and_forth = true; + if ((error = checkarg(--argc, "workspace", EXPECTED_AT_LEAST, 1))) { + return error; + } + ++argv; + } + + struct sway_container *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { + if (argc < 2) { + cmd_results_new(CMD_INVALID, "workspace", + "Expected workspace number"); + } if (!(ws = workspace_by_number(argv[1]))) { char *name = join_args(argv + 1, argc - 1); ws = workspace_create(NULL, name); free(name); } - } else if (strcasecmp(argv[0], "next") == 0) { - ws = workspace_next(old_workspace); - } else if (strcasecmp(argv[0], "prev") == 0) { - ws = workspace_prev(old_workspace); - } else if (strcasecmp(argv[0], "next_on_output") == 0) { - ws = workspace_output_next(old_output); - } else if (strcasecmp(argv[0], "prev_on_output") == 0) { - ws = workspace_output_prev(old_output); - } else if (strcasecmp(argv[0], "back_and_forth") == 0) { - // if auto_back_and_forth is enabled, workspace_switch will swap - // the workspaces. If we created prev_workspace here, workspace_switch - // would put us back on original workspace. - if (config->auto_back_and_forth) { - ws = old_workspace; - } else if (prev_workspace_name - && !(ws = workspace_by_name(prev_workspace_name))) { - ws = workspace_create(NULL, prev_workspace_name); - } } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { - ws = workspace_create(NULL, name); + if (strcasecmp(argv[0], "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } + } else { + ws = workspace_create(NULL, name); + } } free(name); } - workspace_switch(ws); + workspace_switch(ws, no_auto_back_and_forth); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 8083106b..36ce13df 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -526,7 +526,7 @@ config after the others, or it will be matched instead of the others. state. Using _allow_ or _deny_ controls the window's ability to set itself as urgent. By default, windows are allowed to set their own urgency. -*workspace* [number] +*workspace* [--no-auto-back-and-forth] [number] Switches to the specified workspace. The string "number" is optional and is used to sort workspaces. @@ -537,6 +537,9 @@ config after the others, or it will be matched instead of the others. *workspace* prev\_on\_output|next\_on\_output Switches to the next workspace on the current output. +*workspace* back_and_forth + Switches to the previously focused workspace. + *workspace* output Specifies that workspace _name_ should be shown on the specified _output_. diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 250d5ba7..5e20429b 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -250,20 +250,35 @@ struct sway_container *workspace_by_name(const char *name) { current_workspace = container_parent(focus, C_WORKSPACE); current_output = container_parent(focus, C_OUTPUT); } - if (strcmp(name, "prev") == 0) { - return workspace_prev(current_workspace); - } else if (strcmp(name, "prev_on_output") == 0) { - return workspace_output_prev(current_output); - } else if (strcmp(name, "next") == 0) { - return workspace_next(current_workspace); - } else if (strcmp(name, "next_on_output") == 0) { - return workspace_output_next(current_output); - } else if (strcmp(name, "current") == 0) { - return current_workspace; + + char *name_cpy = strdup(name); + char *first_word = strtok(name_cpy, " "); + if (first_word == NULL) { + first_word = name_cpy; + } + + struct sway_container *ws = NULL; + if (strcmp(first_word, "prev") == 0) { + ws = workspace_prev(current_workspace); + } else if (strcmp(first_word, "prev_on_output") == 0) { + ws = workspace_output_prev(current_output); + } else if (strcmp(first_word, "next") == 0) { + ws = workspace_next(current_workspace); + } else if (strcmp(first_word, "next_on_output") == 0) { + ws = workspace_output_next(current_output); + } else if (strcmp(first_word, "current") == 0) { + ws = current_workspace; + } else if (strcasecmp(first_word, "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = container_find(&root_container, _workspace_by_name, + (void *)prev_workspace_name); + } } else { - return container_find(&root_container, _workspace_by_name, + ws = container_find(&root_container, _workspace_by_name, (void *)name); } + free(name_cpy); + return ws; } /** @@ -364,7 +379,8 @@ struct sway_container *workspace_prev(struct sway_container *current) { return workspace_prev_next_impl(current, false); } -bool workspace_switch(struct sway_container *workspace) { +bool workspace_switch(struct sway_container *workspace, + bool no_auto_back_and_forth) { if (!workspace) { return false; } @@ -379,7 +395,7 @@ bool workspace_switch(struct sway_container *workspace) { active_ws = container_parent(focus, C_WORKSPACE); } - if (config->auto_back_and_forth + if (!no_auto_back_and_forth && config->auto_back_and_forth && active_ws == workspace && prev_workspace_name) { struct sway_container *new_ws = workspace_by_name(prev_workspace_name); -- cgit v1.2.3 From 667b8dcb67d8c3f15b52f59d228bb3146a5cdb30 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Mon, 6 Aug 2018 10:43:09 +0100 Subject: commands: check for special workspaces in workspace & move commands --- sway/commands/move.c | 60 +++++++++++++++++++++++++++-------------------- sway/commands/workspace.c | 18 ++++++++------ sway/tree/workspace.c | 39 +++++++++++------------------- 3 files changed, 59 insertions(+), 58 deletions(-) (limited to 'sway/tree') diff --git a/sway/commands/move.c b/sway/commands/move.c index d49d6862..500151f7 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -99,40 +99,48 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, if (strcasecmp(argv[1], "workspace") == 0) { // move container to workspace x struct sway_container *ws; - char *ws_name = NULL; - if (strcasecmp(argv[2], "number") == 0) { - // move "container to workspace number x" - if (argc < 4) { - return cmd_results_new(CMD_INVALID, "move", expected_syntax); + if (strcasecmp(argv[2], "next") == 0 || + strcasecmp(argv[2], "prev") == 0 || + strcasecmp(argv[2], "next_on_output") == 0 || + strcasecmp(argv[2], "prev_on_output") == 0 || + strcasecmp(argv[2], "back_and_forth") == 0 || + strcasecmp(argv[2], "current") == 0) { + ws = workspace_by_name(argv[2]); + } else if (strcasecmp(argv[2], "back_and_forth") == 0) { + if (!(ws = workspace_by_name(argv[0])) && prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); } - ws_name = strdup(argv[3]); - ws = workspace_by_number(ws_name); } else { - ws_name = join_args(argv + 2, argc - 2); - ws = workspace_by_name(ws_name); - } - - if (!no_auto_back_and_forth && config->auto_back_and_forth && - prev_workspace_name) { - // auto back and forth move - if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) { - // if target workspace is the current one - free(ws_name); - ws_name = strdup(prev_workspace_name); + char *ws_name = NULL; + if (strcasecmp(argv[2], "number") == 0) { + // move "container to workspace number x" + if (argc < 4) { + return cmd_results_new(CMD_INVALID, "move", + expected_syntax); + } + ws_name = strdup(argv[3]); + ws = workspace_by_number(ws_name); + } else { + ws_name = join_args(argv + 2, argc - 2); ws = workspace_by_name(ws_name); } - } - if (!ws) { - if (strcasecmp(argv[2], "back_and_forth") == 0) { - if (prev_workspace_name) { - ws = workspace_create(NULL, prev_workspace_name); + if (!no_auto_back_and_forth && config->auto_back_and_forth && + prev_workspace_name) { + // auto back and forth move + if (old_ws->name && strcmp(old_ws->name, ws_name) == 0) { + // if target workspace is the current one + free(ws_name); + ws_name = strdup(prev_workspace_name); + ws = workspace_by_name(ws_name); } } - ws = workspace_create(NULL, ws_name); - } - free(ws_name); + if (!ws) { + ws = workspace_create(NULL, ws_name); + } + free(ws_name); + } destination = seat_get_focus_inactive(config->handler_context.seat, ws); } else if (strcasecmp(argv[1], "output") == 0) { struct sway_container *source = container_parent(current, C_OUTPUT); diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index f32ede1e..f5558bb4 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -68,16 +68,20 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { ws = workspace_create(NULL, name); free(name); } + } else if (strcasecmp(argv[0], "next") == 0 || + strcasecmp(argv[0], "prev") == 0 || + strcasecmp(argv[0], "next_on_output") == 0 || + strcasecmp(argv[0], "prev_on_output") == 0 || + strcasecmp(argv[0], "current") == 0) { + ws = workspace_by_name(argv[0]); + } else if (strcasecmp(argv[0], "back_and_forth") == 0) { + if (!(ws = workspace_by_name(argv[0])) && prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } } else { char *name = join_args(argv, argc); if (!(ws = workspace_by_name(name))) { - if (strcasecmp(argv[0], "back_and_forth") == 0) { - if (prev_workspace_name) { - ws = workspace_create(NULL, prev_workspace_name); - } - } else { - ws = workspace_create(NULL, name); - } + ws = workspace_create(NULL, name); } free(name); } diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 5e20429b..3fcad631 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -251,34 +251,23 @@ struct sway_container *workspace_by_name(const char *name) { current_output = container_parent(focus, C_OUTPUT); } - char *name_cpy = strdup(name); - char *first_word = strtok(name_cpy, " "); - if (first_word == NULL) { - first_word = name_cpy; - } - - struct sway_container *ws = NULL; - if (strcmp(first_word, "prev") == 0) { - ws = workspace_prev(current_workspace); - } else if (strcmp(first_word, "prev_on_output") == 0) { - ws = workspace_output_prev(current_output); - } else if (strcmp(first_word, "next") == 0) { - ws = workspace_next(current_workspace); - } else if (strcmp(first_word, "next_on_output") == 0) { - ws = workspace_output_next(current_output); - } else if (strcmp(first_word, "current") == 0) { - ws = current_workspace; - } else if (strcasecmp(first_word, "back_and_forth") == 0) { - if (prev_workspace_name) { - ws = container_find(&root_container, _workspace_by_name, - (void *)prev_workspace_name); - } + if (strcmp(name, "prev") == 0) { + return workspace_prev(current_workspace); + } else if (strcmp(name, "prev_on_output") == 0) { + return workspace_output_prev(current_output); + } else if (strcmp(name, "next") == 0) { + return workspace_next(current_workspace); + } else if (strcmp(name, "next_on_output") == 0) { + return workspace_output_next(current_output); + } else if (strcmp(name, "current") == 0) { + return current_workspace; + } else if (strcasecmp(name, "back_and_forth") == 0) { + return prev_workspace_name ? container_find(&root_container, + _workspace_by_name, (void *)prev_workspace_name) : NULL; } else { - ws = container_find(&root_container, _workspace_by_name, + return container_find(&root_container, _workspace_by_name, (void *)name); } - free(name_cpy); - return ws; } /** -- cgit v1.2.3 From f7c21451dfa7c4ffdce1307b5856707a0ed40405 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Mon, 6 Aug 2018 12:46:28 +0100 Subject: commands: fix workspace edge cases --- sway/commands/move.c | 9 +++++++-- sway/commands/rename.c | 10 ++++++++++ sway/tree/view.c | 9 ++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) (limited to 'sway/tree') diff --git a/sway/commands/move.c b/sway/commands/move.c index 500151f7..af3dc538 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -107,8 +107,13 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, strcasecmp(argv[2], "current") == 0) { ws = workspace_by_name(argv[2]); } else if (strcasecmp(argv[2], "back_and_forth") == 0) { - if (!(ws = workspace_by_name(argv[0])) && prev_workspace_name) { - ws = workspace_create(NULL, prev_workspace_name); + if (!(ws = workspace_by_name(argv[2]))) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } else { + return cmd_results_new(CMD_FAILURE, "move", + "No workspace was previously active."); + } } } else { char *ws_name = NULL; diff --git a/sway/commands/rename.c b/sway/commands/rename.c index a380ff9c..c6952bbb 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c @@ -61,6 +61,16 @@ struct cmd_results *cmd_rename(int argc, char **argv) { } char *new_name = join_args(argv + argn, argc - argn); + if (strcasecmp(new_name, "next") == 0 || + strcasecmp(new_name, "prev") == 0 || + strcasecmp(new_name, "next_on_output") == 0 || + strcasecmp(new_name, "prev_on_output") == 0 || + strcasecmp(new_name, "back_and_forth") == 0 || + strcasecmp(new_name, "current") == 0) { + free(new_name); + return cmd_results_new(CMD_INVALID, "rename", + "Cannot use special workspace name '%s'", argv[argn]); + } struct sway_container *tmp_workspace = workspace_by_name(new_name); if (tmp_workspace) { free(new_name); diff --git a/sway/tree/view.c b/sway/tree/view.c index 48bd7ac0..faaa53a1 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -456,7 +457,13 @@ static struct sway_container *select_workspace(struct sway_view *view) { if (criteria->type == CT_ASSIGN_WORKSPACE) { ws = workspace_by_name(criteria->target); if (!ws) { - ws = workspace_create(NULL, criteria->target); + if (strcasecmp(criteria->target, "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } + } else { + ws = workspace_create(NULL, criteria->target); + } } break; } else { -- cgit v1.2.3