diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-09-05 09:33:27 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-05 09:33:27 -0400 |
commit | 610eb946171f782165a20614b2d3318b89273990 (patch) | |
tree | 05eec1df1ef48e05b23d273d31143ad32e7632d2 /sway/commands | |
parent | aa2bf98e0442f9bf41a852c2fafee5b0897010a2 (diff) | |
parent | dbf4aa3e33bdee53876c6893b15ac3f224818e7c (diff) |
Merge pull request #2540 from RyanDwyer/typesafety
Implement type safe arguments and demote sway_container
Diffstat (limited to 'sway/commands')
-rw-r--r-- | sway/commands/border.c | 13 | ||||
-rw-r--r-- | sway/commands/floating.c | 18 | ||||
-rw-r--r-- | sway/commands/focus.c | 284 | ||||
-rw-r--r-- | sway/commands/fullscreen.c | 18 | ||||
-rw-r--r-- | sway/commands/gaps.c | 35 | ||||
-rw-r--r-- | sway/commands/hide_edge_borders.c | 4 | ||||
-rw-r--r-- | sway/commands/kill.c | 20 | ||||
-rw-r--r-- | sway/commands/layout.c | 185 | ||||
-rw-r--r-- | sway/commands/mark.c | 7 | ||||
-rw-r--r-- | sway/commands/move.c | 887 | ||||
-rw-r--r-- | sway/commands/opacity.c | 3 | ||||
-rw-r--r-- | sway/commands/reload.c | 2 | ||||
-rw-r--r-- | sway/commands/rename.c | 11 | ||||
-rw-r--r-- | sway/commands/resize.c | 86 | ||||
-rw-r--r-- | sway/commands/scratchpad.c | 42 | ||||
-rw-r--r-- | sway/commands/seat/cursor.c | 4 | ||||
-rw-r--r-- | sway/commands/show_marks.c | 10 | ||||
-rw-r--r-- | sway/commands/smart_gaps.c | 2 | ||||
-rw-r--r-- | sway/commands/split.c | 23 | ||||
-rw-r--r-- | sway/commands/sticky.c | 27 | ||||
-rw-r--r-- | sway/commands/swap.c | 76 | ||||
-rw-r--r-- | sway/commands/title_format.c | 7 | ||||
-rw-r--r-- | sway/commands/unmark.c | 13 | ||||
-rw-r--r-- | sway/commands/urgent.c | 7 | ||||
-rw-r--r-- | sway/commands/workspace.c | 2 |
25 files changed, 867 insertions, 919 deletions
diff --git a/sway/commands/border.c b/sway/commands/border.c index 9502c877..95498b2f 100644 --- a/sway/commands/border.c +++ b/sway/commands/border.c @@ -13,13 +13,12 @@ struct cmd_results *cmd_border(int argc, char **argv) { return error; } - struct sway_container *container = - config->handler_context.current_container; - if (container->type != C_VIEW) { + struct sway_container *container = config->handler_context.container; + if (!container->view) { return cmd_results_new(CMD_INVALID, "border", "Only views can have borders"); } - struct sway_view *view = container->sway_view; + struct sway_view *view = container->view; if (strcmp(argv[0], "none") == 0) { view->border = B_NONE; @@ -38,11 +37,11 @@ struct cmd_results *cmd_border(int argc, char **argv) { view->border_thickness = atoi(argv[1]); } - if (container_is_floating(view->swayc)) { - container_set_geometry_from_floating_view(view->swayc); + if (container_is_floating(view->container)) { + container_set_geometry_from_floating_view(view->container); } - arrange_windows(view->swayc); + arrange_container(view->container); struct sway_seat *seat = input_manager_current_seat(input_manager); if (seat->cursor) { diff --git a/sway/commands/floating.c b/sway/commands/floating.c index 436376e3..d8729094 100644 --- a/sway/commands/floating.c +++ b/sway/commands/floating.c @@ -15,24 +15,23 @@ struct cmd_results *cmd_floating(int argc, char **argv) { if ((error = checkarg(argc, "floating", EXPECTED_EQUAL_TO, 1))) { return error; } - struct sway_container *container = - config->handler_context.current_container; - if (container->type == C_WORKSPACE && container->children->length == 0) { + struct sway_container *container = config->handler_context.container; + struct sway_workspace *workspace = config->handler_context.workspace; + if (!container && workspace->tiling->length == 0) { return cmd_results_new(CMD_INVALID, "floating", "Can't float an empty workspace"); } - if (container->type == C_WORKSPACE) { + if (!container) { // Wrap the workspace's children in a container so we can float it - struct sway_container *workspace = container; - container = workspace_wrap_children(container); + container = workspace_wrap_children(workspace); workspace->layout = L_HORIZ; - seat_set_focus(config->handler_context.seat, container); + seat_set_focus(config->handler_context.seat, &container->node); } // If the container is in a floating split container, // operate on the split container instead of the child. if (container_is_floating_or_child(container)) { - while (container->parent->type != C_WORKSPACE) { + while (container->parent) { container = container->parent; } } @@ -51,8 +50,7 @@ struct cmd_results *cmd_floating(int argc, char **argv) { container_set_floating(container, wants_floating); - struct sway_container *workspace = container_parent(container, C_WORKSPACE); - arrange_windows(workspace); + arrange_workspace(container->workspace); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/focus.c b/sway/commands/focus.c index f342e524..83b8c64a 100644 --- a/sway/commands/focus.c +++ b/sway/commands/focus.c @@ -34,58 +34,49 @@ static bool parse_movement_direction(const char *name, } /** - * Get swayc in the direction of newly entered output. + * Get node in the direction of newly entered output. */ -static struct sway_container *get_swayc_in_output_direction( - struct sway_container *output, enum movement_direction dir, - struct sway_seat *seat) { - if (!output) { - return NULL; - } - - struct sway_container *ws = seat_get_focus_inactive(seat, output); - if (ws->type != C_WORKSPACE) { - ws = container_parent(ws, C_WORKSPACE); - } - - if (ws == NULL) { - wlr_log(WLR_ERROR, "got an output without a workspace"); - return NULL; +static struct sway_node *get_node_in_output_direction( + struct sway_output *output, enum movement_direction dir) { + struct sway_seat *seat = config->handler_context.seat; + struct sway_workspace *ws = output_get_active_workspace(output); + if (ws->fullscreen) { + return seat_get_focus_inactive(seat, &ws->fullscreen->node); } + struct sway_container *container = NULL; - if (ws->children->length > 0) { + if (ws->tiling->length > 0) { switch (dir) { case MOVE_LEFT: if (ws->layout == L_HORIZ || ws->layout == L_TABBED) { // get most right child of new output - return ws->children->items[ws->children->length-1]; + container = ws->tiling->items[ws->tiling->length-1]; } else { - return seat_get_focus_inactive(seat, ws); + container = seat_get_focus_inactive_tiling(seat, ws); } + break; case MOVE_RIGHT: if (ws->layout == L_HORIZ || ws->layout == L_TABBED) { // get most left child of new output - return ws->children->items[0]; + container = ws->tiling->items[0]; } else { - return seat_get_focus_inactive(seat, ws); + container = seat_get_focus_inactive_tiling(seat, ws); } + break; case MOVE_UP: + if (ws->layout == L_VERT || ws->layout == L_STACKED) { + // get most bottom child of new output + container = ws->tiling->items[ws->tiling->length-1]; + } else { + container = seat_get_focus_inactive_tiling(seat, ws); + } + break; case MOVE_DOWN: { - struct sway_container *focused = - seat_get_focus_inactive(seat, ws); - if (focused && focused->parent) { - struct sway_container *parent = focused->parent; - if (parent->layout == L_VERT) { - if (dir == MOVE_UP) { - // get child furthest down on new output - int idx = parent->children->length - 1; - return parent->children->items[idx]; - } else if (dir == MOVE_DOWN) { - // get child furthest up on new output - return parent->children->items[0]; - } - } - return focused; + if (ws->layout == L_VERT || ws->layout == L_STACKED) { + // get most top child of new output + container = ws->tiling->items[0]; + } else { + container = seat_get_focus_inactive_tiling(seat, ws); } break; } @@ -94,151 +85,90 @@ static struct sway_container *get_swayc_in_output_direction( } } - return ws; -} + if (container) { + container = seat_get_focus_inactive_view(seat, &container->node); + return &container->node; + } -static struct sway_container *container_get_in_direction( - struct sway_container *container, struct sway_seat *seat, - enum movement_direction dir) { - struct sway_container *parent = container->parent; + return &ws->node; +} - if (dir == MOVE_CHILD) { - return seat_get_focus_inactive(seat, container); - } +static struct sway_node *node_get_in_direction(struct sway_container *container, + struct sway_seat *seat, enum movement_direction dir) { if (container->is_fullscreen) { if (dir == MOVE_PARENT) { return NULL; } - container = container_parent(container, C_OUTPUT); - parent = container->parent; - } else { - if (dir == MOVE_PARENT) { - if (parent->type == C_OUTPUT || container_is_floating(container)) { - return NULL; - } else { - return parent; - } - } + // Fullscreen container with a direction - go straight to outputs + struct sway_output *output = container->workspace->output; + struct sway_output *new_output = output_get_in_direction(output, dir); + return get_node_in_output_direction(new_output, dir); + } + if (dir == MOVE_PARENT) { + return node_get_parent(&container->node); } struct sway_container *wrap_candidate = NULL; - while (true) { + struct sway_container *current = container; + while (current) { bool can_move = false; int desired; - int idx = list_find(container->parent->children, container); - if (idx == -1) { - return NULL; - } - if (parent->type == C_ROOT) { - enum wlr_direction wlr_dir = 0; - if (!sway_assert(sway_dir_to_wlr(dir, &wlr_dir), - "got invalid direction: %d", dir)) { - return NULL; - } - int lx = container->x + container->width / 2; - int ly = container->y + container->height / 2; - struct wlr_output_layout *layout = - root_container.sway_root->output_layout; - struct wlr_output *wlr_adjacent = - wlr_output_layout_adjacent_output(layout, wlr_dir, - container->sway_output->wlr_output, lx, ly); - struct sway_container *adjacent = - output_from_wlr_output(wlr_adjacent); + int idx = container_sibling_index(current); + enum sway_container_layout parent_layout = + container_parent_layout(current); + list_t *siblings = container_get_siblings(current); - if (!adjacent || adjacent == container) { - if (!wrap_candidate) { - return NULL; - } - return seat_get_focus_inactive_view(seat, wrap_candidate); - } - struct sway_container *next = - get_swayc_in_output_direction(adjacent, dir, seat); - if (next == NULL) { - return NULL; - } - struct sway_container *next_workspace = next; - if (next_workspace->type != C_WORKSPACE) { - next_workspace = container_parent(next_workspace, C_WORKSPACE); - } - sway_assert(next_workspace, "Next container has no workspace"); - if (next_workspace->sway_workspace->fullscreen) { - return seat_get_focus_inactive(seat, - next_workspace->sway_workspace->fullscreen); - } - if (next->children && next->children->length) { - // TODO consider floating children as well - return seat_get_focus_inactive_view(seat, next); - } else { - return next; + if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { + if (parent_layout == L_HORIZ || parent_layout == L_TABBED) { + can_move = true; + desired = idx + (dir == MOVE_LEFT ? -1 : 1); } } else { - if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { - if (parent->layout == L_HORIZ || parent->layout == L_TABBED) { - can_move = true; - desired = idx + (dir == MOVE_LEFT ? -1 : 1); - } - } else { - if (parent->layout == L_VERT || parent->layout == L_STACKED) { - can_move = true; - desired = idx + (dir == MOVE_UP ? -1 : 1); - } + if (parent_layout == L_VERT || parent_layout == L_STACKED) { + can_move = true; + desired = idx + (dir == MOVE_UP ? -1 : 1); } } if (can_move) { - // TODO handle floating - if (desired < 0 || desired >= parent->children->length) { + if (desired < 0 || desired >= siblings->length) { can_move = false; - int len = parent->children->length; + int len = siblings->length; if (config->focus_wrapping != WRAP_NO && !wrap_candidate && len > 1) { if (desired < 0) { - wrap_candidate = parent->children->items[len-1]; + wrap_candidate = siblings->items[len-1]; } else { - wrap_candidate = parent->children->items[0]; + wrap_candidate = siblings->items[0]; } if (config->focus_wrapping == WRAP_FORCE) { - return seat_get_focus_inactive_view(seat, - wrap_candidate); + struct sway_container *c = seat_get_focus_inactive_view( + seat, &wrap_candidate->node); + return &c->node; } } } else { - struct sway_container *desired_con = - parent->children->items[desired]; - wlr_log(WLR_DEBUG, - "cont %d-%p dir %i sibling %d: %p", idx, - container, dir, desired, desired_con); - return seat_get_focus_inactive_view(seat, desired_con); + struct sway_container *desired_con = siblings->items[desired]; + struct sway_container *c = seat_get_focus_inactive_view( + seat, &desired_con->node); + return &c->node; } } - if (!can_move) { - container = parent; - parent = parent->parent; - if (!parent) { - // wrapping is the last chance - if (!wrap_candidate) { - return NULL; - } - return seat_get_focus_inactive_view(seat, wrap_candidate); - } - } + current = current->parent; } -} - -static struct cmd_results *focus_mode(struct sway_container *con, - struct sway_seat *seat, bool floating) { - struct sway_container *ws = con->type == C_WORKSPACE ? - con : container_parent(con, C_WORKSPACE); - // If the container is in a floating split container, - // operate on the split container instead of the child. - if (container_is_floating_or_child(con)) { - while (con->parent->type != C_WORKSPACE) { - con = con->parent; - } + // Check a different output + struct sway_output *output = container->workspace->output; + struct sway_output *new_output = output_get_in_direction(output, dir); + if (new_output) { + return get_node_in_output_direction(new_output, dir); } + return NULL; +} +static struct cmd_results *focus_mode(struct sway_workspace *ws, + struct sway_seat *seat, bool floating) { struct sway_container *new_focus = NULL; if (floating) { new_focus = seat_get_focus_inactive_floating(seat, ws); @@ -246,7 +176,7 @@ static struct cmd_results *focus_mode(struct sway_container *con, new_focus = seat_get_focus_inactive_tiling(seat, ws); } if (new_focus) { - seat_set_focus(seat, new_focus); + seat_set_focus(seat, &new_focus->node); } else { return cmd_results_new(CMD_FAILURE, "focus", "Failed to find a %s container in workspace", @@ -255,14 +185,14 @@ static struct cmd_results *focus_mode(struct sway_container *con, return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static struct cmd_results *focus_output(struct sway_container *con, - struct sway_seat *seat, int argc, char **argv) { +static struct cmd_results *focus_output(struct sway_seat *seat, + int argc, char **argv) { if (!argc) { return cmd_results_new(CMD_INVALID, "focus", "Expected 'focus output <direction|name>'"); } char *identifier = join_args(argv, argc); - struct sway_container *output = output_by_name(identifier); + struct sway_output *output = output_by_name(identifier); if (!output) { enum movement_direction direction; @@ -272,14 +202,13 @@ static struct cmd_results *focus_output(struct sway_container *con, return cmd_results_new(CMD_INVALID, "focus", "There is no output with that name"); } - struct sway_container *focus = seat_get_focus(seat); - focus = container_parent(focus, C_OUTPUT); - output = container_get_in_direction(focus, seat, direction); + struct sway_workspace *ws = seat_get_focused_workspace(seat); + output = output_get_in_direction(ws->output, direction); } free(identifier); if (output) { - seat_set_focus(seat, seat_get_focus_inactive(seat, output)); + seat_set_focus(seat, seat_get_focus_inactive(seat, &output->node)); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); @@ -289,29 +218,32 @@ struct cmd_results *cmd_focus(int argc, char **argv) { if (config->reading || !config->active) { return cmd_results_new(CMD_DEFER, NULL, NULL); } - struct sway_container *con = config->handler_context.current_container; + struct sway_node *node = config->handler_context.node; + struct sway_container *container = config->handler_context.container; + struct sway_workspace *workspace = config->handler_context.workspace; struct sway_seat *seat = config->handler_context.seat; - if (con->type < C_WORKSPACE) { + if (node->type < N_WORKSPACE) { return cmd_results_new(CMD_FAILURE, "focus", "Command 'focus' cannot be used above the workspace level"); } if (argc == 0) { - seat_set_focus(seat, con); + seat_set_focus(seat, node); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } if (strcmp(argv[0], "floating") == 0) { - return focus_mode(con, seat, true); + return focus_mode(workspace, seat, true); } else if (strcmp(argv[0], "tiling") == 0) { - return focus_mode(con, seat, false); + return focus_mode(workspace, seat, false); } else if (strcmp(argv[0], "mode_toggle") == 0) { - return focus_mode(con, seat, !container_is_floating_or_child(con)); + bool floating = container && container_is_floating_or_child(container); + return focus_mode(workspace, seat, !floating); } if (strcmp(argv[0], "output") == 0) { argc--; argv++; - return focus_output(con, seat, argc, argv); + return focus_output(seat, argc, argv); } enum movement_direction direction = 0; @@ -321,8 +253,34 @@ struct cmd_results *cmd_focus(int argc, char **argv) { "or 'focus output <direction|name>'"); } - struct sway_container *next_focus = container_get_in_direction( - con, seat, direction); + if (direction == MOVE_CHILD) { + struct sway_node *focus = seat_get_active_child(seat, node); + if (focus) { + seat_set_focus(seat, focus); + } + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + + if (node->type == N_WORKSPACE) { + if (direction == MOVE_PARENT) { + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + + // Jump to the next output + struct sway_output *new_output = + output_get_in_direction(workspace->output, direction); + if (!new_output) { + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + + struct sway_node *node = + get_node_in_output_direction(new_output, direction); + seat_set_focus(seat, node); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + + struct sway_node *next_focus = + node_get_in_direction(container, seat, direction); if (next_focus) { seat_set_focus(seat, next_focus); } diff --git a/sway/commands/fullscreen.c b/sway/commands/fullscreen.c index ac65dffb..3bbe00c5 100644 --- a/sway/commands/fullscreen.c +++ b/sway/commands/fullscreen.c @@ -12,18 +12,18 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { if ((error = checkarg(argc, "fullscreen", EXPECTED_LESS_THAN, 2))) { return error; } - struct sway_container *container = - config->handler_context.current_container; - if (container->type == C_WORKSPACE && container->children->length == 0) { + struct sway_node *node = config->handler_context.node; + struct sway_container *container = config->handler_context.container; + struct sway_workspace *workspace = config->handler_context.workspace; + if (node->type == N_WORKSPACE && workspace->tiling->length == 0) { return cmd_results_new(CMD_INVALID, "fullscreen", "Can't fullscreen an empty workspace"); } - if (container->type == C_WORKSPACE) { + if (node->type == N_WORKSPACE) { // Wrap the workspace's children in a container so we can fullscreen it - struct sway_container *workspace = container; - container = workspace_wrap_children(container); + container = workspace_wrap_children(workspace); workspace->layout = L_HORIZ; - seat_set_focus(config->handler_context.seat, container); + seat_set_focus(config->handler_context.seat, &container->node); } bool enable = !container->is_fullscreen; @@ -32,9 +32,7 @@ struct cmd_results *cmd_fullscreen(int argc, char **argv) { } container_set_fullscreen(container, enable); - - struct sway_container *workspace = container_parent(container, C_WORKSPACE); - arrange_windows(workspace->parent); + arrange_workspace(workspace); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/gaps.c b/sway/commands/gaps.c index 3906eb70..d676e475 100644 --- a/sway/commands/gaps.c +++ b/sway/commands/gaps.c @@ -2,6 +2,7 @@ #include "sway/commands.h" #include "sway/config.h" #include "sway/tree/arrange.h" +#include "sway/tree/workspace.h" #include "log.h" #include "stringop.h" #include <math.h> @@ -43,7 +44,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "gaps", "gaps edge_gaps on|off|toggle"); } - arrange_windows(&root_container); + arrange_root(); } else { int amount_idx = 0; // the current index in argv enum gaps_op op = GAPS_OP_SET; @@ -124,7 +125,7 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { if (amount_idx == 0) { // gaps <amount> config->gaps_inner = val; config->gaps_outer = val; - arrange_windows(&root_container); + arrange_root(); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } // Other variants. The middle-length variant (gaps inner|outer <amount>) @@ -155,21 +156,27 @@ struct cmd_results *cmd_gaps(int argc, char **argv) { } else { config->gaps_outer = total; } - arrange_windows(&root_container); + arrange_root(); } else { - struct sway_container *c = - config->handler_context.current_container; - if (scope == GAPS_SCOPE_WORKSPACE && c->type != C_WORKSPACE) { - c = container_parent(c, C_WORKSPACE); - } - c->has_gaps = true; - if (inner) { - c->gaps_inner = total; + if (scope == GAPS_SCOPE_WORKSPACE) { + struct sway_workspace *ws = config->handler_context.workspace; + ws->has_gaps = true; + if (inner) { + ws->gaps_inner = total; + } else { + ws->gaps_outer = total; + } + arrange_workspace(ws); } else { - c->gaps_outer = total; + struct sway_container *c = config->handler_context.container; + c->has_gaps = true; + if (inner) { + c->gaps_inner = total; + } else { + c->gaps_outer = total; + } + arrange_workspace(c->workspace); } - - arrange_windows(c->parent ? c->parent : &root_container); } } diff --git a/sway/commands/hide_edge_borders.c b/sway/commands/hide_edge_borders.c index e494f6aa..0a5c7f28 100644 --- a/sway/commands/hide_edge_borders.c +++ b/sway/commands/hide_edge_borders.c @@ -5,8 +5,8 @@ #include "sway/tree/view.h" static void _configure_view(struct sway_container *con, void *data) { - if (con->type == C_VIEW) { - view_autoconfigure(con->sway_view); + if (con->view) { + view_autoconfigure(con->view); } } diff --git a/sway/commands/kill.c b/sway/commands/kill.c index f3fa52f1..85ca0f33 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -2,15 +2,27 @@ #include "log.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" -#include "sway/tree/view.h" #include "sway/tree/container.h" +#include "sway/tree/view.h" +#include "sway/tree/workspace.h" #include "sway/commands.h" +static void close_container_iterator(struct sway_container *con, void *data) { + if (con->view) { + view_close(con->view); + } +} + struct cmd_results *cmd_kill(int argc, char **argv) { - struct sway_container *con = - config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; + struct sway_workspace *ws = config->handler_context.workspace; - container_close(con); + if (con) { + close_container_iterator(con, NULL); + container_for_each_child(con, close_container_iterator, NULL); + } else { + workspace_for_each_container(ws, close_container_iterator, NULL); + } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/layout.c b/sway/commands/layout.c index a06832de..44ce2970 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -4,21 +4,20 @@ #include "sway/commands.h" #include "sway/tree/arrange.h" #include "sway/tree/container.h" +#include "sway/tree/workspace.h" #include "log.h" -static bool parse_layout_string(char *s, enum sway_container_layout *ptr) { +static enum sway_container_layout parse_layout_string(char *s) { if (strcasecmp(s, "splith") == 0) { - *ptr = L_HORIZ; + return L_HORIZ; } else if (strcasecmp(s, "splitv") == 0) { - *ptr = L_VERT; + return L_VERT; } else if (strcasecmp(s, "tabbed") == 0) { - *ptr = L_TABBED; + return L_TABBED; } else if (strcasecmp(s, "stacking") == 0) { - *ptr = L_STACKED; - } else { - return false; + return L_STACKED; } - return true; + return L_NONE; } static const char* expected_syntax = @@ -26,84 +25,128 @@ static const char* expected_syntax = "'layout toggle [split|all]' or " "'layout toggle [split|tabbed|stacking|splitv|splith] [split|tabbed|stacking|splitv|splith]...'"; +static enum sway_container_layout get_layout_toggle(int argc, char **argv, + enum sway_container_layout layout, + enum sway_container_layout prev_split_layout) { + // "layout toggle" + if (argc == 0) { + return layout == L_HORIZ ? L_VERT : L_HORIZ; + } + + if (argc == 2) { + // "layout toggle split" (same as "layout toggle") + if (strcasecmp(argv[1], "split") == 0) { + return layout == L_HORIZ ? L_VERT : L_HORIZ; + } + // "layout toggle all" + if (strcasecmp(argv[1], "all") == 0) { + return layout == L_HORIZ ? L_VERT : + layout == L_VERT ? L_STACKED : + layout == L_STACKED ? L_TABBED : L_HORIZ; + } + return L_NONE; + } + + enum sway_container_layout parsed; + int curr = 1; + for (; curr < argc; curr++) { + parsed = parse_layout_string(argv[curr]); + if (parsed == layout || (strcmp(argv[curr], "split") == 0 && + (layout == L_VERT || layout == L_HORIZ))) { + break; + } + } + for (int i = curr + 1; i != curr; ++i) { + // cycle round to find next valid layout + if (i >= argc) { + i = 1; + } + parsed = parse_layout_string(argv[i]); + if (parsed != L_NONE) { + return parsed; + } + if (strcmp(argv[i], "split") == 0) { + return layout == L_HORIZ ? L_VERT : + layout == L_VERT ? L_HORIZ : prev_split_layout; + } + // invalid layout strings are silently ignored + } + return L_NONE; +} + +static enum sway_container_layout get_layout(int argc, char **argv, + enum sway_container_layout layout, + enum sway_container_layout prev_split_layout) { + // Check if assigned directly + enum sway_container_layout parsed = parse_layout_string(argv[0]); + if (parsed != L_NONE) { + return parsed; + } + + if (strcasecmp(argv[0], "default") == 0) { + return prev_split_layout; + } + + if (strcasecmp(argv[0], "toggle") == 0) { + return get_layout_toggle(argc, argv, layout, prev_split_layout); + } + + return L_NONE; +} + struct cmd_results *cmd_layout(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "layout", EXPECTED_MORE_THAN, 0))) { return error; } - struct sway_container *parent = config->handler_context.current_container; + struct sway_container *container = config->handler_context.container; + struct sway_workspace *workspace = config->handler_context.workspace; - if (container_is_floating(parent)) { + if (container && container_is_floating(container)) { return cmd_results_new(CMD_FAILURE, "layout", "Unable to change layout of floating windows"); } - while (parent->type == C_VIEW) { - parent = parent->parent; + // Typically we change the layout of the current container, but if the + // current container is a view (it usually is) then we'll change the layout + // of the parent instead, as it doesn't make sense for views to have layout. + if (container && container->view) { + container = container->parent; } - 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_split_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_HORIZ ? L_VERT : - parent->layout == L_VERT ? L_HORIZ : parent->prev_split_layout; - } else { - return cmd_results_new(CMD_INVALID, "layout", expected_syntax); - } - } else { - enum sway_container_layout parsed_layout; - int curr = 1; - for (; curr < argc; curr++) { - 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; - } - } - 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; - } 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 - } - } - } else { - return cmd_results_new(CMD_INVALID, "layout", expected_syntax); - } + // We could be working with a container OR a workspace. These are different + // structures, so we set up pointers to they layouts so we can refer them in + // an abstract way. + enum sway_container_layout new_layout = L_NONE; + enum sway_container_layout old_layout = L_NONE; + if (container) { + old_layout = container->layout; + new_layout = get_layout(argc, argv, + container->layout, container->prev_split_layout); + } else { + old_layout = workspace->layout; + new_layout = get_layout(argc, argv, + workspace->layout, workspace->prev_split_layout); } - if (parent->layout == L_NONE) { - parent->layout = container_get_default_layout(parent); + if (new_layout == L_NONE) { + return cmd_results_new(CMD_INVALID, "layout", expected_syntax); } - if (prev != parent->layout) { - if (prev != L_TABBED && prev != L_STACKED) { - parent->prev_split_layout = prev; + if (new_layout != old_layout) { + if (container) { + if (old_layout != L_TABBED && old_layout != L_STACKED) { + container->prev_split_layout = old_layout; + } + container->layout = new_layout; + container_update_representation(container); + arrange_container(container); + } else { + if (old_layout != L_TABBED && old_layout != L_STACKED) { + workspace->prev_split_layout = old_layout; + } + workspace->layout = new_layout; + workspace_update_representation(workspace); + arrange_workspace(workspace); } - container_notify_subtree_changed(parent); - arrange_windows(parent->parent); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/mark.c b/sway/commands/mark.c index 9ea8c301..fb95a7d0 100644 --- a/sway/commands/mark.c +++ b/sway/commands/mark.c @@ -18,13 +18,12 @@ struct cmd_results *cmd_mark(int argc, char **argv) { if ((error = checkarg(argc, "mark", EXPECTED_AT_LEAST, 1))) { return error; } - struct sway_container *container = - config->handler_context.current_container; - if (container->type != C_VIEW) { + struct sway_container *container = config->handler_context.container; + if (!container->view) { return cmd_results_new(CMD_INVALID, "mark", "Only views can have marks"); } - struct sway_view *view = container->sway_view; + struct sway_view *view = container->view; bool add = false, toggle = false; while (argc > 0 && strncmp(*argv, "--", 2) == 0) { diff --git a/sway/commands/move.c b/sway/commands/move.c index 4426f24e..7b503624 100644 --- a/sway/commands/move.c +++ b/sway/commands/move.c @@ -40,8 +40,8 @@ enum wlr_direction opposite_direction(enum wlr_direction d) { } } -static struct sway_container *output_in_direction(const char *direction_string, - struct wlr_output *reference, int ref_lx, int ref_ly) { +static struct sway_output *output_in_direction(const char *direction_string, + struct sway_output *reference, int ref_lx, int ref_ly) { struct { char *name; enum wlr_direction direction; @@ -61,449 +61,370 @@ static struct sway_container *output_in_direction(const char *direction_string, } } - if (direction) { + if (reference && direction) { struct wlr_output *target = wlr_output_layout_adjacent_output( - root_container.sway_root->output_layout, - direction, reference, ref_lx, ref_ly); + root->output_layout, direction, reference->wlr_output, + ref_lx, ref_ly); if (!target) { target = wlr_output_layout_farthest_output( - root_container.sway_root->output_layout, - opposite_direction(direction), reference, ref_lx, ref_ly); + root->output_layout, opposite_direction(direction), + reference->wlr_output, ref_lx, ref_ly); } if (target) { - struct sway_output *sway_output = target->data; - return sway_output->swayc; + return target->data; } } return output_by_name(direction_string); } -static void container_move_to(struct sway_container *container, - struct sway_container *destination) { - if (!sway_assert(container->type == C_CONTAINER || - container->type == C_VIEW, "Expected a container or view")) { - return; +static bool is_parallel(enum sway_container_layout layout, + enum movement_direction dir) { + switch (layout) { + case L_TABBED: + case L_HORIZ: + return dir == MOVE_LEFT || dir == MOVE_RIGHT; + case L_STACKED: + case L_VERT: + return dir == MOVE_UP || dir == MOVE_DOWN; + default: + return false; } - if (container == destination - || container_has_ancestor(container, destination)) { +} + +/** + * Ensures all seats focus the fullscreen container if needed. + */ +static void workspace_focus_fullscreen(struct sway_workspace *workspace) { + if (!workspace->fullscreen) { return; } - struct sway_container *old_parent = NULL; - struct sway_container *new_parent = NULL; - if (container_is_floating(container)) { - // Resolve destination into a workspace - struct sway_container *new_ws = NULL; - if (destination->type == C_OUTPUT) { - new_ws = output_get_active_workspace(destination->sway_output); - } else if (destination->type == C_WORKSPACE) { - new_ws = destination; - } else { - new_ws = container_parent(destination, C_WORKSPACE); + struct sway_seat *seat; + struct sway_workspace *focus_ws; + wl_list_for_each(seat, &input_manager->seats, link) { + focus_ws = seat_get_focused_workspace(seat); + if (focus_ws == workspace) { + struct sway_node *new_focus = + seat_get_focus_inactive(seat, &workspace->fullscreen->node); + seat_set_focus(seat, new_focus); } - if (!new_ws) { - // This can happen if the user has run "move container to mark foo", - // where mark foo is on a hidden scratchpad container. - return; + } +} + +static void container_move_to_container_from_direction( + struct sway_container *container, struct sway_container *destination, + enum movement_direction move_dir) { + if (destination->view) { + if (destination->parent == container->parent) { + wlr_log(WLR_DEBUG, "Swapping siblings"); + list_t *siblings = container_get_siblings(container); + int container_index = list_find(siblings, container); + int destination_index = list_find(siblings, destination); + list_swap(siblings, container_index, destination_index); + } else { + wlr_log(WLR_DEBUG, "Promoting to sibling of cousin"); + int offset = move_dir == MOVE_LEFT || move_dir == MOVE_UP; + int index = container_sibling_index(destination) + offset; + if (destination->parent) { + container_insert_child(destination->parent, container, index); + } else { + workspace_insert_tiling(destination->workspace, + container, index); + } + container->width = container->height = 0; } - struct sway_container *old_output = - container_parent(container, C_OUTPUT); - old_parent = container_remove_child(container); - workspace_add_floating(new_ws, container); - container_handle_fullscreen_reparent(container, old_parent); + return; + } + + if (is_parallel(destination->layout, move_dir)) { + wlr_log(WLR_DEBUG, "Reparenting container (parallel)"); + int index = move_dir == MOVE_RIGHT || move_dir == MOVE_DOWN ? + 0 : destination->children->length; + container_insert_child(destination, container, index); + container->width = container->height = 0; + return; + } + + wlr_log(WLR_DEBUG, "Reparenting container (perpendicular)"); + struct sway_node *focus_inactive = seat_get_active_child( + config->handler_context.seat, &destination->node); + if (!focus_inactive || focus_inactive == &destination->node) { + // The container has no children + container_add_child(destination, container); + return; + } + + // Try again but with the child + container_move_to_container_from_direction(container, + focus_inactive->sway_container, move_dir); +} + +static void container_move_to_workspace_from_direction( + struct sway_container *container, struct sway_workspace *workspace, + enum movement_direction move_dir) { + if (is_parallel(workspace->layout, move_dir)) { + wlr_log(WLR_DEBUG, "Reparenting container (parallel)"); + int index = move_dir == MOVE_RIGHT || move_dir == MOVE_DOWN ? + 0 : workspace->tiling->length; + workspace_insert_tiling(workspace, container, index); + return; + } + + wlr_log(WLR_DEBUG, "Reparenting container (perpendicular)"); + struct sway_container *focus_inactive = seat_get_focus_inactive_tiling( + config->handler_context.seat, workspace); + if (!focus_inactive) { + // The workspace has no tiling children + workspace_add_tiling(workspace, container); + return; + } + while (focus_inactive->parent) { + focus_inactive = focus_inactive->parent; + } + container_move_to_container_from_direction(container, focus_inactive, + move_dir); +} + +static void container_move_to_workspace(struct sway_container *container, + struct sway_workspace *workspace) { + if (container->workspace == workspace) { + return; + } + struct sway_workspace *old_workspace = container->workspace; + if (container_is_floating(container)) { + struct sway_output *old_output = container->workspace->output; + container_detach(container); + workspace_add_floating(workspace, container); + container_handle_fullscreen_reparent(container); // If changing output, center it within the workspace - if (old_output != new_ws->parent && !container->is_fullscreen) { + if (old_output != workspace->output && !container->is_fullscreen) { container_floating_move_to_center(container); } } else { - old_parent = container_remove_child(container); + container_detach(container); container->width = container->height = 0; container->saved_width = container->saved_height = 0; - - if (destination->type == C_VIEW) { - new_parent = container_add_sibling(destination, container); - } else { - new_parent = destination; - container_add_child(destination, container); - } + workspace_add_tiling(workspace, container); + container_update_representation(container); } - - if (container->type == C_VIEW) { + if (container->view) { ipc_event_window(container, "move"); } - container_notify_subtree_changed(old_parent); - container_notify_subtree_changed(new_parent); - - // If view was moved to a fullscreen workspace, refocus the fullscreen view - struct sway_container *new_workspace = container; - if (new_workspace->type != C_WORKSPACE) { - new_workspace = container_parent(new_workspace, C_WORKSPACE); - } - if (new_workspace->sway_workspace->fullscreen) { - struct sway_seat *seat; - struct sway_container *focus, *focus_ws; - wl_list_for_each(seat, &input_manager->seats, link) { - focus = seat_get_focus(seat); - focus_ws = focus; - if (focus_ws->type != C_WORKSPACE) { - focus_ws = container_parent(focus_ws, C_WORKSPACE); - } - if (focus_ws == new_workspace) { - struct sway_container *new_focus = seat_get_focus_inactive(seat, - new_workspace->sway_workspace->fullscreen); - seat_set_focus(seat, new_focus); - } - } + workspace_detect_urgent(old_workspace); + workspace_detect_urgent(workspace); + workspace_focus_fullscreen(workspace); +} + +static void container_move_to_container(struct sway_container *container, + struct sway_container *destination) { + if (container == destination + || container_has_ancestor(container, destination) + || container_has_ancestor(destination, container)) { + return; } - // Update workspace urgent state - struct sway_container *old_workspace = old_parent; - if (old_workspace->type != C_WORKSPACE) { - old_workspace = container_parent(old_workspace, C_WORKSPACE); - } - if (new_workspace != old_workspace) { - workspace_detect_urgent(new_workspace); - if (old_workspace) { - workspace_detect_urgent(old_workspace); - } + if (container_is_floating(container)) { + return; } -} + struct sway_workspace *old_workspace = container->workspace; -static bool is_parallel(enum sway_container_layout layout, - enum movement_direction dir) { - switch (layout) { - case L_TABBED: - case L_HORIZ: - return dir == MOVE_LEFT || dir == MOVE_RIGHT; - case L_STACKED: - case L_VERT: - return dir == MOVE_UP || dir == MOVE_DOWN; - default: - return false; + container_detach(container); + container->width = container->height = 0; + container->saved_width = container->saved_height = 0; + + if (destination->view) { + container_add_sibling(destination, container); + } else { + container_add_child(destination, container); } -} -static enum movement_direction invert_movement(enum movement_direction dir) { - switch (dir) { - case MOVE_LEFT: - return MOVE_RIGHT; - case MOVE_RIGHT: - return MOVE_LEFT; - case MOVE_UP: - return MOVE_DOWN; - case MOVE_DOWN: - return MOVE_UP; - default: - sway_assert(0, "This function expects left|right|up|down"); - return MOVE_LEFT; + if (container->view) { + ipc_event_window(container, "move"); } -} -static int move_offs(enum movement_direction move_dir) { - return move_dir == MOVE_LEFT || move_dir == MOVE_UP ? -1 : 1; -} + workspace_focus_fullscreen(destination->workspace); -/* Gets the index of the most extreme member based on the movement offset */ -static int container_limit(struct sway_container *container, - enum movement_direction move_dir) { - return move_offs(move_dir) < 0 ? 0 : container->children->length; + // Update workspace urgent state + workspace_detect_urgent(destination->workspace); + if (old_workspace && old_workspace != destination->workspace) { + workspace_detect_urgent(old_workspace); + } } /* Takes one child, sets it aside, wraps the rest of the children in a new * container, switches the layout of the workspace, and drops the child back in. * In other words, rejigger it. */ -static void workspace_rejigger(struct sway_container *ws, +static void workspace_rejigger(struct sway_workspace *ws, struct sway_container *child, enum movement_direction move_dir) { - struct sway_container *original_parent = child->parent; - struct sway_container *new_parent = - container_split(ws, ws->layout); - - container_remove_child(child); - for (int i = 0; i < ws->children->length; ++i) { - struct sway_container *_child = ws->children->items[i]; - container_move_to(new_parent, _child); + if (!sway_assert(child->parent == NULL, "Expected a root child")) { + return; } + container_detach(child); + workspace_wrap_children(ws); - int index = move_offs(move_dir); - container_insert_child(ws, child, index < 0 ? 0 : 1); + int index = move_dir == MOVE_LEFT || move_dir == MOVE_UP ? 0 : 1; + workspace_insert_tiling(ws, child, index); ws->layout = move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT; - - container_flatten(ws); - container_reap_empty(original_parent); - container_create_notify(new_parent); + workspace_update_representation(ws); } static void move_out_of_tabs_stacks(struct sway_container *container, struct sway_container *current, enum movement_direction move_dir, int offs) { - if (container->parent == current->parent - && current->parent->children->length == 1) { - wlr_log(WLR_DEBUG, "Changing layout of %zd", current->parent->id); - current->parent->layout = move_dir == - MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT; + enum sway_container_layout layout = move_dir == + MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT; + list_t *siblings = container_get_siblings(container); + if (container == current && siblings->length == 1) { + wlr_log(WLR_DEBUG, "Changing layout of parent"); + if (container->parent) { + container->parent->layout = layout; + container_update_representation(container); + } else { + container->workspace->layout = layout; + workspace_update_representation(container->workspace); + } return; } wlr_log(WLR_DEBUG, "Moving out of tab/stack into a split"); - bool is_workspace = current->parent->type == C_WORKSPACE; - struct sway_container *new_parent = container_split(current->parent, - move_dir == MOVE_LEFT || move_dir == MOVE_RIGHT ? L_HORIZ : L_VERT); - if (is_workspace) { - container_insert_child(new_parent->parent, container, offs < 0 ? 0 : 1); - } else { + if (container->parent) { + struct sway_container *new_parent = + container_split(current->parent, layout); container_insert_child(new_parent, container, offs < 0 ? 0 : 1); - container_reap_empty(new_parent->parent); - container_flatten(new_parent->parent); + container_reap_empty(new_parent); + container_flatten(new_parent); + } else { + // Changing a workspace + struct sway_workspace *workspace = container->workspace; + workspace_split(workspace, layout); + workspace_insert_tiling(workspace, container, offs < 0 ? 0 : 1); } - container_create_notify(new_parent); - container_notify_subtree_changed(new_parent); } -static void container_move(struct sway_container *container, - enum movement_direction move_dir, int move_amt) { - if (!sway_assert( - container->type != C_CONTAINER || container->type != C_VIEW, - "Can only move containers and views")) { - return; - } - int offs = move_offs(move_dir); - - struct sway_container *sibling = NULL; - struct sway_container *current = container; - struct sway_container *parent = current->parent; - struct sway_container *top = &root_container; - +// Returns true if moved +static bool container_move_in_direction(struct sway_container *container, + enum movement_direction move_dir) { // If moving a fullscreen view, only consider outputs if (container->is_fullscreen) { - current = container_parent(container, C_OUTPUT); - } else if (container_is_fullscreen_or_child(container) || - container_is_floating_or_child(container)) { - // If we've fullscreened a split container, only allow the child to move - // around within the fullscreen parent. - // Same with floating a split container. - struct sway_container *ws = container_parent(container, C_WORKSPACE); - top = ws->sway_workspace->fullscreen; - } - - struct sway_container *new_parent = container_flatten(parent); - if (new_parent != parent) { - // Special case: we were the last one in this container, so leave - return; + struct sway_output *new_output = + output_get_in_direction(container->workspace->output, move_dir); + if (!new_output) { + return false; + } + struct sway_workspace *ws = output_get_active_workspace(new_output); + container_move_to_workspace(container, ws); + return true; } - while (!sibling) { - if (current == top) { - return; + // If container is in a split container by itself, move out of the split + if (container->parent) { + struct sway_container *new_parent = + container_flatten(container->parent); + if (new_parent != container->parent) { + return true; } + } - parent = current->parent; - wlr_log(WLR_DEBUG, "Visiting %p %s '%s'", current, - container_type_to_str(current->type), current->name); - - int index = container_sibling_index(current); - - switch (current->type) { - case C_OUTPUT: { - enum wlr_direction wlr_dir = 0; - if (!sway_assert(sway_dir_to_wlr(move_dir, &wlr_dir), - "got invalid direction: %d", move_dir)) { - return; - } - double ref_lx = current->x + current->width / 2; - double ref_ly = current->y + current->height / 2; - struct wlr_output *next = wlr_output_layout_adjacent_output( - root_container.sway_root->output_layout, wlr_dir, - current->sway_output->wlr_output, ref_lx, ref_ly); - if (!next) { - wlr_log(WLR_DEBUG, "Hit edge of output, nowhere else to go"); - return; - } - struct sway_output *next_output = next->data; - current = next_output->swayc; - wlr_log(WLR_DEBUG, "Selected next output (%s)", current->name); - // Select workspace and get outta here - current = seat_get_focus_inactive( - config->handler_context.seat, current); - if (current->type != C_WORKSPACE) { - current = container_parent(current, C_WORKSPACE); - } - sibling = current; - break; - } - case C_WORKSPACE: - if (!is_parallel(current->layout, move_dir)) { - if (current->children->length >= 2) { - wlr_log(WLR_DEBUG, "Rejiggering the workspace (%d kiddos)", - current->children->length); - workspace_rejigger(current, container, move_dir); - return; - } else { - wlr_log(WLR_DEBUG, "Selecting output"); - current = current->parent; - } - } else if (current->layout == L_TABBED - || current->layout == L_STACKED) { - wlr_log(WLR_DEBUG, "Rejiggering out of tabs/stacks"); - workspace_rejigger(current, container, move_dir); - } else { - wlr_log(WLR_DEBUG, "Selecting output"); - current = current->parent; - } - break; - case C_CONTAINER: - case C_VIEW: - if (is_parallel(parent->layout, move_dir)) { - if ((index == parent->children->length - 1 && offs > 0) - || (index == 0 && offs < 0)) { - if (current->parent == container->parent) { - if (!parent->is_fullscreen && - (parent->layout == L_TABBED || - parent->layout == L_STACKED)) { - move_out_of_tabs_stacks(container, current, - move_dir, offs); - return; - } else { - wlr_log(WLR_DEBUG, "Hit limit, selecting parent"); - current = current->parent; - } + // Look for a suitable *container* sibling or parent. + // The below loop stops once we hit the workspace because current->parent + // is NULL for the topmost containers in a workspace. + struct sway_container *current = container; + int offs = move_dir == MOVE_LEFT || move_dir == MOVE_UP ? -1 : 1; + + while (current) { + struct sway_container *parent = current->parent; + list_t *siblings = container_get_siblings(current); + enum sway_container_layout layout = container_parent_layout(current); + int index = list_find(siblings, current); + int desired = index + offs; + + if (is_parallel(layout, move_dir)) { + if (desired == -1 || desired == siblings->length) { + if (current->parent == container->parent) { + if (!(parent && parent->is_fullscreen) && + (layout == L_TABBED || layout == L_STACKED)) { + move_out_of_tabs_stacks(container, current, + move_dir, offs); + return true; } else { - wlr_log(WLR_DEBUG, "Hit limit, " - "promoting descendant to sibling"); - // Special case + current = current->parent; + continue; + } + } else { + // Special case + if (current->parent) { container_insert_child(current->parent, container, index + (offs < 0 ? 0 : 1)); - container->width = container->height = 0; - return; + } else { + workspace_insert_tiling(current->workspace, container, + index + (offs < 0 ? 0 : 1)); } - } else { - sibling = parent->children->items[index + offs]; - wlr_log(WLR_DEBUG, "Selecting sibling id:%zd", sibling->id); + return true; } - } else if (!parent->is_fullscreen && (parent->layout == L_TABBED || - parent->layout == L_STACKED)) { - move_out_of_tabs_stacks(container, current, move_dir, offs); - return; } else { - wlr_log(WLR_DEBUG, "Moving up to find a parallel container"); - current = current->parent; + // Container can move within its siblings + container_move_to_container_from_direction(container, + siblings->items[desired], move_dir); + return true; } - break; - default: - sway_assert(0, "Not expecting to see container of type %s here", - container_type_to_str(current->type)); - return; + } else if (!(parent && parent->is_fullscreen) && + (layout == L_TABBED || layout == L_STACKED)) { + move_out_of_tabs_stacks(container, current, move_dir, offs); + return true; } - } - // Part two: move stuff around - int index = container_sibling_index(container); - struct sway_container *old_parent = container->parent; + current = current->parent; - while (sibling) { - switch (sibling->type) { - case C_VIEW: - if (sibling->parent == container->parent) { - wlr_log(WLR_DEBUG, "Swapping siblings"); - sibling->parent->children->items[index + offs] = container; - sibling->parent->children->items[index] = sibling; - } else { - wlr_log(WLR_DEBUG, "Promoting to sibling of cousin"); - container_insert_child(sibling->parent, container, - container_sibling_index(sibling) + (offs > 0 ? 0 : 1)); - container->width = container->height = 0; - } - sibling = NULL; - break; - case C_WORKSPACE: // Note: only in the case of moving between outputs - case C_CONTAINER: - if (is_parallel(sibling->layout, move_dir)) { - int limit = container_limit(sibling, invert_movement(move_dir)); - wlr_log(WLR_DEBUG, "limit: %d", limit); - wlr_log(WLR_DEBUG, - "Reparenting container (parallel) to index %d " - "(move dir: %d)", limit, move_dir); - container_insert_child(sibling, container, limit); - container->width = container->height = 0; - sibling = NULL; - } else { - wlr_log(WLR_DEBUG, "Reparenting container (perpendicular)"); - struct sway_container *focus_inactive = seat_get_focus_inactive( - config->handler_context.seat, sibling); - if (focus_inactive && focus_inactive != sibling) { - while (focus_inactive->parent != sibling) { - focus_inactive = focus_inactive->parent; - } - wlr_log(WLR_DEBUG, "Focus inactive: id:%zd", - focus_inactive->id); - sibling = focus_inactive; - continue; - } else if (sibling->children->length) { - wlr_log(WLR_DEBUG, "No focus-inactive, adding arbitrarily"); - container_remove_child(container); - container_add_sibling(sibling->children->items[0], container); - } else { - wlr_log(WLR_DEBUG, "No kiddos, adding container alone"); - container_remove_child(container); - container_add_child(sibling, container); - } - container->width = container->height = 0; - sibling = NULL; - } - break; - default: - sway_assert(0, "Not expecting to see container of type %s here", - container_type_to_str(sibling->type)); - return; + // Don't allow containers to move out of their + // fullscreen or floating parent + if (current && + (current->is_fullscreen || container_is_floating(current))) { + return false; } } - container_notify_subtree_changed(old_parent); - container_notify_subtree_changed(container->parent); - - if (container->type == C_VIEW) { - ipc_event_window(container, "move"); - } - - if (old_parent) { - seat_set_focus(config->handler_context.seat, old_parent); - seat_set_focus(config->handler_context.seat, container); + // Maybe rejigger the workspace + struct sway_workspace *ws = container->workspace; + if (!is_parallel(ws->layout, move_dir)) { + if (ws->tiling->length >= 2) { + workspace_rejigger(ws, container, move_dir); + return true; + } + } else if (ws->layout == L_TABBED || ws->layout == L_STACKED) { + workspace_rejigger(ws, container, move_dir); + return true; } - struct sway_container *last_ws = old_parent; - struct sway_container *next_ws = container->parent; - if (last_ws && last_ws->type != C_WORKSPACE) { - last_ws = container_parent(last_ws, C_WORKSPACE); + // Try adjacent output + struct sway_output *output = + output_get_in_direction(container->workspace->output, move_dir); + if (output) { + struct sway_workspace *ws = output_get_active_workspace(output); + container_move_to_workspace_from_direction(container, ws, move_dir); + return true; } - if (next_ws && next_ws->type != C_WORKSPACE) { - next_ws = container_parent(next_ws, C_WORKSPACE); - } - if (last_ws && next_ws && last_ws != next_ws) { - ipc_event_workspace(last_ws, next_ws, "focus"); - workspace_detect_urgent(last_ws); - workspace_detect_urgent(next_ws); - } - container_end_mouse_operation(container); + wlr_log(WLR_DEBUG, "Hit edge of output, nowhere else to go"); + return false; } -static struct cmd_results *cmd_move_container(struct sway_container *current, - int argc, char **argv) { +static struct cmd_results *cmd_move_container(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "move container/window", EXPECTED_AT_LEAST, 3))) { return error; } - if (current->type == C_WORKSPACE) { - if (current->children->length == 0) { + struct sway_node *node = config->handler_context.node; + struct sway_workspace *workspace = config->handler_context.workspace; + struct sway_container *container = config->handler_context.container; + if (node->type == N_WORKSPACE) { + if (workspace->tiling->length == 0) { return cmd_results_new(CMD_FAILURE, "move", "Can't move an empty workspace"); } - current = workspace_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."); + container = workspace_wrap_children(workspace); } bool no_auto_back_and_forth = false; @@ -530,15 +451,15 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, } struct sway_seat *seat = config->handler_context.seat; - struct sway_container *old_parent = current->parent; - struct sway_container *old_ws = container_parent(current, C_WORKSPACE); - struct sway_container *old_output = container_parent(current, C_OUTPUT); - struct sway_container *destination = NULL; + struct sway_container *old_parent = container->parent; + struct sway_workspace *old_ws = container->workspace; + struct sway_output *old_output = old_ws ? old_ws->output : NULL; + struct sway_node *destination = NULL; // determine destination if (strcasecmp(argv[1], "workspace") == 0) { // move container to workspace x - struct sway_container *ws = NULL; + struct sway_workspace *ws = NULL; char *ws_name = NULL; if (strcasecmp(argv[2], "next") == 0 || strcasecmp(argv[2], "prev") == 0 || @@ -576,7 +497,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, 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 (old_ws && 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); @@ -588,8 +510,8 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, // We have to create the workspace, but if the container is // sticky and the workspace is going to be created on the same // output, we'll bail out first. - if (current->is_sticky) { - struct sway_container *new_output = + if (container->is_sticky) { + struct sway_output *new_output = workspace_get_initial_output(ws_name); if (old_output == new_output) { free(ws_name); @@ -601,105 +523,119 @@ static struct cmd_results *cmd_move_container(struct sway_container *current, ws = workspace_create(NULL, ws_name); } free(ws_name); - destination = seat_get_focus_inactive(seat, ws); + destination = seat_get_focus_inactive(seat, &ws->node); } else if (strcasecmp(argv[1], "output") == 0) { - struct sway_container *dest_output = output_in_direction(argv[2], - old_output->sway_output->wlr_output, current->x, current->y); - if (!dest_output) { + struct sway_output *new_output = output_in_direction(argv[2], + old_output, container->x, container->y); + if (!new_output) { return cmd_results_new(CMD_FAILURE, "move workspace", "Can't find output with name/direction '%s'", argv[2]); } - destination = seat_get_focus_inactive(seat, dest_output); - if (!destination) { - // We've never been to this output before - destination = dest_output->children->items[0]; - } + destination = seat_get_focus_inactive(seat, &new_output->node); } 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[2]); } - destination = dest_view->swayc; + destination = &dest_view->container->node; } else { return cmd_results_new(CMD_INVALID, "move", expected_syntax); } - struct sway_container *new_output = destination->type == C_OUTPUT ? - destination : container_parent(destination, C_OUTPUT); - if (current->is_sticky && old_output == new_output) { + if (container->is_sticky && old_output && + node_has_ancestor(destination, &old_output->node)) { return cmd_results_new(CMD_FAILURE, "move", "Can't move sticky " "container to another workspace on the same output"); } - struct sway_container *new_output_last_ws = old_output == new_output ? - NULL : seat_get_active_child(seat, new_output); - struct sway_container *new_workspace = destination->type == C_WORKSPACE ? - destination : container_parent(destination, C_WORKSPACE); + struct sway_output *new_output = node_get_output(destination); + struct sway_workspace *new_output_last_ws = old_output == new_output ? + NULL : output_get_active_workspace(new_output); // move container, arrange windows and return focus - container_move_to(current, destination); + if (container->scratchpad) { + root_scratchpad_remove_container(container); + } + switch (destination->type) { + case N_WORKSPACE: + container_move_to_workspace(container, destination->sway_workspace); + break; + case N_OUTPUT: { + struct sway_output *output = destination->sway_output; + struct sway_workspace *ws = output_get_active_workspace(output); + container_move_to_workspace(container, ws); + } + break; + case N_CONTAINER: + container_move_to_container(container, destination->sway_container); + break; + case N_ROOT: + break; + } + struct sway_workspace *new_workspace = + output_get_active_workspace(new_output); if (new_output_last_ws && new_output_last_ws != new_workspace) { // change focus on destination output back to its last active workspace - struct sway_container *new_output_last_focus = - seat_get_focus_inactive(seat, new_output_last_ws); + struct sway_node *new_output_last_focus = + seat_get_focus_inactive(seat, &new_output_last_ws->node); seat_set_focus_warp(seat, new_output_last_focus, false, false); } - struct sway_container *focus = seat_get_focus_inactive(seat, old_parent); + + struct sway_node *focus = NULL; + if (old_parent) { + focus = seat_get_focus_inactive(seat, &old_parent->node); + } else if (old_ws) { + focus = seat_get_focus_inactive(seat, &old_ws->node); + } seat_set_focus_warp(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); + if (old_parent) { + container_reap_empty(old_parent); + } else if (old_ws) { + workspace_consider_destroy(old_ws); + } + + if (old_ws) { + arrange_workspace(old_ws); + } + arrange_node(node_get_parent(destination)); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static void workspace_move_to_output(struct sway_container *workspace, - struct sway_container *output) { - if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) { +static void workspace_move_to_output(struct sway_workspace *workspace, + struct sway_output *output) { + if (workspace->output == output) { return; } - if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) { - return; - } - if (workspace->parent == output) { - return; - } - struct sway_container *old_output = container_remove_child(workspace); - struct sway_seat *seat = input_manager_get_default_seat(input_manager); - struct sway_container *new_output_focus = - seat_get_focus_inactive(seat, output); + struct sway_output *old_output = workspace->output; + workspace_detach(workspace); + struct sway_workspace *new_output_old_ws = + output_get_active_workspace(output); - container_add_child(output, workspace); + output_add_workspace(output, workspace); // If moving the last workspace from the old output, create a new workspace // on the old output - if (old_output->children->length == 0) { - char *ws_name = workspace_next_name(old_output->name); - struct sway_container *ws = workspace_create(old_output, ws_name); + struct sway_seat *seat = config->handler_context.seat; + if (old_output->workspaces->length == 0) { + char *ws_name = workspace_next_name(old_output->wlr_output->name); + struct sway_workspace *ws = workspace_create(old_output, ws_name); free(ws_name); - seat_set_focus(seat, ws); + seat_set_focus(seat, &ws->node); } - // Try to remove an empty workspace from the destination output. - container_reap_empty(new_output_focus); + workspace_consider_destroy(new_output_old_ws); output_sort_workspaces(output); - seat_set_focus(seat, output); + struct sway_node *focus = seat_get_focus_inactive(seat, &workspace->node); + seat_set_focus(seat, focus); workspace_output_raise_priority(workspace, old_output, output); ipc_event_workspace(NULL, workspace, "move"); - - container_notify_subtree_changed(old_output); - container_notify_subtree_changed(output); } -static struct cmd_results *cmd_move_workspace(struct sway_container *current, - int argc, char **argv) { +static struct cmd_results *cmd_move_workspace(int argc, char **argv) { struct cmd_results *error = NULL; if ((error = checkarg(argc, "move workspace", EXPECTED_AT_LEAST, 2))) { return error; @@ -716,27 +652,25 @@ static struct cmd_results *cmd_move_workspace(struct sway_container *current, 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[2], - source->sway_output->wlr_output, center_x, center_y); - if (!destination) { + struct sway_workspace *workspace = config->handler_context.workspace; + struct sway_output *old_output = workspace->output; + int center_x = workspace->width / 2 + workspace->x, + center_y = workspace->height / 2 + workspace->y; + struct sway_output *new_output = output_in_direction(argv[2], + old_output, center_x, center_y); + if (!new_output) { return cmd_results_new(CMD_FAILURE, "move workspace", "Can't find output with name/direction '%s'", argv[2]); } - if (current->type != C_WORKSPACE) { - current = container_parent(current, C_WORKSPACE); - } - workspace_move_to_output(current, destination); + workspace_move_to_output(workspace, new_output); - arrange_windows(source); - arrange_windows(destination); + arrange_output(old_output); + arrange_output(new_output); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static struct cmd_results *move_in_direction(struct sway_container *container, +static struct cmd_results *cmd_move_in_direction( enum movement_direction direction, int argc, char **argv) { int move_amt = 10; if (argc > 1) { @@ -748,7 +682,8 @@ static struct cmd_results *move_in_direction(struct sway_container *container, } } - if (container->type == C_WORKSPACE) { + struct sway_container *container = config->handler_context.container; + if (!container) { return cmd_results_new(CMD_FAILURE, "move", "Cannot move workspaces in a direction"); } @@ -780,20 +715,34 @@ static struct cmd_results *move_in_direction(struct sway_container *container, container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } - // For simplicity, we'll arrange the entire workspace. The reason for this - // is moving the container might reap the old parent, and container_move - // does not return a surviving parent. - // TODO: Make container_move return the surviving parent so we can arrange - // just that. - struct sway_container *old_ws = container_parent(container, C_WORKSPACE); - container_move(container, direction, move_amt); - struct sway_container *new_ws = container_parent(container, C_WORKSPACE); + struct sway_workspace *old_ws = container->workspace; - arrange_windows(old_ws); + if (!container_move_in_direction(container, direction)) { + // Container didn't move + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } + + struct sway_workspace *new_ws = container->workspace; + + arrange_workspace(old_ws); if (new_ws != old_ws) { - arrange_windows(new_ws); + arrange_workspace(new_ws); + } + + if (container->view) { + ipc_event_window(container, "move"); } + seat_set_focus(config->handler_context.seat, &new_ws->node); + seat_set_focus(config->handler_context.seat, &container->node); + + if (old_ws != new_ws) { + ipc_event_workspace(old_ws, new_ws, "focus"); + workspace_detect_urgent(old_ws); + workspace_detect_urgent(new_ws); + } + container_end_mouse_operation(container); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -802,9 +751,9 @@ static const char *expected_position_syntax = "'move [absolute] position center' or " "'move position cursor|mouse|pointer'"; -static struct cmd_results *move_to_position(struct sway_container *container, - int argc, char **argv) { - if (!container_is_floating(container)) { +static struct cmd_results *cmd_move_to_position(int argc, char **argv) { + struct sway_container *container = config->handler_context.container; + if (!container || !container_is_floating(container)) { return cmd_results_new(CMD_FAILURE, "move", "Only floating containers " "can be moved to an absolute position"); @@ -842,10 +791,10 @@ static struct cmd_results *move_to_position(struct sway_container *container, } else if (strcmp(argv[0], "center") == 0) { double lx, ly; if (absolute) { - lx = root_container.x + (root_container.width - container->width) / 2; - ly = root_container.y + (root_container.height - container->height) / 2; + lx = root->x + (root->width - container->width) / 2; + ly = root->y + (root->height - container->height) / 2; } else { - struct sway_container *ws = container_parent(container, C_WORKSPACE); + struct sway_workspace *ws = container->workspace; lx = ws->x + (ws->width - container->width) / 2; ly = ws->y + (ws->height - container->height) / 2; } @@ -881,30 +830,31 @@ static struct cmd_results *move_to_position(struct sway_container *container, } if (!absolute) { - struct sway_container *ws = container_parent(container, C_WORKSPACE); - lx += ws->x; - ly += ws->y; + lx += container->workspace->x; + ly += container->workspace->y; } container_floating_move_to(container, lx, ly); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } -static struct cmd_results *move_to_scratchpad(struct sway_container *con) { - if (con->type == C_WORKSPACE && con->children->length == 0) { +static struct cmd_results *cmd_move_to_scratchpad(void) { + struct sway_node *node = config->handler_context.node; + struct sway_container *con = config->handler_context.container; + struct sway_workspace *ws = config->handler_context.workspace; + if (node->type == N_WORKSPACE && ws->tiling->length == 0) { return cmd_results_new(CMD_INVALID, "move", "Can't move an empty workspace to the scratchpad"); } - if (con->type == C_WORKSPACE) { + if (node->type == N_WORKSPACE) { // Wrap the workspace's children in a container - struct sway_container *workspace = con; - con = workspace_wrap_children(con); - workspace->layout = L_HORIZ; + con = workspace_wrap_children(ws); + ws->layout = L_HORIZ; } // If the container is in a floating split container, // operate on the split container instead of the child. if (container_is_floating_or_child(con)) { - while (con->parent->type != C_WORKSPACE) { + while (con->parent) { con = con->parent; } } @@ -922,32 +872,31 @@ struct cmd_results *cmd_move(int argc, char **argv) { if ((error = checkarg(argc, "move", EXPECTED_AT_LEAST, 1))) { return error; } - struct sway_container *current = config->handler_context.current_container; if (strcasecmp(argv[0], "left") == 0) { - return move_in_direction(current, MOVE_LEFT, argc, argv); + return cmd_move_in_direction(MOVE_LEFT, argc, argv); } else if (strcasecmp(argv[0], "right") == 0) { - return move_in_direction(current, MOVE_RIGHT, argc, argv); + return cmd_move_in_direction(MOVE_RIGHT, argc, argv); } else if (strcasecmp(argv[0], "up") == 0) { - return move_in_direction(current, MOVE_UP, argc, argv); + return cmd_move_in_direction(MOVE_UP, argc, argv); } else if (strcasecmp(argv[0], "down") == 0) { - return move_in_direction(current, MOVE_DOWN, argc, argv); + return cmd_move_in_direction(MOVE_DOWN, argc, argv); } 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); + (strcasecmp(argv[0], "--no-auto-back-and-forth") && argc >= 2 + && (strcasecmp(argv[1], "container") == 0 + || strcasecmp(argv[1], "window") == 0))) { + return cmd_move_container(argc, argv); } else if (strcasecmp(argv[0], "workspace") == 0) { - return cmd_move_workspace(current, argc, argv); + return cmd_move_workspace(argc, argv); } else if (strcasecmp(argv[0], "scratchpad") == 0 || (strcasecmp(argv[0], "to") == 0 && argc == 2 && strcasecmp(argv[1], "scratchpad") == 0)) { - return move_to_scratchpad(current); + return cmd_move_to_scratchpad(); } else if (strcasecmp(argv[0], "position") == 0) { - return move_to_position(current, argc, argv); + return cmd_move_to_position(argc, argv); } else if (strcasecmp(argv[0], "absolute") == 0) { - return move_to_position(current, argc, argv); + return cmd_move_to_position(argc, argv); } else { return cmd_results_new(CMD_INVALID, "move", expected_syntax); } diff --git a/sway/commands/opacity.c b/sway/commands/opacity.c index 68fd9f42..9cdaad7f 100644 --- a/sway/commands/opacity.c +++ b/sway/commands/opacity.c @@ -19,8 +19,7 @@ struct cmd_results *cmd_opacity(int argc, char **argv) { return error; } - struct sway_container *con = - config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; float opacity = 0.0f; diff --git a/sway/commands/reload.c b/sway/commands/reload.c index f8ca374d..36fb9092 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -42,7 +42,7 @@ struct cmd_results *cmd_reload(int argc, char **argv) { } list_free(bar_ids); - arrange_windows(&root_container); + arrange_root(); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/rename.c b/sway/commands/rename.c index 21d2aa64..d982f941 100644 --- a/sway/commands/rename.c +++ b/sway/commands/rename.c @@ -25,14 +25,11 @@ struct cmd_results *cmd_rename(int argc, char **argv) { } int argn = 1; - struct sway_container *workspace; + struct sway_workspace *workspace = NULL; if (strcasecmp(argv[1], "to") == 0) { // 'rename workspace to new_name' - workspace = config->handler_context.current_container; - if (workspace->type != C_WORKSPACE) { - workspace = container_parent(workspace, C_WORKSPACE); - } + workspace = config->handler_context.workspace; } else if (strcasecmp(argv[1], "number") == 0) { // 'rename workspace number x to new_name' if (!isdigit(argv[2][0])) { @@ -78,7 +75,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) { 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); + struct sway_workspace *tmp_workspace = workspace_by_name(new_name); if (tmp_workspace) { free(new_name); return cmd_results_new(CMD_INVALID, "rename", @@ -89,7 +86,7 @@ struct cmd_results *cmd_rename(int argc, char **argv) { free(workspace->name); workspace->name = new_name; - output_sort_workspaces(workspace->parent); + output_sort_workspaces(workspace->output); ipc_event_workspace(NULL, workspace, "rename"); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/resize.c b/sway/commands/resize.c index ad659ef5..99e9dbda 100644 --- a/sway/commands/resize.c +++ b/sway/commands/resize.c @@ -10,6 +10,7 @@ #include "sway/commands.h" #include "sway/tree/arrange.h" #include "sway/tree/view.h" +#include "sway/tree/workspace.h" #include "log.h" static const int MIN_SANE_W = 100, MIN_SANE_H = 60; @@ -75,7 +76,7 @@ static int parse_resize_amount(int argc, char **argv, static void calculate_constraints(int *min_width, int *max_width, int *min_height, int *max_height) { - struct sway_container *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; if (config->floating_minimum_width == -1) { // no minimum *min_width = 0; @@ -96,8 +97,7 @@ static void calculate_constraints(int *min_width, int *max_width, if (config->floating_maximum_width == -1) { // no maximum *max_width = INT_MAX; } else if (config->floating_maximum_width == 0) { // automatic - struct sway_container *ws = container_parent(con, C_WORKSPACE); - *max_width = ws->width; + *max_width = con->workspace->width; } else { *max_width = config->floating_maximum_width; } @@ -105,8 +105,7 @@ static void calculate_constraints(int *min_width, int *max_width, if (config->floating_maximum_height == -1) { // no maximum *max_height = INT_MAX; } else if (config->floating_maximum_height == 0) { // automatic - struct sway_container *ws = container_parent(con, C_WORKSPACE); - *max_height = ws->height; + *max_height = con->workspace->height; } else { *max_height = config->floating_maximum_height; } @@ -191,11 +190,11 @@ static void resize_tiled(struct sway_container *parent, int amount, normalize_axis(axis) == RESIZE_AXIS_HORIZONTAL ? L_HORIZ : L_VERT; int minor_weight = 0; int major_weight = 0; - while (parent->parent) { - struct sway_container *next = parent->parent; - if (next->layout == parallel_layout) { - for (int i = 0; i < next->children->length; i++) { - struct sway_container *sibling = next->children->items[i]; + while (parent) { + list_t *siblings = container_get_siblings(parent); + if (container_parent_layout(parent) == parallel_layout) { + for (int i = 0; i < siblings->length; i++) { + struct sway_container *sibling = siblings->items[i]; int sibling_pos = parallel_coord(sibling, axis); int focused_pos = parallel_coord(focused, axis); @@ -213,17 +212,13 @@ static void resize_tiled(struct sway_container *parent, int amount, break; } } - parent = next; + parent = parent->parent; } - - if (parent->type == C_ROOT) { + if (!parent) { + // Can't resize in this direction return; } - wlr_log(WLR_DEBUG, - "Found the proper parent: %p. It has %d l conts, and %d r conts", - parent->parent, minor_weight, major_weight); - // Implement up/down/left/right direction by zeroing one of the weights, // then setting the axis to be horizontal or vertical if (axis == RESIZE_AXIS_UP || axis == RESIZE_AXIS_LEFT) { @@ -237,9 +232,10 @@ static void resize_tiled(struct sway_container *parent, int amount, //TODO: Ensure rounding is done in such a way that there are NO pixel leaks // ^ ????? + list_t *siblings = container_get_siblings(parent); - for (int i = 0; i < parent->parent->children->length; i++) { - struct sway_container *sibling = parent->parent->children->items[i]; + for (int i = 0; i < siblings->length; i++) { + struct sway_container *sibling = siblings->items[i]; int sibling_pos = parallel_coord(sibling, axis); int focused_pos = parallel_coord(focused, axis); @@ -277,8 +273,8 @@ static void resize_tiled(struct sway_container *parent, int amount, enum wlr_edges major_edge = axis == RESIZE_AXIS_HORIZONTAL ? WLR_EDGE_RIGHT : WLR_EDGE_BOTTOM; - for (int i = 0; i < parent->parent->children->length; i++) { - struct sway_container *sibling = parent->parent->children->items[i]; + for (int i = 0; i < siblings->length; i++) { + struct sway_container *sibling = siblings->items[i]; int sibling_pos = parallel_coord(sibling, axis); int focused_pos = parallel_coord(focused, axis); @@ -316,7 +312,11 @@ static void resize_tiled(struct sway_container *parent, int amount, } } - arrange_windows(parent->parent); + if (parent->parent) { + arrange_container(parent->parent); + } else { + arrange_workspace(parent->workspace); + } } void container_resize_tiled(struct sway_container *parent, @@ -346,7 +346,7 @@ void container_resize_tiled(struct sway_container *parent, */ static struct cmd_results *resize_adjust_floating(enum resize_axis axis, struct resize_amount *amount) { - struct sway_container *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; int grow_width = 0, grow_height = 0; switch (axis) { case RESIZE_AXIS_HORIZONTAL: @@ -400,15 +400,15 @@ static struct cmd_results *resize_adjust_floating(enum resize_axis axis, con->width += grow_width; con->height += grow_height; - if (con->type == C_VIEW) { - struct sway_view *view = con->sway_view; + if (con->view) { + struct sway_view *view = con->view; view->x += grow_x; view->y += grow_y; view->width += grow_width; view->height += grow_height; } - arrange_windows(con); + arrange_container(con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -418,7 +418,7 @@ static struct cmd_results *resize_adjust_floating(enum resize_axis axis, */ static struct cmd_results *resize_adjust_tiled(enum resize_axis axis, struct resize_amount *amount) { - struct sway_container *current = config->handler_context.current_container; + struct sway_container *current = config->handler_context.container; if (amount->unit == RESIZE_UNIT_DEFAULT) { amount->unit = RESIZE_UNIT_PPT; @@ -456,13 +456,15 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, width->unit == RESIZE_UNIT_DEFAULT) { // Convert to px struct sway_container *parent = con->parent; - while (parent->type >= C_WORKSPACE && parent->layout != L_HORIZ) { + while (parent && parent->layout != L_HORIZ) { parent = parent->parent; } - if (parent->type >= C_WORKSPACE) { + if (parent) { width->amount = parent->width * width->amount / 100; - width->unit = RESIZE_UNIT_PX; + } else { + width->amount = con->workspace->width * width->amount / 100; } + width->unit = RESIZE_UNIT_PX; } if (width->unit == RESIZE_UNIT_PX) { resize_tiled(con, width->amount - con->width, @@ -475,13 +477,15 @@ static struct cmd_results *resize_set_tiled(struct sway_container *con, height->unit == RESIZE_UNIT_DEFAULT) { // Convert to px struct sway_container *parent = con->parent; - while (parent->type >= C_WORKSPACE && parent->layout != L_VERT) { + while (parent && parent->layout != L_VERT) { parent = parent->parent; } - if (parent->type >= C_WORKSPACE) { + if (parent) { height->amount = parent->height * height->amount / 100; - height->unit = RESIZE_UNIT_PX; + } else { + height->amount = con->workspace->height * height->amount / 100; } + height->unit = RESIZE_UNIT_PX; } if (height->unit == RESIZE_UNIT_PX) { resize_tiled(con, height->amount - con->height, @@ -508,15 +512,15 @@ static struct cmd_results *resize_set_floating(struct sway_container *con, con->width = width->amount; con->height = height->amount; - if (con->type == C_VIEW) { - struct sway_view *view = con->sway_view; + if (con->view) { + struct sway_view *view = con->view; view->x -= grow_width / 2; view->y -= grow_height / 2; view->width += grow_width; view->height += grow_height; } - arrange_windows(con); + arrange_container(con); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -555,7 +559,7 @@ static struct cmd_results *cmd_resize_set(int argc, char **argv) { } // If 0, don't resize that dimension - struct sway_container *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; if (width.amount <= 0) { width.amount = con->width; } @@ -624,7 +628,7 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, first_amount.amount *= multiplier; second_amount.amount *= multiplier; - struct sway_container *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; if (container_is_floating(con)) { // Floating containers can only resize in px. Choose an amount which // uses px, with fallback to an amount that specified no unit. @@ -657,14 +661,10 @@ static struct cmd_results *cmd_resize_adjust(int argc, char **argv, } struct cmd_results *cmd_resize(int argc, char **argv) { - struct sway_container *current = config->handler_context.current_container; + struct sway_container *current = config->handler_context.container; if (!current) { return cmd_results_new(CMD_INVALID, "resize", "Cannot resize nothing"); } - if (current->type != C_VIEW && current->type != C_CONTAINER) { - return cmd_results_new(CMD_INVALID, "resize", - "Can only resize views/containers"); - } struct cmd_results *error; if ((error = checkarg(argc, "resize", EXPECTED_AT_LEAST, 2))) { diff --git a/sway/commands/scratchpad.c b/sway/commands/scratchpad.c index 7da20015..d8bae615 100644 --- a/sway/commands/scratchpad.c +++ b/sway/commands/scratchpad.c @@ -9,36 +9,34 @@ static void scratchpad_toggle_auto(void) { struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - struct sway_container *ws = focus->type == C_WORKSPACE ? - focus : container_parent(focus, C_WORKSPACE); + struct sway_container *focus = seat_get_focused_container(seat); + struct sway_workspace *ws = seat_get_focused_workspace(seat); // If the focus is in a floating split container, // operate on the split container instead of the child. - if (container_is_floating_or_child(focus)) { - while (focus->parent->type != C_WORKSPACE) { + if (focus && container_is_floating_or_child(focus)) { + while (focus->parent) { focus = focus->parent; } } - // Check if the currently focused window is a scratchpad window and should // be hidden again. - if (focus->scratchpad) { + if (focus && focus->scratchpad) { wlr_log(WLR_DEBUG, "Focus is a scratchpad window - hiding %s", - focus->name); + focus->title); root_scratchpad_hide(focus); return; } // Check if there is an unfocused scratchpad window on the current workspace // and focus it. - for (int i = 0; i < ws->sway_workspace->floating->length; ++i) { - struct sway_container *floater = ws->sway_workspace->floating->items[i]; + for (int i = 0; i < ws->floating->length; ++i) { + struct sway_container *floater = ws->floating->items[i]; if (floater->scratchpad && focus != floater) { wlr_log(WLR_DEBUG, "Focusing other scratchpad window (%s) in this workspace", - floater->name); + floater->title); root_scratchpad_show(floater); return; } @@ -46,25 +44,23 @@ static void scratchpad_toggle_auto(void) { // Check if there is a visible scratchpad window on another workspace. // In this case we move it to the current workspace. - for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) { - struct sway_container *con = - root_container.sway_root->scratchpad->items[i]; + for (int i = 0; i < root->scratchpad->length; ++i) { + struct sway_container *con = root->scratchpad->items[i]; if (con->parent) { wlr_log(WLR_DEBUG, "Moving a visible scratchpad window (%s) to this workspace", - con->name); + con->title); root_scratchpad_show(con); return; } } // Take the container at the bottom of the scratchpad list - if (!sway_assert(root_container.sway_root->scratchpad->length, - "Scratchpad is empty")) { + if (!sway_assert(root->scratchpad->length, "Scratchpad is empty")) { return; } - struct sway_container *con = root_container.sway_root->scratchpad->items[0]; - wlr_log(WLR_DEBUG, "Showing %s from list", con->name); + struct sway_container *con = root->scratchpad->items[0]; + wlr_log(WLR_DEBUG, "Showing %s from list", con->title); root_scratchpad_show(con); } @@ -74,7 +70,7 @@ static void scratchpad_toggle_container(struct sway_container *con) { } // Check if it matches a currently visible scratchpad window and hide it. - if (con->parent) { + if (con->workspace) { root_scratchpad_hide(con); return; } @@ -91,18 +87,18 @@ struct cmd_results *cmd_scratchpad(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "scratchpad", "Expected 'scratchpad show'"); } - if (!root_container.sway_root->scratchpad->length) { + if (!root->scratchpad->length) { return cmd_results_new(CMD_INVALID, "scratchpad", "Scratchpad is empty"); } if (config->handler_context.using_criteria) { - struct sway_container *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; // If the container is in a floating split container, // operate on the split container instead of the child. if (container_is_floating_or_child(con)) { - while (con->parent->type != C_WORKSPACE) { + while (con->parent) { con = con->parent; } } diff --git a/sway/commands/seat/cursor.c b/sway/commands/seat/cursor.c index 4d0a22c7..cd6630e0 100644 --- a/sway/commands/seat/cursor.c +++ b/sway/commands/seat/cursor.c @@ -42,8 +42,8 @@ struct cmd_results *seat_cmd_cursor(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "cursor", expected_syntax); } // map absolute coords (0..1,0..1) to root container coords - float x = strtof(argv[1], NULL) / root_container.width; - float y = strtof(argv[2], NULL) / root_container.height; + float x = strtof(argv[1], NULL) / root->width; + float y = strtof(argv[2], NULL) / root->height; wlr_cursor_warp_absolute(cursor->cursor, NULL, x, y); cursor_send_pointer_motion(cursor, 0, true); } else { diff --git a/sway/commands/show_marks.c b/sway/commands/show_marks.c index 1844e917..d501584a 100644 --- a/sway/commands/show_marks.c +++ b/sway/commands/show_marks.c @@ -11,8 +11,8 @@ #include "util.h" static void rebuild_marks_iterator(struct sway_container *con, void *data) { - if (con->type == C_VIEW) { - view_update_marks_textures(con->sway_view); + if (con->view) { + view_update_marks_textures(con->view); } } @@ -28,9 +28,9 @@ struct cmd_results *cmd_show_marks(int argc, char **argv) { root_for_each_container(rebuild_marks_iterator, NULL); } - for (int i = 0; i < root_container.children->length; ++i) { - struct sway_container *con = root_container.children->items[i]; - output_damage_whole(con->sway_output); + for (int i = 0; i < root->outputs->length; ++i) { + struct sway_output *output = root->outputs->items[i]; + output_damage_whole(output); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/smart_gaps.c b/sway/commands/smart_gaps.c index 7d27e571..273905df 100644 --- a/sway/commands/smart_gaps.c +++ b/sway/commands/smart_gaps.c @@ -23,7 +23,7 @@ struct cmd_results *cmd_smart_gaps(int argc, char **argv) { "Expected 'smart_gaps <on|off>' "); } - arrange_windows(&root_container); + arrange_root(); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/commands/split.c b/sway/commands/split.c index a8eddf54..9a53f3d3 100644 --- a/sway/commands/split.c +++ b/sway/commands/split.c @@ -4,15 +4,21 @@ #include "sway/tree/arrange.h" #include "sway/tree/container.h" #include "sway/tree/view.h" +#include "sway/tree/workspace.h" #include "sway/input/input-manager.h" #include "sway/input/seat.h" #include "log.h" static struct cmd_results *do_split(int layout) { - struct sway_container *con = config->handler_context.current_container; - struct sway_container *parent = container_split(con, layout); - container_create_notify(parent); - arrange_windows(parent->parent); + struct sway_container *con = config->handler_context.container; + struct sway_workspace *ws = config->handler_context.workspace; + if (con) { + container_split(con, layout); + } else { + workspace_split(ws, layout); + } + + arrange_workspace(ws); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } @@ -29,10 +35,9 @@ struct cmd_results *cmd_split(int argc, char **argv) { return do_split(L_HORIZ); } else if (strcasecmp(argv[0], "t") == 0 || strcasecmp(argv[0], "toggle") == 0) { - struct sway_container *focused = - config->handler_context.current_container; + struct sway_container *focused = config->handler_context.container; - if (focused->parent->layout == L_VERT) { + if (focused && container_parent_layout(focused) == L_VERT) { return do_split(L_HORIZ); } else { return do_split(L_VERT); @@ -66,9 +71,9 @@ struct cmd_results *cmd_splitt(int argc, char **argv) { return error; } - struct sway_container *con = config->handler_context.current_container; + struct sway_container *con = config->handler_context.container; - if (con->parent->layout == L_VERT) { + if (con && container_parent_layout(con) == L_VERT) { return do_split(L_HORIZ); } else { return do_split(L_VERT); diff --git a/sway/commands/sticky.c b/sway/commands/sticky.c index 8692e08d..7995cdd6 100644 --- a/sway/commands/sticky.c +++ b/sway/commands/sticky.c @@ -15,8 +15,7 @@ struct cmd_results *cmd_sticky(int argc, char **argv) { if ((error = checkarg(argc, "sticky", EXPECTED_EQUAL_TO, 1))) { return error; } - struct sway_container *container = - config->handler_context.current_container; + struct sway_container *container = config->handler_context.container; if (!container_is_floating(container)) { return cmd_results_new(CMD_FAILURE, "sticky", "Can't set sticky on a tiled container"); @@ -37,20 +36,16 @@ struct cmd_results *cmd_sticky(int argc, char **argv) { container->is_sticky = wants_sticky; if (wants_sticky) { - // move container to focused workspace - struct sway_container *output = container_parent(container, C_OUTPUT); - struct sway_seat *seat = input_manager_current_seat(input_manager); - struct sway_container *focus = seat_get_focus_inactive(seat, output); - struct sway_container *focused_workspace = container_parent(focus, C_WORKSPACE); - struct sway_container *current_workspace = container_parent(container, C_WORKSPACE); - if (current_workspace != focused_workspace) { - container_remove_child(container); - workspace_add_floating(focused_workspace, container); - container_handle_fullscreen_reparent(container, current_workspace); - arrange_windows(focused_workspace); - if (!container_reap_empty(current_workspace)) { - arrange_windows(current_workspace); - } + // move container to active workspace + struct sway_workspace *active_workspace = + output_get_active_workspace(container->workspace->output); + if (container->workspace != active_workspace) { + struct sway_workspace *old_workspace = container->workspace; + container_detach(container); + workspace_add_floating(active_workspace, container); + container_handle_fullscreen_reparent(container); + arrange_workspace(active_workspace); + workspace_consider_destroy(old_workspace); } } diff --git a/sway/commands/swap.c b/sway/commands/swap.c index f25c43a1..a0ffbda8 100644 --- a/sway/commands/swap.c +++ b/sway/commands/swap.c @@ -4,6 +4,7 @@ #include "config.h" #include "log.h" #include "sway/commands.h" +#include "sway/output.h" #include "sway/tree/arrange.h" #include "sway/tree/root.h" #include "sway/tree/view.h" @@ -43,27 +44,28 @@ static void swap_focus(struct sway_container *con1, struct sway_container *con2, struct sway_seat *seat, struct sway_container *focus) { if (focus == con1 || focus == con2) { - struct sway_container *ws1 = container_parent(con1, C_WORKSPACE); - struct sway_container *ws2 = container_parent(con2, C_WORKSPACE); - if (focus == con1 && (con2->parent->layout == L_TABBED - || con2->parent->layout == L_STACKED)) { + struct sway_workspace *ws1 = con1->workspace; + struct sway_workspace *ws2 = con2->workspace; + enum sway_container_layout layout1 = container_parent_layout(con1); + enum sway_container_layout layout2 = container_parent_layout(con2); + if (focus == con1 && (layout2 == L_TABBED || layout2 == L_STACKED)) { if (workspace_is_visible(ws2)) { - seat_set_focus_warp(seat, con2, false, true); + seat_set_focus_warp(seat, &con2->node, false, true); } - seat_set_focus(seat, ws1 != ws2 ? con2 : con1); - } else if (focus == con2 && (con1->parent->layout == L_TABBED - || con1->parent->layout == L_STACKED)) { + seat_set_focus(seat, ws1 != ws2 ? &con2->node : &con1->node); + } else if (focus == con2 && (layout1 == L_TABBED + || layout1 == L_STACKED)) { if (workspace_is_visible(ws1)) { - seat_set_focus_warp(seat, con1, false, true); + seat_set_focus_warp(seat, &con1->node, false, true); } - seat_set_focus(seat, ws1 != ws2 ? con1 : con2); + seat_set_focus(seat, ws1 != ws2 ? &con1->node : &con2->node); } else if (ws1 != ws2) { - seat_set_focus(seat, focus == con1 ? con2 : con1); + seat_set_focus(seat, focus == con1 ? &con2->node : &con1->node); } else { - seat_set_focus(seat, focus); + seat_set_focus(seat, &focus->node); } } else { - seat_set_focus(seat, focus); + seat_set_focus(seat, &focus->node); } } @@ -72,10 +74,6 @@ static void container_swap(struct sway_container *con1, if (!sway_assert(con1 && con2, "Cannot swap with nothing")) { return; } - if (!sway_assert(con1->type >= C_CONTAINER && con2->type >= C_CONTAINER, - "Can only swap containers and views")) { - return; - } if (!sway_assert(!container_has_ancestor(con1, con2) && !container_has_ancestor(con2, con1), "Cannot swap ancestor and descendant")) { @@ -87,10 +85,11 @@ static void container_swap(struct sway_container *con1, return; } - wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", con1->id, con2->id); + wlr_log(WLR_DEBUG, "Swapping containers %zu and %zu", + con1->node.id, con2->node.id); - int fs1 = con1->is_fullscreen; - int fs2 = con2->is_fullscreen; + bool fs1 = con1->is_fullscreen; + bool fs2 = con2->is_fullscreen; if (fs1) { container_set_fullscreen(con1, false); } @@ -99,13 +98,11 @@ static void container_swap(struct sway_container *con1, } struct sway_seat *seat = input_manager_get_default_seat(input_manager); - struct sway_container *focus = seat_get_focus(seat); - struct sway_container *vis1 = container_parent( - seat_get_focus_inactive(seat, container_parent(con1, C_OUTPUT)), - C_WORKSPACE); - struct sway_container *vis2 = container_parent( - seat_get_focus_inactive(seat, container_parent(con2, C_OUTPUT)), - C_WORKSPACE); + struct sway_container *focus = seat_get_focused_container(seat); + struct sway_workspace *vis1 = + output_get_active_workspace(con1->workspace->output); + struct sway_workspace *vis2 = + output_get_active_workspace(con2->workspace->output); char *stored_prev_name = NULL; if (prev_workspace_name) { @@ -115,10 +112,10 @@ static void container_swap(struct sway_container *con1, swap_places(con1, con2); if (!workspace_is_visible(vis1)) { - seat_set_focus(seat, seat_get_focus_inactive(seat, vis1)); + seat_set_focus(seat, seat_get_focus_inactive(seat, &vis1->node)); } if (!workspace_is_visible(vis2)) { - seat_set_focus(seat, seat_get_focus_inactive(seat, vis2)); + seat_set_focus(seat, seat_get_focus_inactive(seat, &vis2->node)); } swap_focus(con1, con2, seat, focus); @@ -137,23 +134,22 @@ static void container_swap(struct sway_container *con1, } static bool test_con_id(struct sway_container *container, void *con_id) { - return container->id == (size_t)con_id; + return container->node.id == (size_t)con_id; } static bool test_id(struct sway_container *container, void *id) { #ifdef HAVE_XWAYLAND xcb_window_t *wid = id; - return (container->type == C_VIEW - && container->sway_view->type == SWAY_VIEW_XWAYLAND - && container->sway_view->wlr_xwayland_surface->window_id == *wid); + return (container->view && container->view->type == SWAY_VIEW_XWAYLAND + && container->view->wlr_xwayland_surface->window_id == *wid); #else return false; #endif } static bool test_mark(struct sway_container *container, void *mark) { - if (container->type == C_VIEW && container->sway_view->marks->length) { - return !list_seq_find(container->sway_view->marks, + if (container->view && container->view->marks->length) { + return !list_seq_find(container->view->marks, (int (*)(const void *, const void *))strcmp, mark); } return false; @@ -169,7 +165,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "swap", EXPECTED_SYNTAX); } - struct sway_container *current = config->handler_context.current_container; + struct sway_container *current = config->handler_context.container; struct sway_container *other; char *value = join_args(argv + 3, argc - 3); @@ -191,7 +187,7 @@ struct cmd_results *cmd_swap(int argc, char **argv) { if (!other) { error = cmd_results_new(CMD_FAILURE, "swap", "Failed to find %s '%s'", argv[2], value); - } else if (current->type < C_CONTAINER || other->type < C_CONTAINER) { + } else if (!current) { error = cmd_results_new(CMD_FAILURE, "swap", "Can only swap with containers and views"); } else if (container_has_ancestor(current, other) @@ -211,9 +207,9 @@ struct cmd_results *cmd_swap(int argc, char **argv) { container_swap(current, other); - arrange_windows(current->parent); - if (other->parent != current->parent) { - arrange_windows(other->parent); + arrange_node(node_get_parent(¤t->node)); + if (node_get_parent(&other->node) != node_get_parent(¤t->node)) { + arrange_node(node_get_parent(&other->node)); } return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/commands/title_format.c b/sway/commands/title_format.c index 3d1c578c..c9ffe8fa 100644 --- a/sway/commands/title_format.c +++ b/sway/commands/title_format.c @@ -11,13 +11,12 @@ struct cmd_results *cmd_title_format(int argc, char **argv) { if ((error = checkarg(argc, "title_format", EXPECTED_AT_LEAST, 1))) { return error; } - struct sway_container *container = - config->handler_context.current_container; - if (container->type != C_VIEW) { + struct sway_container *container = config->handler_context.container; + if (!container->view) { return cmd_results_new(CMD_INVALID, "title_format", "Only views can have a title_format"); } - struct sway_view *view = container->sway_view; + struct sway_view *view = container->view; char *format = join_args(argv, argc); if (view->title_format) { free(view->title_format); diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c index 62127c97..c6251dc8 100644 --- a/sway/commands/unmark.c +++ b/sway/commands/unmark.c @@ -9,9 +9,9 @@ #include "stringop.h" static void remove_all_marks_iterator(struct sway_container *con, void *data) { - if (con->type == C_VIEW) { - view_clear_marks(con->sway_view); - view_update_marks_textures(con->sway_view); + if (con->view) { + view_clear_marks(con->view); + view_update_marks_textures(con->view); } } @@ -24,13 +24,12 @@ struct cmd_results *cmd_unmark(int argc, char **argv) { // Determine the view struct sway_view *view = NULL; if (config->handler_context.using_criteria) { - struct sway_container *container = - config->handler_context.current_container; - if (container->type != C_VIEW) { + struct sway_container *container = config->handler_context.container; + if (!container->view) { return cmd_results_new(CMD_INVALID, "unmark", "Only views can have marks"); } - view = container->sway_view; + view = container->view; } // Determine the mark diff --git a/sway/commands/urgent.c b/sway/commands/urgent.c index bccb33fe..53c37d4d 100644 --- a/sway/commands/urgent.c +++ b/sway/commands/urgent.c @@ -11,13 +11,12 @@ struct cmd_results *cmd_urgent(int argc, char **argv) { if ((error = checkarg(argc, "urgent", EXPECTED_EQUAL_TO, 1))) { return error; } - struct sway_container *container = - config->handler_context.current_container; - if (container->type != C_VIEW) { + struct sway_container *container = config->handler_context.container; + if (!container->view) { return cmd_results_new(CMD_INVALID, "urgent", "Only views can be urgent"); } - struct sway_view *view = container->sway_view; + struct sway_view *view = container->view; if (strcmp(argv[0], "allow") == 0) { view->allow_request_urgent = true; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index ceb4cd6e..f026a39d 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -58,7 +58,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { } - struct sway_container *ws = NULL; + struct sway_workspace *ws = NULL; if (strcasecmp(argv[0], "number") == 0) { if (argc < 2) { return cmd_results_new(CMD_INVALID, "workspace", |