From 710f27d0d2a33e937d5b8dd8c9342b19fa04ebe9 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 29 Jul 2018 10:33:21 +0100 Subject: commands: allow "first", "last", "newest" and "recent" as values for urgent criteria --- sway/sway.5.scd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sway/sway.5.scd') diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 82df38e3..2d35f5d0 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -612,7 +612,8 @@ The following attributes may be matched with: currently focused window. *urgent* - Compares the urgent state of the window. Can be "latest" or "oldest". + Compares the urgent state of the window. Can be "first", "last", "latest", + "newest", "oldest" or "recent". *window\_role* Compare against the window role (WM\_WINDOW\_ROLE). Can be a regular -- cgit v1.2.3 From 11ac66d6fef118077731fccdaecc350257b8942a Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 29 Jul 2018 11:16:28 +0100 Subject: commands: allow __focused__ for con_id criterion --- sway/criteria.c | 15 ++++++++++++--- sway/sway.5.scd | 4 +++- 2 files changed, 15 insertions(+), 4 deletions(-) (limited to 'sway/sway.5.scd') diff --git a/sway/criteria.c b/sway/criteria.c index dd995c4b..2fa9878b 100644 --- a/sway/criteria.c +++ b/sway/criteria.c @@ -361,8 +361,17 @@ static char *get_focused_prop(enum criteria_token token) { } } break; - case T_CON_ID: // These do not support __focused__ - case T_CON_MARK: + case T_CON_ID: + if (view->swayc == NULL) { + return NULL; + } + size_t id = view->swayc->id; + int len = snprintf(NULL, 0, "%zu", id) + 1; + char *id_str = malloc(len); + snprintf(id_str, len, "%zu", id); + value = id_str; + break; + case T_CON_MARK: // These do not support __focused__ case T_FLOATING: #ifdef HAVE_XWAYLAND case T_ID: @@ -425,7 +434,7 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { case T_CON_ID: criteria->con_id = strtoul(effective_value, &endptr, 10); if (*endptr != 0) { - error = strdup("The value for 'con_id' should be numeric"); + error = strdup("The value for 'con_id' should be '__focused__' or numeric"); } break; case T_CON_MARK: diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 2d35f5d0..b639653a 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -582,7 +582,9 @@ The following attributes may be matched with: the currently focused window. *con\_id* - Compare against the internal container ID, which you can find via IPC. + Compare against the internal container ID, which you can find via IPC. If + value is \_\_focused\_\_, then the id must be the same as that of the + currently focused window. *con\_mark* Compare against the window marks. Can be a regular expression. -- cgit v1.2.3 From be64c466245d4c537a70484abfe21adc9d60f3c5 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 29 Jul 2018 12:27:34 +0100 Subject: commands: complete layout implementation --- sway/commands/layout.c | 76 ++++++++++++++++++++++++++++++++++++++++---------- sway/sway.5.scd | 12 ++++++-- 2 files changed, 70 insertions(+), 18 deletions(-) (limited to 'sway/sway.5.scd') diff --git a/sway/commands/layout.c b/sway/commands/layout.c index c446f1f9..ec170591 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -1,3 +1,4 @@ +#include #include #include #include "sway/commands.h" @@ -5,6 +6,26 @@ #include "sway/tree/container.h" #include "log.h" +static bool parse_layout_string(char *s, enum sway_container_layout *ptr) { + if (strcasecmp(s, "splith") == 0) { + *ptr = L_HORIZ; + } else if (strcasecmp(s, "splitv") == 0) { + *ptr = L_VERT; + } else if (strcasecmp(s, "tabbed") == 0) { + *ptr = L_TABBED; + } else if (strcasecmp(s, "stacking") == 0) { + *ptr = L_STACKED; + } else { + return false; + } + return true; +} + +static const char* expected_syntax = + "Expected 'layout default|tabbed|stacking|splitv|splith' or " + "'layout toggle [split|all]' or " + "'layout toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]...'"; + struct cmd_results *cmd_layout(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { @@ -23,30 +44,55 @@ struct cmd_results *cmd_layout(int argc, char **argv) { if (strcasecmp(argv[0], "default") == 0) { parent->layout = parent->prev_layout; - if (parent->layout == L_NONE) { - parent->layout = container_get_default_layout(parent); - } } else { if (parent->layout != L_TABBED && parent->layout != L_STACKED) { parent->prev_layout = parent->layout; } - if (strcasecmp(argv[0], "splith") == 0) { - parent->layout = L_HORIZ; - } else if (strcasecmp(argv[0], "splitv") == 0) { - parent->layout = L_VERT; - } else if (strcasecmp(argv[0], "tabbed") == 0) { - parent->layout = L_TABBED; - } else if (strcasecmp(argv[0], "stacking") == 0) { - parent->layout = L_STACKED; - } else if (strcasecmp(argv[0], "toggle") == 0 && argc == 2 && strcasecmp(argv[1], "split") == 0) { - if (parent->layout == L_HORIZ) { - parent->layout = L_VERT; + bool assigned_directly = parse_layout_string(argv[0], &parent->layout); + if (!assigned_directly && 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; + } else if (argc == 2) { + if (strcasecmp(argv[1], "all") == 0) { + parent->layout = + parent->layout == L_HORIZ ? L_VERT : + 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; + } else { + return cmd_results_new(CMD_INVALID, "layout", expected_syntax); + } } else { - parent->layout = L_HORIZ; + 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) { + break; + } + } + for (int i = curr + 1; i != curr; ++i) { + // cycle round to find next valid layout + if (i >= argc) { + i = 1; + } + if (parse_layout_string(argv[i], &parent->layout)) { + break; + } // invalid layout strings are silently ignored + } } + } else { + return cmd_results_new(CMD_INVALID, "layout", expected_syntax); } } + if (parent->layout == L_NONE) { + parent->layout = container_get_default_layout(parent); + } container_notify_subtree_changed(parent); arrange_windows(parent); diff --git a/sway/sway.5.scd b/sway/sway.5.scd index b639653a..a580c7d6 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -111,11 +111,17 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *fullscreen* Toggles fullscreen for the focused view. -*layout* splith|splitv|stacking|tabbed +*layout* default|splith|splitv|stacking|tabbed Sets the layout mode of the focused container. -*layout* toggle split - Switches the focused container between the splitv and splith layouts. +*layout* toggle [split|all] + Cycles the layout mode of the focused container though a preset list of + layouts. If no argument is given, then it cycles through stacking, tabbed + and the last split layout. If "split" is given, then it cycles through + splith and splitv. If "all" is given, then it cycles through every layout. + +*layout* toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]... + Cycles the layout mode of the focused container through a list of layouts. *move* left|right|up|down [] Moves the focused container in the direction specified. If the container, -- cgit v1.2.3 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 --- include/sway/tree/view.h | 5 ++ sway/commands/move.c | 138 ++++++++++++++++++++++++++--------------------- sway/sway.5.scd | 17 ++++-- sway/tree/view.c | 9 ++++ 4 files changed, 103 insertions(+), 66 deletions(-) (limited to 'sway/sway.5.scd') diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 37fd02bc..4a3f01e7 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -315,6 +315,11 @@ void view_update_title(struct sway_view *view, bool force); */ void view_execute_criteria(struct sway_view *view); +/** + * Find any view that has the given mark and return it. + */ +struct sway_view *view_find_mark(char *mark); + /** * Find any view that has the given mark and remove the mark from the view. * Returns true if it matched a view. diff --git a/sway/commands/move.c b/sway/commands/move.c index 841da4c4..b80ce936 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -20,6 +20,7 @@ static const char* expected_syntax = "Expected 'move <[px] px>' or " "'move to workspace ' or " "'move to output ' or " + "'move to mark ' or " "'move position mouse'"; static struct sway_container *output_in_direction(const char *direction, @@ -54,19 +55,27 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 4))) { return error; - } else if (strcasecmp(argv[1], "to") == 0 - && strcasecmp(argv[2], "workspace") == 0) { - // move container to workspace x - if (current->type == C_WORKSPACE) { - if (current->children->length == 0) { - return cmd_results_new(CMD_FAILURE, "move", - "Can't move an empty workspace"); - } - current = container_wrap_children(current); - } else if (current->type != C_CONTAINER && current->type != C_VIEW) { + } + + if (current->type == C_WORKSPACE) { + if (current->children->length == 0) { return cmd_results_new(CMD_FAILURE, "move", - "Can only move containers and views."); + "Can't move an empty workspace"); } + current = container_wrap_children(current); + } else if (current->type != C_CONTAINER && current->type != C_VIEW) { + return cmd_results_new(CMD_FAILURE, "move", + "Can only move containers and views."); + } + + struct sway_container *old_parent = current->parent; + struct sway_container *old_ws = container_parent(current, C_WORKSPACE); + struct sway_container *destination = NULL; + + // determine destination + if (strcasecmp(argv[1], "to") == 0 + && strcasecmp(argv[2], "workspace") == 0) { + // move container to workspace x struct sway_container *ws; char *ws_name = NULL; if (argc == 5 && strcasecmp(argv[3], "number") == 0) { @@ -80,8 +89,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, if (config->auto_back_and_forth && prev_workspace_name) { // auto back and forth move - struct sway_container *curr_ws = container_parent(current, C_WORKSPACE); - if (curr_ws->name && strcmp(curr_ws->name, ws_name) == 0) { + 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); @@ -93,63 +101,50 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, ws = workspace_create(NULL, ws_name); } free(ws_name); - struct sway_container *old_parent = current->parent; - struct sway_container *old_ws = container_parent(current, C_WORKSPACE); - struct sway_container *destination = seat_get_focus_inactive( - config->handler_context.seat, ws); - container_move_to(current, destination); - struct sway_container *focus = seat_get_focus_inactive( - config->handler_context.seat, old_parent); - seat_set_focus_warp(config->handler_context.seat, focus, true, false); - container_reap_empty(old_parent); - container_reap_empty(destination->parent); - - // TODO: Ideally we would arrange the surviving parent after reaping, - // but container_reap_empty does not return it, so we arrange the - // workspace instead. - arrange_windows(old_ws); - arrange_windows(destination->parent); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); + destination = seat_get_focus_inactive(config->handler_context.seat, ws); } else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) { - if (current->type == C_WORKSPACE) { - // TODO: Wrap children in a container and move that - return cmd_results_new(CMD_FAILURE, "move", "Unimplemented"); - } else if (current->type != C_CONTAINER - && current->type != C_VIEW) { - return cmd_results_new(CMD_FAILURE, "move", - "Can only move containers and views."); - } struct sway_container *source = container_parent(current, C_OUTPUT); - struct sway_container *destination = output_in_direction(argv[3], + struct sway_container *dest_output = output_in_direction(argv[3], source->sway_output->wlr_output, current->x, current->y); - if (!destination) { + if (!dest_output) { return cmd_results_new(CMD_FAILURE, "move workspace", "Can't find output with name/direction '%s'", argv[3]); } - struct sway_container *focus = seat_get_focus_inactive( - config->handler_context.seat, destination); - if (!focus) { + destination = seat_get_focus_inactive( + config->handler_context.seat, dest_output); + if (!destination) { // We've never been to this output before - focus = destination->children->items[0]; + destination = dest_output->children->items[0]; } - struct sway_container *old_parent = current->parent; - struct sway_container *old_ws = container_parent(current, C_WORKSPACE); - container_move_to(current, focus); - seat_set_focus_warp(config->handler_context.seat, old_parent, true, false); - container_reap_empty(old_parent); - container_reap_empty(focus->parent); + } else if (strcasecmp(argv[1], "to") == 0 + && strcasecmp(argv[2], "mark") == 0) { + struct sway_view *dest_view = view_find_mark(argv[3]); + if (dest_view == NULL) { + return cmd_results_new(CMD_FAILURE, "move", + "Mark '%s' not found", argv[3]); + } + destination = dest_view->swayc; + } else { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } - // TODO: Ideally we would arrange the surviving parent after reaping, - // but container_reap_empty does not return it, so we arrange the - // workspace instead. - arrange_windows(old_ws); - arrange_windows(focus->parent); + // move container, arrange windows and return focus + container_move_to(current, destination); + struct sway_container *focus = + seat_get_focus_inactive(config->handler_context.seat, old_parent); + seat_set_focus_warp(config->handler_context.seat, focus, true, false); + container_reap_empty(old_parent); + container_reap_empty(destination->parent); - return cmd_results_new(CMD_SUCCESS, NULL, NULL); - } - return cmd_results_new(CMD_INVALID, "move", expected_syntax); + // TODO: Ideally we would arrange the surviving parent after reaping, + // but container_reap_empty does not return it, so we arrange the + // workspace instead. + arrange_windows(old_ws); + arrange_windows(destination->parent); + + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } static struct cmd_results *cmd_move_workspace(struct sway_container *current, @@ -243,8 +238,8 @@ static struct cmd_results *move_in_direction(struct sway_container *container, } static const char* expected_position_syntax = - "Expected 'move [absolute] position ' or " - "'move [absolute] position mouse'"; + "Expected 'move [absolute] position [px] [px]' or " + "'move [absolute] position center|mouse'"; static struct cmd_results *move_to_position(struct sway_container *container, int argc, char **argv) { @@ -279,10 +274,18 @@ static struct cmd_results *move_to_position(struct sway_container *container, double ly = seat->cursor->cursor->y - container->height / 2; container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } else if (strcmp(argv[0], "center") == 0) { + struct sway_container *ws = container_parent(container, C_WORKSPACE); + double lx = ws->x + (ws->width - container->width) / 2; + double ly = ws->y + (ws->height - container->height) / 2; + container_floating_move_to(container, lx, ly); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } - if (argc != 2) { + + if (argc < 2) { return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); } + double lx, ly; char *inv; lx = (double)strtol(argv[0], &inv, 10); @@ -290,11 +293,22 @@ static struct cmd_results *move_to_position(struct sway_container *container, return cmd_results_new(CMD_FAILURE, "move", "Invalid position specified"); } + if (strcmp(argv[1], "px") == 0) { + --argc; + ++argv; + } + + if (argc > 3) { + return cmd_results_new(CMD_FAILURE, "move", expected_position_syntax); + } + ly = (double)strtol(argv[1], &inv, 10); - if (*inv != '\0' && strcasecmp(inv, "px") != 0) { + if ((*inv != '\0' && strcasecmp(inv, "px") != 0) || + (argc == 3 && strcmp(argv[2], "px") != 0)) { return cmd_results_new(CMD_FAILURE, "move", "Invalid position specified"); } + container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/sway.5.scd b/sway/sway.5.scd index a580c7d6..8083106b 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -123,18 +123,27 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *layout* toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]... Cycles the layout mode of the focused container through a list of layouts. -*move* left|right|up|down [] +*move* left|right|up|down [ px] Moves the focused container in the direction specified. If the container, the optional _px_ argument specifies how many pixels to move the container. If unspecified, the default is 10 pixels. Pixels are ignored when moving tiled containers. +*move* [absolute] position [px] [px] + Moves the focused container to the specified position. + +*move* [absolute] position center|mouse + Moves the focused container to be centered on the workspace or mouse. + +*move* container|window to mark + Moves the focused container to the specified mark. + *move* container|window to workspace Moves the focused container to the specified workspace. -*move* container|window to workspace prev|next - Moves the focused container to the previous or next workspace on this - output, or if no workspaces remain, the previous or next output. +*move* container|window to workspace prev|next|current + Moves the focused container to the previous, next or current workspace on + this output, or if no workspaces remain, the previous or next output. *move* container|window to workspace prev\_on\_output|next\_on\_output Moves the focused container to the previous or next workspace on this 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 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/sway.5.scd') 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 dd48c8a579918f34c6a3441068e6f4b7e753e09c Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 5 Aug 2018 00:16:21 +0100 Subject: commands: add optional flags to move --- sway/commands/move.c | 97 +++++++++++++++++++++++++++++++++++++--------------- sway/sway.5.scd | 19 ++++++---- 2 files changed, 81 insertions(+), 35 deletions(-) (limited to 'sway/sway.5.scd') diff --git a/sway/commands/move.c b/sway/commands/move.c index b80ce936..d49d6862 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -1,4 +1,5 @@ #define _XOPEN_SOURCE 500 +#include #include #include #include @@ -16,12 +17,11 @@ #include "stringop.h" #include "list.h" -static const char* expected_syntax = +static const char *expected_syntax = "Expected 'move <[px] px>' or " - "'move to workspace ' or " - "'move to output ' or " - "'move to mark ' or " - "'move position mouse'"; + "'move [--no-auto-back-and-forth] [to] workspace ' or " + "'move [--no-auto-back-and-forth] [to] output ' or " + "'move [to] mark '"; static struct sway_container *output_in_direction(const char *direction, struct wlr_output *reference, int ref_lx, int ref_ly) { @@ -53,7 +53,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "move container/window", - EXPECTED_AT_LEAST, 4))) { + EXPECTED_AT_LEAST, 3))) { return error; } @@ -68,26 +68,52 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, "Can only move containers and views."); } + bool no_auto_back_and_forth = false; + while (strcasecmp(argv[0], "--no-auto-back-and-forth") == 0) { + no_auto_back_and_forth = true; + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + ++argv; + } + while (strcasecmp(argv[1], "--no-auto-back-and-forth") == 0) { + no_auto_back_and_forth = true; + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + argv++; + } + + while (strcasecmp(argv[1], "to") == 0) { + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + argv++; + } + struct sway_container *old_parent = current->parent; struct sway_container *old_ws = container_parent(current, C_WORKSPACE); struct sway_container *destination = NULL; // determine destination - if (strcasecmp(argv[1], "to") == 0 - && strcasecmp(argv[2], "workspace") == 0) { + if (strcasecmp(argv[1], "workspace") == 0) { // move container to workspace x struct sway_container *ws; char *ws_name = NULL; - if (argc == 5 && strcasecmp(argv[3], "number") == 0) { + if (strcasecmp(argv[2], "number") == 0) { // move "container to workspace number x" - ws_name = strdup(argv[4]); + 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 + 3, argc - 3); + ws_name = join_args(argv + 2, argc - 2); ws = workspace_by_name(ws_name); } - if (config->auto_back_and_forth && 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 @@ -98,19 +124,23 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, } if (!ws) { + if (strcasecmp(argv[2], "back_and_forth") == 0) { + if (prev_workspace_name) { + ws = workspace_create(NULL, prev_workspace_name); + } + } ws = workspace_create(NULL, ws_name); } free(ws_name); destination = seat_get_focus_inactive(config->handler_context.seat, ws); - } else if (strcasecmp(argv[1], "to") == 0 - && strcasecmp(argv[2], "output") == 0) { + } else if (strcasecmp(argv[1], "output") == 0) { struct sway_container *source = container_parent(current, C_OUTPUT); - struct sway_container *dest_output = output_in_direction(argv[3], + struct sway_container *dest_output = output_in_direction(argv[2], source->sway_output->wlr_output, current->x, current->y); if (!dest_output) { return cmd_results_new(CMD_FAILURE, "move workspace", - "Can't find output with name/direction '%s'", argv[3]); + "Can't find output with name/direction '%s'", argv[2]); } destination = seat_get_focus_inactive( config->handler_context.seat, dest_output); @@ -118,12 +148,11 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, // We've never been to this output before destination = dest_output->children->items[0]; } - } else if (strcasecmp(argv[1], "to") == 0 - && strcasecmp(argv[2], "mark") == 0) { - struct sway_view *dest_view = view_find_mark(argv[3]); + } else if (strcasecmp(argv[1], "mark") == 0) { + struct sway_view *dest_view = view_find_mark(argv[2]); if (dest_view == NULL) { return cmd_results_new(CMD_FAILURE, "move", - "Mark '%s' not found", argv[3]); + "Mark '%s' not found", argv[2]); } destination = dest_view->swayc; } else { @@ -150,20 +179,29 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, static struct cmd_results *cmd_move_workspace(struct sway_container *current, int argc, char **argv) { struct cmd_results *error = NULL; - if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) { + if ((error = checkarg(argc, "move workspace", EXPECTED_AT_LEAST, 2))) { return error; - } else if (strcasecmp(argv[1], "to") != 0 - || strcasecmp(argv[2], "output") != 0) { + } + + while (strcasecmp(argv[1], "to") == 0) { + if (--argc < 3) { + return cmd_results_new(CMD_INVALID, "move", expected_syntax); + } + ++argv; + } + + if (strcasecmp(argv[1], "output") != 0) { return cmd_results_new(CMD_INVALID, "move", expected_syntax); } + struct sway_container *source = container_parent(current, C_OUTPUT); int center_x = current->width / 2 + current->x, center_y = current->height / 2 + current->y; - struct sway_container *destination = output_in_direction(argv[3], + struct sway_container *destination = output_in_direction(argv[2], source->sway_output->wlr_output, center_x, center_y); if (!destination) { return cmd_results_new(CMD_FAILURE, "move workspace", - "Can't find output with name/direction '%s'", argv[3]); + "Can't find output with name/direction '%s'", argv[2]); } if (current->type != C_WORKSPACE) { current = container_parent(current, C_WORKSPACE); @@ -237,7 +275,7 @@ static struct cmd_results *move_in_direction(struct sway_container *container, return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static const char* expected_position_syntax = +static const char *expected_position_syntax = "Expected 'move [absolute] position [px] [px]' or " "'move [absolute] position center|mouse'"; @@ -356,8 +394,11 @@ struct cmd_results *cmd_move(int argc, char **argv) { return move_in_direction(current, MOVE_UP, argc, argv); } else if (strcasecmp(argv[0], "down") == 0) { return move_in_direction(current, MOVE_DOWN, argc, argv); - } else if (strcasecmp(argv[0], "container") == 0 - || strcasecmp(argv[0], "window") == 0) { + } else if ((strcasecmp(argv[0], "container") == 0 + || strcasecmp(argv[0], "window") == 0) || + (strcasecmp(argv[0], "--no-auto-back-and-forth") && + (strcasecmp(argv[0], "container") == 0 + || strcasecmp(argv[0], "window") == 0))) { return cmd_move_container(current, argc, argv); } else if (strcasecmp(argv[0], "workspace") == 0) { return cmd_move_workspace(current, argc, argv); diff --git a/sway/sway.5.scd b/sway/sway.5.scd index 36ce13df..b43cbe8d 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -135,24 +135,29 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *move* [absolute] position center|mouse Moves the focused container to be centered on the workspace or mouse. -*move* container|window to mark +*move* container|window [to] mark Moves the focused container to the specified mark. -*move* container|window to workspace - Moves the focused container to the specified workspace. +*move* [--no-auto-back-and-forth] container|window [to] workspace [number] + Moves the focused container to the specified workspace. The string "number" + is optional and is used to match a workspace with the same number, even if + it has a different name. -*move* container|window to workspace prev|next|current +*move* container|window [to] workspace prev|next|current Moves the focused container to the previous, next or current workspace on this output, or if no workspaces remain, the previous or next output. -*move* container|window to workspace prev\_on\_output|next\_on\_output +*move* container|window [to] workspace prev\_on\_output|next\_on\_output Moves the focused container to the previous or next workspace on this output, wrapping around if already at the first or last workspace. -*move* container|window|workspace to output +*move* container|window [to] workspace back_and_forth + Moves the focused container to previously focused workspace. + +*move* container|window|workspace [to] output Moves the focused container or workspace to the specified output. -*move* container|window|workspace to output up|right|down|left +*move* container|window|workspace [to] output up|right|down|left Moves the focused container or workspace to next output in the specified direction. -- cgit v1.2.3 From 3b1f58e1353f68ea10a3c5325ba4e04fbbe0c6a7 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 5 Aug 2018 00:27:53 +0100 Subject: commands: document focus --- sway/sway.5.scd | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sway/sway.5.scd') diff --git a/sway/sway.5.scd b/sway/sway.5.scd index b43cbe8d..73a01152 100644 --- a/sway/sway.5.scd +++ b/sway/sway.5.scd @@ -84,6 +84,9 @@ They are expected to be used with *bindsym* or at runtime through *swaymsg*(1). *floating* enable|disable|toggle Make focused view floating, non-floating, or the opposite of what it is now. + *focus* + Moves focus to the container that matches the specified criteria. + *focus* up|right|down|left Moves focus to the next container in the specified direction. -- cgit v1.2.3