aboutsummaryrefslogtreecommitdiff
path: root/sway/commands
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2018-09-05 09:33:27 -0400
committerGitHub <noreply@github.com>2018-09-05 09:33:27 -0400
commit610eb946171f782165a20614b2d3318b89273990 (patch)
tree05eec1df1ef48e05b23d273d31143ad32e7632d2 /sway/commands
parentaa2bf98e0442f9bf41a852c2fafee5b0897010a2 (diff)
parentdbf4aa3e33bdee53876c6893b15ac3f224818e7c (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.c13
-rw-r--r--sway/commands/floating.c18
-rw-r--r--sway/commands/focus.c284
-rw-r--r--sway/commands/fullscreen.c18
-rw-r--r--sway/commands/gaps.c35
-rw-r--r--sway/commands/hide_edge_borders.c4
-rw-r--r--sway/commands/kill.c20
-rw-r--r--sway/commands/layout.c185
-rw-r--r--sway/commands/mark.c7
-rw-r--r--sway/commands/move.c887
-rw-r--r--sway/commands/opacity.c3
-rw-r--r--sway/commands/reload.c2
-rw-r--r--sway/commands/rename.c11
-rw-r--r--sway/commands/resize.c86
-rw-r--r--sway/commands/scratchpad.c42
-rw-r--r--sway/commands/seat/cursor.c4
-rw-r--r--sway/commands/show_marks.c10
-rw-r--r--sway/commands/smart_gaps.c2
-rw-r--r--sway/commands/split.c23
-rw-r--r--sway/commands/sticky.c27
-rw-r--r--sway/commands/swap.c76
-rw-r--r--sway/commands/title_format.c7
-rw-r--r--sway/commands/unmark.c13
-rw-r--r--sway/commands/urgent.c7
-rw-r--r--sway/commands/workspace.c2
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(&current->node));
+ if (node_get_parent(&other->node) != node_get_parent(&current->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",