aboutsummaryrefslogtreecommitdiff
path: root/sway/tree
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/arrange.c109
-rw-r--r--sway/tree/container.c873
-rw-r--r--sway/tree/node.c151
-rw-r--r--sway/tree/output.c348
-rw-r--r--sway/tree/root.c186
-rw-r--r--sway/tree/view.c275
-rw-r--r--sway/tree/workspace.c493
7 files changed, 1172 insertions, 1263 deletions
diff --git a/sway/tree/arrange.c b/sway/tree/arrange.c
index 92f20fcc..edb05f86 100644
--- a/sway/tree/arrange.c
+++ b/sway/tree/arrange.c
@@ -166,29 +166,23 @@ void arrange_container(struct sway_container *container) {
if (config->reloading) {
return;
}
- if (container->type == C_VIEW) {
- view_autoconfigure(container->sway_view);
- container_set_dirty(container);
- return;
- }
- if (!sway_assert(container->type == C_CONTAINER, "Expected a container")) {
+ if (container->view) {
+ view_autoconfigure(container->view);
+ node_set_dirty(&container->node);
return;
}
struct wlr_box box;
container_get_box(container, &box);
arrange_children(container->children, container->layout, &box);
- container_set_dirty(container);
+ node_set_dirty(&container->node);
}
-void arrange_workspace(struct sway_container *workspace) {
+void arrange_workspace(struct sway_workspace *workspace) {
if (config->reloading) {
return;
}
- if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
- return;
- }
- struct sway_container *output = workspace->parent;
- struct wlr_box *area = &output->sway_output->usable_area;
+ struct sway_output *output = workspace->output;
+ struct wlr_box *area = &output->usable_area;
wlr_log(WLR_DEBUG, "Usable area for ws: %dx%d@%d,%d",
area->width, area->height, area->x, area->y);
workspace_remove_gaps(workspace);
@@ -197,21 +191,20 @@ void arrange_workspace(struct sway_container *workspace) {
double prev_y = workspace->y;
workspace->width = area->width;
workspace->height = area->height;
- workspace->x = output->x + area->x;
- workspace->y = output->y + area->y;
+ workspace->x = output->wlr_output->lx + area->x;
+ workspace->y = output->wlr_output->ly + area->y;
// Adjust any floating containers
double diff_x = workspace->x - prev_x;
double diff_y = workspace->y - prev_y;
if (diff_x != 0 || diff_y != 0) {
- for (int i = 0; i < workspace->sway_workspace->floating->length; ++i) {
- struct sway_container *floater =
- workspace->sway_workspace->floating->items[i];
+ for (int i = 0; i < workspace->floating->length; ++i) {
+ struct sway_container *floater = workspace->floating->items[i];
container_floating_translate(floater, diff_x, diff_y);
double center_x = floater->x + floater->width / 2;
double center_y = floater->y + floater->height / 2;
struct wlr_box workspace_box;
- container_get_box(workspace, &workspace_box);
+ workspace_get_box(workspace, &workspace_box);
if (!wlr_box_contains_point(&workspace_box, center_x, center_y)) {
container_floating_move_to_center(floater);
}
@@ -219,43 +212,37 @@ void arrange_workspace(struct sway_container *workspace) {
}
workspace_add_gaps(workspace);
- container_set_dirty(workspace);
+ node_set_dirty(&workspace->node);
wlr_log(WLR_DEBUG, "Arranging workspace '%s' at %f, %f", workspace->name,
workspace->x, workspace->y);
- if (workspace->sway_workspace->fullscreen) {
- struct sway_container *fs = workspace->sway_workspace->fullscreen;
- fs->x = workspace->parent->x;
- fs->y = workspace->parent->y;
- fs->width = workspace->parent->width;
- fs->height = workspace->parent->height;
+ if (workspace->fullscreen) {
+ struct sway_container *fs = workspace->fullscreen;
+ fs->x = output->lx;
+ fs->y = output->ly;
+ fs->width = output->width;
+ fs->height = output->height;
arrange_container(fs);
} else {
struct wlr_box box;
- container_get_box(workspace, &box);
- arrange_children(workspace->children, workspace->layout, &box);
- arrange_floating(workspace->sway_workspace->floating);
+ workspace_get_box(workspace, &box);
+ arrange_children(workspace->tiling, workspace->layout, &box);
+ arrange_floating(workspace->floating);
}
}
-void arrange_output(struct sway_container *output) {
+void arrange_output(struct sway_output *output) {
if (config->reloading) {
return;
}
- if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
- return;
- }
const struct wlr_box *output_box = wlr_output_layout_get_box(
- root_container.sway_root->output_layout,
- output->sway_output->wlr_output);
- output->x = output_box->x;
- output->y = output_box->y;
+ root->output_layout, output->wlr_output);
+ output->lx = output_box->x;
+ output->ly = output_box->y;
output->width = output_box->width;
output->height = output_box->height;
- container_set_dirty(output);
- wlr_log(WLR_DEBUG, "Arranging output '%s' at %f,%f",
- output->name, output->x, output->y);
- for (int i = 0; i < output->children->length; ++i) {
- struct sway_container *workspace = output->children->items[i];
+
+ for (int i = 0; i < output->workspaces->length; ++i) {
+ struct sway_workspace *workspace = output->workspaces->items[i];
arrange_workspace(workspace);
}
}
@@ -264,37 +251,31 @@ void arrange_root(void) {
if (config->reloading) {
return;
}
- struct wlr_output_layout *output_layout =
- root_container.sway_root->output_layout;
const struct wlr_box *layout_box =
- wlr_output_layout_get_box(output_layout, NULL);
- root_container.x = layout_box->x;
- root_container.y = layout_box->y;
- root_container.width = layout_box->width;
- root_container.height = layout_box->height;
- container_set_dirty(&root_container);
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
+ wlr_output_layout_get_box(root->output_layout, NULL);
+ root->x = layout_box->x;
+ root->y = layout_box->y;
+ root->width = layout_box->width;
+ root->height = layout_box->height;
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
arrange_output(output);
}
}
-void arrange_windows(struct sway_container *container) {
- switch (container->type) {
- case C_ROOT:
+void arrange_node(struct sway_node *node) {
+ switch (node->type) {
+ case N_ROOT:
arrange_root();
break;
- case C_OUTPUT:
- arrange_output(container);
- break;
- case C_WORKSPACE:
- arrange_workspace(container);
+ case N_OUTPUT:
+ arrange_output(node->sway_output);
break;
- case C_CONTAINER:
- case C_VIEW:
- arrange_container(container);
+ case N_WORKSPACE:
+ arrange_workspace(node->sway_workspace);
break;
- case C_TYPES:
+ case N_CONTAINER:
+ arrange_container(node->sway_container);
break;
}
}
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 520b4566..c91b0361 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -24,97 +24,39 @@
#include "log.h"
#include "stringop.h"
-const char *container_type_to_str(enum sway_container_type type) {
- switch (type) {
- case C_ROOT:
- return "C_ROOT";
- case C_OUTPUT:
- return "C_OUTPUT";
- case C_WORKSPACE:
- return "C_WORKSPACE";
- case C_CONTAINER:
- return "C_CONTAINER";
- case C_VIEW:
- return "C_VIEW";
- default:
- return "C_UNKNOWN";
- }
-}
-
-void container_create_notify(struct sway_container *container) {
- if (container->type == C_VIEW) {
- ipc_event_window(container, "new");
- } else if (container->type == C_WORKSPACE) {
- ipc_event_workspace(NULL, container, "init");
- }
- wl_signal_emit(&root_container.sway_root->events.new_container, container);
-}
-
-void container_update_textures_recursive(struct sway_container *con) {
- if (con->type == C_CONTAINER || con->type == C_VIEW) {
- container_update_title_textures(con);
- }
-
- if (con->type == C_VIEW) {
- view_update_marks_textures(con->sway_view);
- } else {
- for (int i = 0; i < con->children->length; ++i) {
- struct sway_container *child = con->children->items[i];
- container_update_textures_recursive(child);
- }
-
- if (con->type == C_WORKSPACE) {
- for (int i = 0; i < con->sway_workspace->floating->length; ++i) {
- struct sway_container *floater =
- con->sway_workspace->floating->items[i];
- container_update_textures_recursive(floater);
- }
- }
- }
-}
-
-struct sway_container *container_create(enum sway_container_type type) {
- // next id starts at 1 because 0 is assigned to root_container in layout.c
- static size_t next_id = 1;
+struct sway_container *container_create(struct sway_view *view) {
struct sway_container *c = calloc(1, sizeof(struct sway_container));
if (!c) {
+ wlr_log(WLR_ERROR, "Unable to allocate sway_container");
return NULL;
}
- c->id = next_id++;
+ node_init(&c->node, N_CONTAINER, c);
c->layout = L_NONE;
- c->type = type;
+ c->view = view;
c->alpha = 1.0f;
- if (type != C_VIEW) {
+ if (!view) {
c->children = create_list();
c->current.children = create_list();
}
c->outputs = create_list();
wl_signal_init(&c->events.destroy);
-
- c->has_gaps = false;
- c->gaps_inner = 0;
- c->gaps_outer = 0;
- c->current_gaps = 0;
+ wl_signal_emit(&root->events.new_node, &c->node);
return c;
}
void container_destroy(struct sway_container *con) {
- if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
- "Expected a container or view")) {
- return;
- }
- if (!sway_assert(con->destroying,
+ if (!sway_assert(con->node.destroying,
"Tried to free container which wasn't marked as destroying")) {
return;
}
- if (!sway_assert(con->ntxnrefs == 0, "Tried to free container "
+ if (!sway_assert(con->node.ntxnrefs == 0, "Tried to free container "
"which is still referenced by transactions")) {
return;
}
- free(con->name);
+ free(con->title);
free(con->formatted_title);
wlr_texture_destroy(con->title_focused);
wlr_texture_destroy(con->title_focused_inactive);
@@ -124,14 +66,14 @@ void container_destroy(struct sway_container *con) {
list_free(con->current.children);
list_free(con->outputs);
- if (con->type == C_VIEW) {
- struct sway_view *view = con->sway_view;
- view->swayc = NULL;
+ if (con->view) {
+ struct sway_view *view = con->view;
+ view->container = NULL;
free(view->title_format);
view->title_format = NULL;
if (view->destroying) {
- view_destroy(view);
+ view_destroy(con->view);
}
}
@@ -139,115 +81,57 @@ void container_destroy(struct sway_container *con) {
}
void container_begin_destroy(struct sway_container *con) {
- if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
- "Expected a container or view")) {
- return;
- }
-
- if (con->type == C_VIEW) {
+ if (con->view) {
ipc_event_window(con, "close");
}
- wl_signal_emit(&con->events.destroy, con);
+ wl_signal_emit(&con->node.events.destroy, &con->node);
container_end_mouse_operation(con);
- con->destroying = true;
- container_set_dirty(con);
+ con->node.destroying = true;
+ node_set_dirty(&con->node);
if (con->scratchpad) {
root_scratchpad_remove_container(con);
}
- if (con->parent) {
- container_remove_child(con);
+ if (con->parent || con->workspace) {
+ container_detach(con);
}
}
-struct sway_container *container_reap_empty(struct sway_container *con) {
- while (con && con->type == C_CONTAINER) {
- struct sway_container *next = con->parent;
- if (con->children->length == 0) {
- container_begin_destroy(con);
- }
- con = next;
+void container_reap_empty(struct sway_container *con) {
+ if (con->view) {
+ return;
}
- if (con && con->type == C_WORKSPACE) {
- workspace_consider_destroy(con);
- if (con->destroying) {
- con = con->parent;
+ struct sway_workspace *ws = con->workspace;
+ while (con) {
+ if (con->children->length) {
+ return;
}
+ struct sway_container *parent = con->parent;
+ container_begin_destroy(con);
+ con = parent;
}
- return con;
+ workspace_consider_destroy(ws);
}
struct sway_container *container_flatten(struct sway_container *container) {
- while (container->type == C_CONTAINER && container->children->length == 1) {
+ if (container->view) {
+ return NULL;
+ }
+ while (container && container->children->length == 1) {
struct sway_container *child = container->children->items[0];
struct sway_container *parent = container->parent;
- container_replace_child(container, child);
+ container_replace(container, child);
container_begin_destroy(container);
container = parent;
}
return container;
}
-static void container_close_func(struct sway_container *container, void *data) {
- if (container->type == C_VIEW) {
- view_close(container->sway_view);
- }
-}
-
-struct sway_container *container_close(struct sway_container *con) {
- if (!sway_assert(con != NULL,
- "container_close called with a NULL container")) {
- return NULL;
- }
-
- struct sway_container *parent = con->parent;
-
- if (con->type == C_VIEW) {
- view_close(con->sway_view);
- } else if (con->type == C_CONTAINER) {
- container_for_each_child(con, container_close_func, NULL);
- } else if (con->type == C_WORKSPACE) {
- workspace_for_each_container(con, container_close_func, NULL);
- }
-
- return parent;
-}
-
-struct sway_container *container_view_create(struct sway_container *sibling,
- struct sway_view *sway_view) {
- if (!sway_assert(sibling,
- "container_view_create called with NULL sibling/parent")) {
- return NULL;
- }
- const char *title = view_get_title(sway_view);
- struct sway_container *swayc = container_create(C_VIEW);
- wlr_log(WLR_DEBUG, "Adding new view %p:%s to container %p %d %s",
- swayc, title, sibling, sibling ? sibling->type : 0, sibling->name);
- // Setup values
- swayc->sway_view = sway_view;
- swayc->width = 0;
- swayc->height = 0;
-
- if (sibling->type == C_WORKSPACE) {
- // Case of focused workspace, just create as child of it
- container_add_child(sibling, swayc);
- } else {
- // Regular case, create as sibling of current container
- container_add_sibling(sibling, swayc);
- }
- container_create_notify(swayc);
- return swayc;
-}
-
struct sway_container *container_find_child(struct sway_container *container,
- bool (*test)(struct sway_container *view, void *data), void *data) {
- if (!sway_assert(container->type == C_CONTAINER ||
- container->type == C_VIEW, "Expected a container or view")) {
- return NULL;
- }
+ bool (*test)(struct sway_container *con, void *data), void *data) {
if (!container->children) {
return NULL;
}
@@ -264,46 +148,32 @@ struct sway_container *container_find_child(struct sway_container *container,
return NULL;
}
-struct sway_container *container_parent(struct sway_container *container,
- enum sway_container_type type) {
- if (!sway_assert(container, "container is NULL")) {
- return NULL;
- }
- if (!sway_assert(type < C_TYPES && type >= C_ROOT, "invalid type")) {
- return NULL;
- }
- do {
- container = container->parent;
- } while (container && container->type != type);
- return container;
-}
-
-static void surface_at_view(struct sway_container *swayc, double lx, double ly,
+static void surface_at_view(struct sway_container *con, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
- if (!sway_assert(swayc->type == C_VIEW, "Expected a view")) {
+ if (!sway_assert(con->view, "Expected a view")) {
return;
}
- struct sway_view *sview = swayc->sway_view;
- double view_sx = lx - sview->x + sview->geometry.x;
- double view_sy = ly - sview->y + sview->geometry.y;
+ struct sway_view *view = con->view;
+ double view_sx = lx - view->x + view->geometry.x;
+ double view_sy = ly - view->y + view->geometry.y;
double _sx, _sy;
struct wlr_surface *_surface = NULL;
- switch (sview->type) {
+ switch (view->type) {
#ifdef HAVE_XWAYLAND
case SWAY_VIEW_XWAYLAND:
- _surface = wlr_surface_surface_at(sview->surface,
+ _surface = wlr_surface_surface_at(view->surface,
view_sx, view_sy, &_sx, &_sy);
break;
#endif
case SWAY_VIEW_XDG_SHELL_V6:
_surface = wlr_xdg_surface_v6_surface_at(
- sview->wlr_xdg_surface_v6,
+ view->wlr_xdg_surface_v6,
view_sx, view_sy, &_sx, &_sy);
break;
case SWAY_VIEW_XDG_SHELL:
_surface = wlr_xdg_surface_surface_at(
- sview->wlr_xdg_surface,
+ view->wlr_xdg_surface,
view_sx, view_sy, &_sx, &_sy);
break;
}
@@ -317,65 +187,72 @@ static void surface_at_view(struct sway_container *swayc, double lx, double ly,
/**
* container_at for a container with layout L_TABBED.
*/
-static struct sway_container *container_at_tabbed(struct sway_container *parent,
+static struct sway_container *container_at_tabbed(struct sway_node *parent,
double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
- if (ly < parent->y || ly > parent->y + parent->height) {
+ struct wlr_box box;
+ node_get_box(parent, &box);
+ if (ly < box.y || ly > box.y + box.height) {
return NULL;
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
+ list_t *children = node_get_children(parent);
// Tab titles
int title_height = container_titlebar_height();
- if (ly < parent->y + title_height) {
- int tab_width = parent->width / parent->children->length;
- int child_index = (lx - parent->x) / tab_width;
- if (child_index >= parent->children->length) {
- child_index = parent->children->length - 1;
+ if (ly < box.y + title_height) {
+ int tab_width = box.width / children->length;
+ int child_index = (lx - box.x) / tab_width;
+ if (child_index >= children->length) {
+ child_index = children->length - 1;
}
- struct sway_container *child = parent->children->items[child_index];
- return seat_get_focus_inactive(seat, child);
+ struct sway_container *child = children->items[child_index];
+ struct sway_node *node = seat_get_focus_inactive(seat, &child->node);
+ return node->sway_container;
}
// Surfaces
- struct sway_container *current = seat_get_active_child(seat, parent);
-
+ struct sway_node *current = seat_get_active_child(seat, parent);
return tiling_container_at(current, lx, ly, surface, sx, sy);
}
/**
* container_at for a container with layout L_STACKED.
*/
-static struct sway_container *container_at_stacked(
- struct sway_container *parent, double lx, double ly,
+static struct sway_container *container_at_stacked(struct sway_node *parent,
+ double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
- if (ly < parent->y || ly > parent->y + parent->height) {
+ struct wlr_box box;
+ node_get_box(parent, &box);
+ if (ly < box.y || ly > box.y + box.height) {
return NULL;
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
+ list_t *children = node_get_children(parent);
// Title bars
int title_height = container_titlebar_height();
- int child_index = (ly - parent->y) / title_height;
- if (child_index < parent->children->length) {
- struct sway_container *child = parent->children->items[child_index];
- return seat_get_focus_inactive(seat, child);
+ int child_index = (ly - box.y) / title_height;
+ if (child_index < children->length) {
+ struct sway_container *child = children->items[child_index];
+ struct sway_node *node = seat_get_focus_inactive(seat, &child->node);
+ return node->sway_container;
}
// Surfaces
- struct sway_container *current = seat_get_active_child(seat, parent);
-
+ struct sway_node *current = seat_get_active_child(seat, parent);
return tiling_container_at(current, lx, ly, surface, sx, sy);
}
/**
* container_at for a container with layout L_HORIZ or L_VERT.
*/
-static struct sway_container *container_at_linear(struct sway_container *parent,
+static struct sway_container *container_at_linear(struct sway_node *parent,
double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
- for (int i = 0; i < parent->children->length; ++i) {
- struct sway_container *child = parent->children->items[i];
+ list_t *children = node_get_children(parent);
+ for (int i = 0; i < children->length; ++i) {
+ struct sway_container *child = children->items[i];
struct wlr_box box = {
.x = child->x,
.y = child->y,
@@ -383,7 +260,7 @@ static struct sway_container *container_at_linear(struct sway_container *parent,
.height = child->height,
};
if (wlr_box_contains_point(&box, lx, ly)) {
- return tiling_container_at(child, lx, ly, surface, sx, sy);
+ return tiling_container_at(&child->node, lx, ly, surface, sx, sy);
}
}
return NULL;
@@ -391,12 +268,11 @@ static struct sway_container *container_at_linear(struct sway_container *parent,
static struct sway_container *floating_container_at(double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
- for (int j = 0; j < output->children->length; ++j) {
- struct sway_container *workspace = output->children->items[j];
- struct sway_workspace *ws = workspace->sway_workspace;
- if (!workspace_is_visible(workspace)) {
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
+ for (int j = 0; j < output->workspaces->length; ++j) {
+ struct sway_workspace *ws = output->workspaces->items[j];
+ if (!workspace_is_visible(ws)) {
continue;
}
// Items at the end of the list are on top, so iterate the list in
@@ -410,7 +286,7 @@ static struct sway_container *floating_container_at(double lx, double ly,
.height = floater->height,
};
if (wlr_box_contains_point(&box, lx, ly)) {
- return tiling_container_at(floater, lx, ly,
+ return tiling_container_at(&floater->node, lx, ly,
surface, sx, sy);
}
}
@@ -419,25 +295,24 @@ static struct sway_container *floating_container_at(double lx, double ly,
return NULL;
}
-struct sway_container *tiling_container_at(
- struct sway_container *con, double lx, double ly,
+struct sway_container *tiling_container_at(struct sway_node *parent,
+ double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
- if (con->type == C_VIEW) {
- surface_at_view(con, lx, ly, surface, sx, sy);
- return con;
+ if (node_is_view(parent)) {
+ surface_at_view(parent->sway_container, lx, ly, surface, sx, sy);
+ return parent->sway_container;
}
- if (!con->children->length) {
+ if (!node_get_children(parent)) {
return NULL;
}
-
- switch (con->layout) {
+ switch (node_get_layout(parent)) {
case L_HORIZ:
case L_VERT:
- return container_at_linear(con, lx, ly, surface, sx, sy);
+ return container_at_linear(parent, lx, ly, surface, sx, sy);
case L_TABBED:
- return container_at_tabbed(con, lx, ly, surface, sx, sy);
+ return container_at_tabbed(parent, lx, ly, surface, sx, sy);
case L_STACKED:
- return container_at_stacked(con, lx, ly, surface, sx, sy);
+ return container_at_stacked(parent, lx, ly, surface, sx, sy);
case L_NONE:
return NULL;
}
@@ -472,19 +347,16 @@ static bool surface_is_popup(struct wlr_surface *surface) {
return false;
}
-struct sway_container *container_at(struct sway_container *workspace,
+struct sway_container *container_at(struct sway_workspace *workspace,
double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
- if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
- return NULL;
- }
struct sway_container *c;
+ // Focused view's popups
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus =
- seat_get_focus_inactive(seat, &root_container);
+ struct sway_container *focus = seat_get_focused_container(seat);
bool is_floating = focus && container_is_floating_or_child(focus);
// Focused view's popups
- if (focus && focus->type == C_VIEW) {
+ if (focus && focus->view) {
surface_at_view(focus, lx, ly, surface, sx, sy);
if (*surface && surface_is_popup(*surface)) {
return focus;
@@ -492,7 +364,7 @@ struct sway_container *container_at(struct sway_container *workspace,
*surface = NULL;
}
// If focused is floating, focused view's non-popups
- if (focus && focus->type == C_VIEW && is_floating) {
+ if (focus && focus->view && is_floating) {
surface_at_view(focus, lx, ly, surface, sx, sy);
if (*surface) {
return focus;
@@ -504,7 +376,7 @@ struct sway_container *container_at(struct sway_container *workspace,
return c;
}
// If focused is tiling, focused view's non-popups
- if (focus && focus->type == C_VIEW && !is_floating) {
+ if (focus && focus->view && !is_floating) {
surface_at_view(focus, lx, ly, surface, sx, sy);
if (*surface) {
return focus;
@@ -512,7 +384,7 @@ struct sway_container *container_at(struct sway_container *workspace,
*surface = NULL;
}
// Tiling (non-focused)
- if ((c = tiling_container_at(workspace, lx, ly, surface, sx, sy))) {
+ if ((c = tiling_container_at(&workspace->node, lx, ly, surface, sx, sy))) {
return c;
}
return NULL;
@@ -521,10 +393,6 @@ struct sway_container *container_at(struct sway_container *workspace,
void container_for_each_child(struct sway_container *container,
void (*f)(struct sway_container *container, void *data),
void *data) {
- if (!sway_assert(container->type == C_CONTAINER ||
- container->type == C_VIEW, "Expected a container or view")) {
- return;
- }
if (container->children) {
for (int i = 0; i < container->children->length; ++i) {
struct sway_container *child = container->children->items[i];
@@ -536,7 +404,7 @@ void container_for_each_child(struct sway_container *container,
bool container_has_ancestor(struct sway_container *descendant,
struct sway_container *ancestor) {
- while (descendant && descendant->type != C_ROOT) {
+ while (descendant) {
descendant = descendant->parent;
if (descendant == ancestor) {
return true;
@@ -545,27 +413,10 @@ bool container_has_ancestor(struct sway_container *descendant,
return false;
}
-int container_count_descendants_of_type(struct sway_container *con,
- enum sway_container_type type) {
- int children = 0;
- if (con->type == type) {
- children++;
- }
- if (con->children) {
- for (int i = 0; i < con->children->length; i++) {
- struct sway_container *child = con->children->items[i];
- children += container_count_descendants_of_type(child, type);
- }
- }
- return children;
-}
-
void container_damage_whole(struct sway_container *container) {
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *cont = root_container.children->items[i];
- if (cont->type == C_OUTPUT) {
- output_damage_whole_container(cont->sway_output, container);
- }
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
+ output_damage_whole_container(output, container);
}
}
@@ -582,10 +433,6 @@ struct sway_output *container_get_effective_output(struct sway_container *con) {
static void update_title_texture(struct sway_container *con,
struct wlr_texture **texture, struct border_colors *class) {
- if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
- "Unexpected type %s", container_type_to_str(con->type))) {
- return;
- }
struct sway_output *output = container_get_effective_output(con);
if (!output) {
return;
@@ -664,9 +511,10 @@ void container_calculate_title_height(struct sway_container *container) {
* An example tree representation is: V[Terminal, Firefox]
* If buffer is not NULL, also populate the buffer with the representation.
*/
-static size_t get_tree_representation(struct sway_container *parent, char *buffer) {
+size_t container_build_representation(enum sway_container_layout layout,
+ list_t *children, char *buffer) {
size_t len = 2;
- switch (parent->layout) {
+ switch (layout) {
case L_VERT:
lenient_strcat(buffer, "V[");
break;
@@ -683,17 +531,17 @@ static size_t get_tree_representation(struct sway_container *parent, char *buffe
lenient_strcat(buffer, "D[");
break;
}
- for (int i = 0; i < parent->children->length; ++i) {
+ for (int i = 0; i < children->length; ++i) {
if (i != 0) {
++len;
lenient_strcat(buffer, " ");
}
- struct sway_container *child = parent->children->items[i];
+ struct sway_container *child = children->items[i];
const char *identifier = NULL;
- if (child->type == C_VIEW) {
- identifier = view_get_class(child->sway_view);
+ if (child->view) {
+ identifier = view_get_class(child->view);
if (!identifier) {
- identifier = view_get_app_id(child->sway_view);
+ identifier = view_get_app_id(child->view);
}
} else {
identifier = child->formatted_title;
@@ -711,25 +559,25 @@ static size_t get_tree_representation(struct sway_container *parent, char *buffe
return len;
}
-void container_notify_subtree_changed(struct sway_container *container) {
- if (!container || container->type < C_WORKSPACE) {
- return;
- }
- free(container->formatted_title);
- container->formatted_title = NULL;
-
- size_t len = get_tree_representation(container, NULL);
- char *buffer = calloc(len + 1, sizeof(char));
- if (!sway_assert(buffer, "Unable to allocate title string")) {
- return;
+void container_update_representation(struct sway_container *con) {
+ if (!con->view) {
+ size_t len = container_build_representation(con->layout,
+ con->children, NULL);
+ free(con->formatted_title);
+ con->formatted_title = calloc(len + 1, sizeof(char));
+ if (!sway_assert(con->formatted_title,
+ "Unable to allocate title string")) {
+ return;
+ }
+ container_build_representation(con->layout, con->children,
+ con->formatted_title);
+ container_calculate_title_height(con);
+ container_update_title_textures(con);
}
- get_tree_representation(container, buffer);
-
- container->formatted_title = buffer;
- if (container->type != C_WORKSPACE) {
- container_calculate_title_height(container);
- container_update_title_textures(container);
- container_notify_subtree_changed(container->parent);
+ if (con->parent) {
+ container_update_representation(con->parent);
+ } else if (con->workspace) {
+ workspace_update_representation(con->workspace);
}
}
@@ -738,11 +586,7 @@ size_t container_titlebar_height() {
}
void container_init_floating(struct sway_container *con) {
- if (!sway_assert(con->type == C_VIEW || con->type == C_CONTAINER,
- "Expected a view or container")) {
- return;
- }
- struct sway_container *ws = container_parent(con, C_WORKSPACE);
+ struct sway_workspace *ws = con->workspace;
int min_width, min_height;
int max_width, max_height;
@@ -778,13 +622,13 @@ void container_init_floating(struct sway_container *con) {
max_height = config->floating_maximum_height;
}
- if (con->type == C_CONTAINER) {
+ if (!con->view) {
con->width = max_width;
con->height = max_height;
con->x = ws->x + (ws->width - con->width) / 2;
con->y = ws->y + (ws->height - con->height) / 2;
} else {
- struct sway_view *view = con->sway_view;
+ struct sway_view *view = con->view;
view->width = fmax(min_width, fmin(view->natural_width, max_width));
view->height = fmax(min_height, fmin(view->natural_height, max_height));
view->x = ws->x + (ws->width - view->width) / 2;
@@ -794,7 +638,7 @@ void container_init_floating(struct sway_container *con) {
view->border_top = view->border_bottom = true;
view->border_left = view->border_right = true;
- container_set_geometry_from_floating_view(view->swayc);
+ container_set_geometry_from_floating_view(con);
}
}
@@ -804,32 +648,41 @@ void container_set_floating(struct sway_container *container, bool enable) {
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *workspace = container_parent(container, C_WORKSPACE);
+ struct sway_workspace *workspace = container->workspace;
if (enable) {
- struct sway_container *old_parent = container_remove_child(container);
+ struct sway_container *old_parent = container->parent;
+ container_detach(container);
workspace_add_floating(workspace, container);
container_init_floating(container);
- if (container->type == C_VIEW) {
- view_set_tiled(container->sway_view, false);
+ if (container->view) {
+ view_set_tiled(container->view, false);
+ }
+ if (old_parent) {
+ container_reap_empty(old_parent);
}
- container_reap_empty(old_parent);
} else {
// Returning to tiled
if (container->scratchpad) {
root_scratchpad_remove_container(container);
}
- container_remove_child(container);
+ container_detach(container);
struct sway_container *reference =
seat_get_focus_inactive_tiling(seat, workspace);
- if (reference->type == C_VIEW) {
+ if (reference && reference->view) {
reference = reference->parent;
}
- container_add_child(reference, container);
- container->width = container->parent->width;
- container->height = container->parent->height;
- if (container->type == C_VIEW) {
- view_set_tiled(container->sway_view, true);
+ if (reference) {
+ container_add_child(reference, container);
+ container->width = reference->width;
+ container->height = reference->height;
+ } else {
+ workspace_add_tiling(workspace, container);
+ container->width = workspace->width;
+ container->height = workspace->height;
+ }
+ if (container->view) {
+ view_set_tiled(container->view, true);
}
container->is_sticky = false;
}
@@ -840,14 +693,13 @@ void container_set_floating(struct sway_container *container, bool enable) {
}
void container_set_geometry_from_floating_view(struct sway_container *con) {
- if (!sway_assert(con->type == C_VIEW, "Expected a view")) {
+ if (!sway_assert(con->view, "Expected a view")) {
return;
}
- if (!sway_assert(container_is_floating(con),
- "Expected a floating view")) {
+ if (!sway_assert(container_is_floating(con), "Expected a floating view")) {
return;
}
- struct sway_view *view = con->sway_view;
+ struct sway_view *view = con->view;
size_t border_width = 0;
size_t top = 0;
@@ -861,12 +713,12 @@ void container_set_geometry_from_floating_view(struct sway_container *con) {
con->y = view->y - top;
con->width = view->width + border_width * 2;
con->height = top + view->height + border_width;
- container_set_dirty(con);
+ node_set_dirty(&con->node);
}
bool container_is_floating(struct sway_container *container) {
- return container->parent && container->parent->type == C_WORKSPACE &&
- list_find(container->parent->sway_workspace->floating, container) != -1;
+ return !container->parent && container->workspace &&
+ list_find(container->workspace->floating, container) != -1;
}
void container_get_box(struct sway_container *container, struct wlr_box *box) {
@@ -883,16 +735,16 @@ void container_floating_translate(struct sway_container *con,
double x_amount, double y_amount) {
con->x += x_amount;
con->y += y_amount;
- if (con->type == C_VIEW) {
- con->sway_view->x += x_amount;
- con->sway_view->y += y_amount;
+ if (con->view) {
+ con->view->x += x_amount;
+ con->view->y += y_amount;
} else {
for (int i = 0; i < con->children->length; ++i) {
struct sway_container *child = con->children->items[i];
container_floating_translate(child, x_amount, y_amount);
}
}
- container_set_dirty(con);
+ node_set_dirty(&con->node);
}
/**
@@ -902,17 +754,16 @@ void container_floating_translate(struct sway_container *con,
* one, otherwise we'll choose whichever output is closest to the container's
* center.
*/
-struct sway_container *container_floating_find_output(
- struct sway_container *con) {
+struct sway_output *container_floating_find_output(struct sway_container *con) {
double center_x = con->x + con->width / 2;
double center_y = con->y + con->height / 2;
- struct sway_container *closest_output = NULL;
+ struct sway_output *closest_output = NULL;
double closest_distance = DBL_MAX;
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
struct wlr_box output_box;
double closest_x, closest_y;
- container_get_box(output, &output_box);
+ output_get_box(output, &output_box);
wlr_box_closest_point(&output_box, center_x, center_y,
&closest_x, &closest_y);
if (center_x == closest_x && center_y == closest_y) {
@@ -937,18 +788,18 @@ void container_floating_move_to(struct sway_container *con,
return;
}
container_floating_translate(con, lx - con->x, ly - con->y);
- struct sway_container *old_workspace = container_parent(con, C_WORKSPACE);
- struct sway_container *new_output = container_floating_find_output(con);
+ struct sway_workspace *old_workspace = con->workspace;
+ struct sway_output *new_output = container_floating_find_output(con);
if (!sway_assert(new_output, "Unable to find any output")) {
return;
}
- struct sway_container *new_workspace =
- output_get_active_workspace(new_output->sway_output);
+ struct sway_workspace *new_workspace =
+ output_get_active_workspace(new_output);
if (old_workspace != new_workspace) {
- container_remove_child(con);
+ container_detach(con);
workspace_add_floating(new_workspace, con);
- arrange_windows(old_workspace);
- arrange_windows(new_workspace);
+ arrange_workspace(old_workspace);
+ arrange_workspace(new_workspace);
workspace_detect_urgent(old_workspace);
workspace_detect_urgent(new_workspace);
}
@@ -959,22 +810,14 @@ void container_floating_move_to_center(struct sway_container *con) {
"Expected a floating container")) {
return;
}
- struct sway_container *ws = container_parent(con, C_WORKSPACE);
+ struct sway_workspace *ws = con->workspace;
double new_lx = ws->x + (ws->width - con->width) / 2;
double new_ly = ws->y + (ws->height - con->height) / 2;
container_floating_translate(con, new_lx - con->x, new_ly - con->y);
}
-void container_set_dirty(struct sway_container *container) {
- if (container->dirty) {
- return;
- }
- container->dirty = true;
- list_add(server.dirty_containers, container);
-}
-
static bool find_urgent_iterator(struct sway_container *con, void *data) {
- return con->type == C_VIEW && view_is_urgent(con->sway_view);
+ return con->view && view_is_urgent(con->view);
}
bool container_has_urgent_child(struct sway_container *container) {
@@ -991,12 +834,12 @@ void container_end_mouse_operation(struct sway_container *container) {
}
static void set_fullscreen_iterator(struct sway_container *con, void *data) {
- if (con->type != C_VIEW) {
+ if (!con->view) {
return;
}
- if (con->sway_view->impl->set_fullscreen) {
+ if (con->view->impl->set_fullscreen) {
bool *enable = data;
- con->sway_view->impl->set_fullscreen(con->sway_view, *enable);
+ con->view->impl->set_fullscreen(con->view, *enable);
}
}
@@ -1005,9 +848,9 @@ void container_set_fullscreen(struct sway_container *container, bool enable) {
return;
}
- struct sway_container *workspace = container_parent(container, C_WORKSPACE);
- if (enable && workspace->sway_workspace->fullscreen) {
- container_set_fullscreen(workspace->sway_workspace->fullscreen, false);
+ struct sway_workspace *workspace = container->workspace;
+ if (enable && workspace->fullscreen) {
+ container_set_fullscreen(workspace->fullscreen, false);
}
set_fullscreen_iterator(container, &enable);
@@ -1016,36 +859,32 @@ void container_set_fullscreen(struct sway_container *container, bool enable) {
container->is_fullscreen = enable;
if (enable) {
- workspace->sway_workspace->fullscreen = container;
+ workspace->fullscreen = container;
container->saved_x = container->x;
container->saved_y = container->y;
container->saved_width = container->width;
container->saved_height = container->height;
struct sway_seat *seat;
- struct sway_container *focus, *focus_ws;
+ struct sway_workspace *focus_ws;
wl_list_for_each(seat, &input_manager->seats, link) {
- focus = seat_get_focus(seat);
- if (focus) {
- focus_ws = focus;
- if (focus_ws->type != C_WORKSPACE) {
- focus_ws = container_parent(focus_ws, C_WORKSPACE);
- }
+ focus_ws = seat_get_focused_workspace(seat);
+ if (focus_ws) {
if (focus_ws == workspace) {
- seat_set_focus(seat, container);
+ seat_set_focus(seat, &container->node);
}
}
}
} else {
- workspace->sway_workspace->fullscreen = NULL;
+ workspace->fullscreen = NULL;
if (container_is_floating(container)) {
container->x = container->saved_x;
container->y = container->saved_y;
container->width = container->saved_width;
container->height = container->saved_height;
- struct sway_container *output =
+ struct sway_output *output =
container_floating_find_output(container);
- if (!container_has_ancestor(container, output)) {
+ if (workspace->output != output) {
container_floating_move_to_center(container);
}
} else {
@@ -1060,7 +899,7 @@ void container_set_fullscreen(struct sway_container *container, bool enable) {
}
bool container_is_floating_or_child(struct sway_container *container) {
- while (container->parent && container->parent->type != C_WORKSPACE) {
+ while (container->parent) {
container = container->parent;
}
return container_is_floating(container);
@@ -1072,7 +911,7 @@ bool container_is_fullscreen_or_child(struct sway_container *container) {
return true;
}
container = container->parent;
- } while (container && container->type != C_WORKSPACE);
+ } while (container);
return false;
}
@@ -1090,42 +929,37 @@ static void surface_send_leave_iterator(struct wlr_surface *surface,
}
void container_discover_outputs(struct sway_container *con) {
- if (!sway_assert(con->type == C_CONTAINER || con->type == C_VIEW,
- "Expected a container or view")) {
- return;
- }
struct wlr_box con_box = {
- .x = con->current.swayc_x,
- .y = con->current.swayc_y,
- .width = con->current.swayc_width,
- .height = con->current.swayc_height,
+ .x = con->current.con_x,
+ .y = con->current.con_y,
+ .width = con->current.con_width,
+ .height = con->current.con_height,
};
struct sway_output *old_output = container_get_effective_output(con);
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
- struct sway_output *sway_output = output->sway_output;
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
struct wlr_box output_box;
- container_get_box(output, &output_box);
+ output_get_box(output, &output_box);
struct wlr_box intersection;
bool intersects =
wlr_box_intersection(&con_box, &output_box, &intersection);
- int index = list_find(con->outputs, sway_output);
+ int index = list_find(con->outputs, output);
if (intersects && index == -1) {
// Send enter
- wlr_log(WLR_DEBUG, "Con %p entered output %p", con, sway_output);
- if (con->type == C_VIEW) {
- view_for_each_surface(con->sway_view,
- surface_send_enter_iterator, sway_output->wlr_output);
+ wlr_log(WLR_DEBUG, "Container %p entered output %p", con, output);
+ if (con->view) {
+ view_for_each_surface(con->view,
+ surface_send_enter_iterator, output->wlr_output);
}
- list_add(con->outputs, sway_output);
+ list_add(con->outputs, output);
} else if (!intersects && index != -1) {
// Send leave
- wlr_log(WLR_DEBUG, "Con %p left output %p", con, sway_output);
- if (con->type == C_VIEW) {
- view_for_each_surface(con->sway_view,
- surface_send_leave_iterator, sway_output->wlr_output);
+ wlr_log(WLR_DEBUG, "Container %p left output %p", con, output);
+ if (con->view) {
+ view_for_each_surface(con->view,
+ surface_send_leave_iterator, output->wlr_output);
}
list_del(con->outputs, index);
}
@@ -1135,17 +969,13 @@ void container_discover_outputs(struct sway_container *con) {
double new_scale = new_output ? new_output->wlr_output->scale : -1;
if (old_scale != new_scale) {
container_update_title_textures(con);
- if (con->type == C_VIEW) {
- view_update_marks_textures(con->sway_view);
+ if (con->view) {
+ view_update_marks_textures(con->view);
}
}
}
void container_remove_gaps(struct sway_container *c) {
- if (!sway_assert(c->type == C_CONTAINER || c->type == C_VIEW,
- "Expected a container or view")) {
- return;
- }
if (c->current_gaps == 0) {
return;
}
@@ -1158,25 +988,20 @@ void container_remove_gaps(struct sway_container *c) {
}
void container_add_gaps(struct sway_container *c) {
- if (!sway_assert(c->type == C_CONTAINER || c->type == C_VIEW,
- "Expected a container or view")) {
- return;
- }
if (c->current_gaps > 0) {
return;
}
// Linear containers don't have gaps because it'd create double gaps
- if (c->type == C_CONTAINER &&
- c->layout != L_TABBED && c->layout != L_STACKED) {
+ if (!c->view && c->layout != L_TABBED && c->layout != L_STACKED) {
return;
}
// Children of tabbed/stacked containers re-use the gaps of the container
- enum sway_container_layout layout = c->parent->layout;
+ enum sway_container_layout layout = container_parent_layout(c);
if (layout == L_TABBED || layout == L_STACKED) {
return;
}
- struct sway_container *ws = container_parent(c, C_WORKSPACE);
+ struct sway_workspace *ws = c->workspace;
c->current_gaps = ws->has_gaps ? ws->gaps_inner : config->gaps_inner;
c->x += c->current_gaps;
@@ -1185,222 +1010,158 @@ void container_add_gaps(struct sway_container *c) {
c->height -= 2 * c->current_gaps;
}
-int container_sibling_index(const struct sway_container *child) {
- return list_find(child->parent->children, child);
+enum sway_container_layout container_parent_layout(struct sway_container *con) {
+ if (con->parent) {
+ return con->parent->layout;
+ }
+ return con->workspace->layout;
}
-void container_handle_fullscreen_reparent(struct sway_container *con,
- struct sway_container *old_parent) {
- if (!con->is_fullscreen) {
- return;
+enum sway_container_layout container_current_parent_layout(
+ struct sway_container *con) {
+ if (con->current.parent) {
+ return con->current.parent->current.layout;
}
- struct sway_container *old_workspace = old_parent;
- if (old_workspace && old_workspace->type != C_WORKSPACE) {
- old_workspace = container_parent(old_workspace, C_WORKSPACE);
+ return con->current.workspace->current.layout;
+}
+
+list_t *container_get_siblings(const struct sway_container *container) {
+ if (container->parent) {
+ return container->parent->children;
}
- struct sway_container *new_workspace = container_parent(con, C_WORKSPACE);
- if (old_workspace == new_workspace) {
- return;
+ if (!container->workspace) {
+ return NULL;
}
- // Unmark the old workspace as fullscreen
- if (old_workspace) {
- old_workspace->sway_workspace->fullscreen = NULL;
+ if (list_find(container->workspace->tiling, container) != -1) {
+ return container->workspace->tiling;
}
+ return container->workspace->floating;
+}
- // Mark the new workspace as fullscreen
- if (new_workspace->sway_workspace->fullscreen) {
- container_set_fullscreen(
- new_workspace->sway_workspace->fullscreen, false);
- }
- new_workspace->sway_workspace->fullscreen = con;
+int container_sibling_index(const struct sway_container *child) {
+ return list_find(container_get_siblings(child), child);
+}
- // Resize container to new output dimensions
- struct sway_container *output = new_workspace->parent;
- con->x = output->x;
- con->y = output->y;
- con->width = output->width;
- con->height = output->height;
+list_t *container_get_current_siblings(struct sway_container *container) {
+ if (container->current.parent) {
+ return container->current.parent->current.children;
+ }
+ return container->current.workspace->current.tiling;
+}
- if (con->type == C_VIEW) {
- struct sway_view *view = con->sway_view;
- view->x = output->x;
- view->y = output->y;
- view->width = output->width;
- view->height = output->height;
- } else {
- arrange_windows(new_workspace);
+void container_handle_fullscreen_reparent(struct sway_container *con) {
+ if (!con->is_fullscreen || con->workspace->fullscreen == con) {
+ return;
}
+ if (con->workspace->fullscreen) {
+ container_set_fullscreen(con->workspace->fullscreen, false);
+ }
+ con->workspace->fullscreen = con;
+
+ arrange_workspace(con->workspace);
+}
+
+static void set_workspace(struct sway_container *container, void *data) {
+ container->workspace = container->parent->workspace;
}
void container_insert_child(struct sway_container *parent,
struct sway_container *child, int i) {
- struct sway_container *old_parent = child->parent;
- if (old_parent) {
- container_remove_child(child);
+ if (child->workspace) {
+ container_detach(child);
}
- wlr_log(WLR_DEBUG, "Inserting id:%zd at index %d", child->id, i);
list_insert(parent->children, i, child);
child->parent = parent;
- container_handle_fullscreen_reparent(child, old_parent);
+ child->workspace = parent->workspace;
+ container_for_each_child(child, set_workspace, NULL);
+ container_handle_fullscreen_reparent(child);
+ container_update_representation(parent);
}
-struct sway_container *container_add_sibling(struct sway_container *fixed,
+void container_add_sibling(struct sway_container *fixed,
struct sway_container *active) {
- // TODO handle floating
- struct sway_container *old_parent = NULL;
- if (active->parent) {
- old_parent = active->parent;
- container_remove_child(active);
- }
- struct sway_container *parent = fixed->parent;
- int i = container_sibling_index(fixed);
- list_insert(parent->children, i + 1, active);
- active->parent = parent;
- container_handle_fullscreen_reparent(active, old_parent);
- return active->parent;
+ if (active->workspace) {
+ container_detach(active);
+ }
+ list_t *siblings = container_get_siblings(fixed);
+ int index = list_find(siblings, fixed);
+ list_insert(siblings, index + 1, active);
+ active->parent = fixed->parent;
+ active->workspace = fixed->workspace;
+ container_for_each_child(active, set_workspace, NULL);
+ container_handle_fullscreen_reparent(active);
+ container_update_representation(active);
}
void container_add_child(struct sway_container *parent,
struct sway_container *child) {
- wlr_log(WLR_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)",
- child, child->type, child->width, child->height,
- parent, parent->type, parent->width, parent->height);
- struct sway_container *old_parent = child->parent;
+ if (child->workspace) {
+ container_detach(child);
+ }
list_add(parent->children, child);
child->parent = parent;
- container_handle_fullscreen_reparent(child, old_parent);
- if (old_parent) {
- container_set_dirty(old_parent);
- }
- container_set_dirty(child);
+ child->workspace = parent->workspace;
+ container_for_each_child(child, set_workspace, NULL);
+ container_handle_fullscreen_reparent(child);
+ container_update_representation(parent);
+ node_set_dirty(&child->node);
+ node_set_dirty(&parent->node);
}
-struct sway_container *container_remove_child(struct sway_container *child) {
+void container_detach(struct sway_container *child) {
if (child->is_fullscreen) {
- struct sway_container *workspace = container_parent(child, C_WORKSPACE);
- workspace->sway_workspace->fullscreen = NULL;
+ child->workspace->fullscreen = NULL;
}
- struct sway_container *parent = child->parent;
- list_t *list = container_is_floating(child) ?
- parent->sway_workspace->floating : parent->children;
- int index = list_find(list, child);
- if (index != -1) {
- list_del(list, index);
+ struct sway_container *old_parent = child->parent;
+ struct sway_workspace *old_workspace = child->workspace;
+ list_t *siblings = container_get_siblings(child);
+ if (siblings) {
+ int index = list_find(siblings, child);
+ if (index != -1) {
+ list_del(siblings, index);
+ }
}
child->parent = NULL;
- container_notify_subtree_changed(parent);
+ child->workspace = NULL;
+ container_for_each_child(child, set_workspace, NULL);
- container_set_dirty(parent);
- container_set_dirty(child);
-
- return parent;
-}
-
-enum sway_container_layout container_get_default_layout(
- struct sway_container *con) {
- if (con->type != C_OUTPUT) {
- con = container_parent(con, C_OUTPUT);
- }
-
- if (!sway_assert(con != NULL,
- "container_get_default_layout must be called on an attached"
- " container below the root container")) {
- return 0;
- }
-
- if (config->default_layout != L_NONE) {
- return config->default_layout;
- } else if (config->default_orientation != L_NONE) {
- return config->default_orientation;
- } else if (con->width >= con->height) {
- return L_HORIZ;
- } else {
- return L_VERT;
+ if (old_parent) {
+ container_update_representation(old_parent);
+ node_set_dirty(&old_parent->node);
+ } else if (old_workspace) {
+ workspace_update_representation(old_workspace);
+ node_set_dirty(&old_workspace->node);
}
+ node_set_dirty(&child->node);
}
-struct sway_container *container_replace_child(struct sway_container *child,
- struct sway_container *new_child) {
- struct sway_container *parent = child->parent;
- if (parent == NULL) {
- return NULL;
- }
-
- list_t *list = container_is_floating(child) ?
- parent->sway_workspace->floating : parent->children;
- int i = list_find(list, child);
-
- if (new_child->parent) {
- container_remove_child(new_child);
- }
- list->items[i] = new_child;
- new_child->parent = parent;
- child->parent = NULL;
-
- // Set geometry for new child
- new_child->x = child->x;
- new_child->y = child->y;
- new_child->width = child->width;
- new_child->height = child->height;
-
- // reset geometry for child
- child->width = 0;
- child->height = 0;
-
- return parent;
+void container_replace(struct sway_container *container,
+ struct sway_container *replacement) {
+ container_add_sibling(container, replacement);
+ container_detach(container);
}
struct sway_container *container_split(struct sway_container *child,
enum sway_container_layout layout) {
- // TODO floating: cannot split a floating container
- if (!sway_assert(child, "child cannot be null")) {
- return NULL;
- }
- if (child->type == C_WORKSPACE && child->children->length == 0) {
- // Special case: this just behaves like splitt
- child->prev_split_layout = child->layout;
- child->layout = layout;
- return child;
- }
-
- struct sway_container *cont = container_create(C_CONTAINER);
-
- wlr_log(WLR_DEBUG, "creating container %p around %p", cont, child);
+ struct sway_seat *seat = input_manager_get_default_seat(input_manager);
+ bool set_focus = (seat_get_focus(seat) == &child->node);
- cont->prev_split_layout = L_NONE;
+ struct sway_container *cont = container_create(NULL);
cont->width = child->width;
cont->height = child->height;
cont->x = child->x;
cont->y = child->y;
cont->current_gaps = child->current_gaps;
+ cont->layout = layout;
- struct sway_seat *seat = input_manager_get_default_seat(input_manager);
- bool set_focus = (seat_get_focus(seat) == child);
-
- if (child->type == C_WORKSPACE) {
- struct sway_container *workspace = child;
- while (workspace->children->length) {
- struct sway_container *ws_child = workspace->children->items[0];
- container_remove_child(ws_child);
- container_add_child(cont, ws_child);
- }
-
- container_add_child(workspace, cont);
- enum sway_container_layout old_layout = workspace->layout;
- workspace->layout = layout;
- cont->layout = old_layout;
- } else {
- cont->layout = layout;
- container_replace_child(child, cont);
- container_add_child(cont, child);
- }
+ container_replace(child, cont);
+ container_add_child(cont, child);
if (set_focus) {
- seat_set_focus(seat, cont);
- seat_set_focus(seat, child);
+ seat_set_focus(seat, &cont->node);
+ seat_set_focus(seat, &child->node);
}
- container_notify_subtree_changed(cont);
return cont;
}
diff --git a/sway/tree/node.c b/sway/tree/node.c
new file mode 100644
index 00000000..74661c1a
--- /dev/null
+++ b/sway/tree/node.c
@@ -0,0 +1,151 @@
+#define _POSIX_C_SOURCE 200809L
+#include "sway/output.h"
+#include "sway/server.h"
+#include "sway/tree/container.h"
+#include "sway/tree/node.h"
+#include "sway/tree/root.h"
+#include "sway/tree/workspace.h"
+#include "log.h"
+
+void node_init(struct sway_node *node, enum sway_node_type type, void *thing) {
+ static size_t next_id = 1;
+ node->id = next_id++;
+ node->type = type;
+ node->sway_root = thing;
+ wl_signal_init(&node->events.destroy);
+}
+
+const char *node_type_to_str(enum sway_node_type type) {
+ switch (type) {
+ case N_ROOT:
+ return "N_ROOT";
+ case N_OUTPUT:
+ return "N_OUTPUT";
+ case N_WORKSPACE:
+ return "N_WORKSPACE";
+ case N_CONTAINER:
+ return "N_CONTAINER";
+ }
+ return "";
+}
+
+void node_set_dirty(struct sway_node *node) {
+ if (node->dirty) {
+ return;
+ }
+ node->dirty = true;
+ list_add(server.dirty_nodes, node);
+}
+
+bool node_is_view(struct sway_node *node) {
+ return node->type == N_CONTAINER && node->sway_container->view;
+}
+
+char *node_get_name(struct sway_node *node) {
+ switch (node->type) {
+ case N_ROOT:
+ return "root";
+ case N_OUTPUT:
+ return node->sway_output->wlr_output->name;
+ case N_WORKSPACE:
+ return node->sway_workspace->name;
+ case N_CONTAINER:
+ return node->sway_container->title;
+ }
+ return NULL;
+}
+
+void node_get_box(struct sway_node *node, struct wlr_box *box) {
+ switch (node->type) {
+ case N_ROOT:
+ root_get_box(root, box);
+ break;
+ case N_OUTPUT:
+ output_get_box(node->sway_output, box);
+ break;
+ case N_WORKSPACE:
+ workspace_get_box(node->sway_workspace, box);
+ break;
+ case N_CONTAINER:
+ container_get_box(node->sway_container, box);
+ break;
+ }
+}
+
+struct sway_output *node_get_output(struct sway_node *node) {
+ switch (node->type) {
+ case N_CONTAINER:
+ return node->sway_container->workspace->output;
+ case N_WORKSPACE:
+ return node->sway_workspace->output;
+ case N_OUTPUT:
+ return node->sway_output;
+ case N_ROOT:
+ return NULL;
+ }
+ return NULL;
+}
+
+enum sway_container_layout node_get_layout(struct sway_node *node) {
+ switch (node->type) {
+ case N_CONTAINER:
+ return node->sway_container->layout;
+ case N_WORKSPACE:
+ return node->sway_workspace->layout;
+ case N_OUTPUT:
+ case N_ROOT:
+ return L_NONE;
+ }
+ return L_NONE;
+}
+
+struct sway_node *node_get_parent(struct sway_node *node) {
+ switch (node->type) {
+ case N_CONTAINER: {
+ struct sway_container *con = node->sway_container;
+ if (con->parent) {
+ return &con->parent->node;
+ }
+ if (con->workspace) {
+ return &con->workspace->node;
+ }
+ }
+ return NULL;
+ case N_WORKSPACE: {
+ struct sway_workspace *ws = node->sway_workspace;
+ if (ws->output) {
+ return &ws->output->node;
+ }
+ }
+ return NULL;
+ case N_OUTPUT:
+ return &root->node;
+ case N_ROOT:
+ return NULL;
+ }
+ return NULL;
+}
+
+list_t *node_get_children(struct sway_node *node) {
+ switch (node->type) {
+ case N_CONTAINER:
+ return node->sway_container->children;
+ case N_WORKSPACE:
+ return node->sway_workspace->tiling;
+ case N_OUTPUT:
+ case N_ROOT:
+ return NULL;
+ }
+ return NULL;
+}
+
+bool node_has_ancestor(struct sway_node *node, struct sway_node *ancestor) {
+ struct sway_node *parent = node_get_parent(node);
+ while (parent) {
+ if (parent == ancestor) {
+ return true;
+ }
+ parent = node_get_parent(parent);
+ }
+ return false;
+}
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 6601220b..35589032 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -2,28 +2,31 @@
#include <ctype.h>
#include <string.h>
#include <strings.h>
+#include <wlr/types/wlr_output_damage.h>
#include "sway/ipc-server.h"
+#include "sway/layers.h"
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/output.h"
#include "sway/tree/workspace.h"
#include "log.h"
+#include "util.h"
-static void restore_workspaces(struct sway_container *output) {
+static void restore_workspaces(struct sway_output *output) {
// Workspace output priority
- for (int i = 0; i < root_container.children->length; i++) {
- struct sway_container *other = root_container.children->items[i];
+ for (int i = 0; i < root->outputs->length; i++) {
+ struct sway_output *other = root->outputs->items[i];
if (other == output) {
continue;
}
- for (int j = 0; j < other->children->length; j++) {
- struct sway_container *ws = other->children->items[j];
- struct sway_container *highest =
+ for (int j = 0; j < other->workspaces->length; j++) {
+ struct sway_workspace *ws = other->workspaces->items[j];
+ struct sway_output *highest =
workspace_output_get_highest_available(ws, NULL);
if (highest == output) {
- container_remove_child(ws);
- container_add_child(output, ws);
+ workspace_detach(ws);
+ output_add_workspace(output, ws);
ipc_event_workspace(NULL, ws, "move");
j--;
}
@@ -31,111 +34,116 @@ static void restore_workspaces(struct sway_container *output) {
}
// Saved workspaces
- list_t *saved = root_container.sway_root->saved_workspaces;
- for (int i = 0; i < saved->length; ++i) {
- struct sway_container *ws = saved->items[i];
- container_add_child(output, ws);
+ for (int i = 0; i < root->saved_workspaces->length; ++i) {
+ struct sway_workspace *ws = root->saved_workspaces->items[i];
+ output_add_workspace(output, ws);
ipc_event_workspace(NULL, ws, "move");
}
- saved->length = 0;
+ root->saved_workspaces->length = 0;
output_sort_workspaces(output);
}
-struct sway_container *output_create(
- struct sway_output *sway_output) {
- const char *name = sway_output->wlr_output->name;
- char identifier[128];
- output_get_identifier(identifier, sizeof(identifier), sway_output);
+struct sway_output *output_create(struct wlr_output *wlr_output) {
+ struct sway_output *output = calloc(1, sizeof(struct sway_output));
+ node_init(&output->node, N_OUTPUT, output);
+ output->wlr_output = wlr_output;
+ wlr_output->data = output;
- struct output_config *oc = NULL, *all = NULL;
- for (int i = 0; i < config->output_configs->length; ++i) {
- struct output_config *cur = config->output_configs->items[i];
+ wl_signal_add(&wlr_output->events.destroy, &output->destroy);
- if (strcasecmp(name, cur->name) == 0 ||
- strcasecmp(identifier, cur->name) == 0) {
- wlr_log(WLR_DEBUG, "Matched output config for %s", name);
- oc = cur;
- }
- if (strcasecmp("*", cur->name) == 0) {
- wlr_log(WLR_DEBUG, "Matched wildcard output config for %s", name);
- all = cur;
- }
+ wl_list_insert(&root->all_outputs, &output->link);
- if (oc && all) {
- break;
- }
- }
- if (!oc) {
- oc = all;
+ if (!wl_list_empty(&wlr_output->modes)) {
+ struct wlr_output_mode *mode =
+ wl_container_of(wlr_output->modes.prev, mode, link);
+ wlr_output_set_mode(wlr_output, mode);
}
- if (oc && !oc->enabled) {
- return NULL;
- }
+ output->workspaces = create_list();
+ output->current.workspaces = create_list();
- struct sway_container *output = container_create(C_OUTPUT);
- output->sway_output = sway_output;
- output->name = strdup(name);
- if (output->name == NULL) {
- output_begin_destroy(output);
- return NULL;
- }
+ return output;
+}
+void output_enable(struct sway_output *output, struct output_config *oc) {
+ if (!sway_assert(!output->enabled, "output is already enabled")) {
+ return;
+ }
+ struct wlr_output *wlr_output = output->wlr_output;
+ output->enabled = true;
apply_output_config(oc, output);
- container_add_child(&root_container, output);
- load_swaybars();
+ list_add(root->outputs, output);
- struct wlr_box size;
- wlr_output_effective_resolution(sway_output->wlr_output, &size.width,
- &size.height);
- output->width = size.width;
- output->height = size.height;
+ output->lx = wlr_output->lx;
+ output->ly = wlr_output->ly;
+ wlr_output_transformed_resolution(wlr_output,
+ &output->width, &output->height);
restore_workspaces(output);
- if (!output->children->length) {
+ if (!output->workspaces->length) {
// Create workspace
- char *ws_name = workspace_next_name(output->name);
+ char *ws_name = workspace_next_name(wlr_output->name);
wlr_log(WLR_DEBUG, "Creating default workspace %s", ws_name);
- struct sway_container *ws = workspace_create(output, ws_name);
+ struct sway_workspace *ws = workspace_create(output, ws_name);
// Set each seat's focus if not already set
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input_manager->seats, link) {
if (!seat->has_focus) {
- seat_set_focus(seat, ws);
+ seat_set_focus(seat, &ws->node);
}
}
free(ws_name);
}
- container_create_notify(output);
- return output;
+ size_t len = sizeof(output->layers) / sizeof(output->layers[0]);
+ for (size_t i = 0; i < len; ++i) {
+ wl_list_init(&output->layers[i]);
+ }
+ wl_signal_init(&output->events.destroy);
+
+ input_manager_configure_xcursor(input_manager);
+
+ wl_signal_add(&wlr_output->events.mode, &output->mode);
+ wl_signal_add(&wlr_output->events.transform, &output->transform);
+ wl_signal_add(&wlr_output->events.scale, &output->scale);
+ wl_signal_add(&output->damage->events.frame, &output->damage_frame);
+ wl_signal_add(&output->damage->events.destroy, &output->damage_destroy);
+
+ output_add_listeners(output);
+
+ wl_signal_emit(&root->events.new_node, &output->node);
+
+ load_swaybars();
+
+ arrange_layers(output);
+ arrange_root();
}
-static void output_evacuate(struct sway_container *output) {
- if (!output->children->length) {
+static void output_evacuate(struct sway_output *output) {
+ if (!output->workspaces->length) {
return;
}
- struct sway_container *fallback_output = NULL;
- if (root_container.children->length > 1) {
- fallback_output = root_container.children->items[0];
+ struct sway_output *fallback_output = NULL;
+ if (root->outputs->length > 1) {
+ fallback_output = root->outputs->items[0];
if (fallback_output == output) {
- fallback_output = root_container.children->items[1];
+ fallback_output = root->outputs->items[1];
}
}
- while (output->children->length) {
- struct sway_container *workspace = output->children->items[0];
+ while (output->workspaces->length) {
+ struct sway_workspace *workspace = output->workspaces->items[0];
- container_remove_child(workspace);
+ workspace_detach(workspace);
if (workspace_is_empty(workspace)) {
workspace_begin_destroy(workspace);
continue;
}
- struct sway_container *new_output =
+ struct sway_output *new_output =
workspace_output_get_highest_available(workspace, output);
if (!new_output) {
new_output = fallback_output;
@@ -143,39 +151,31 @@ static void output_evacuate(struct sway_container *output) {
if (new_output) {
workspace_output_add_priority(workspace, new_output);
- container_add_child(new_output, workspace);
+ output_add_workspace(new_output, workspace);
output_sort_workspaces(new_output);
ipc_event_workspace(NULL, workspace, "move");
} else {
- list_add(root_container.sway_root->saved_workspaces, workspace);
+ list_add(root->saved_workspaces, workspace);
}
}
}
-void output_destroy(struct sway_container *output) {
- if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
+void output_destroy(struct sway_output *output) {
+ if (!sway_assert(output->node.destroying,
+ "Tried to free output which wasn't marked as destroying")) {
return;
}
- if (!sway_assert(output->destroying,
- "Tried to free output which wasn't marked as destroying")) {
+ if (!sway_assert(output->wlr_output == NULL,
+ "Tried to free output which still had a wlr_output")) {
return;
}
- if (!sway_assert(output->ntxnrefs == 0, "Tried to free output "
+ if (!sway_assert(output->node.ntxnrefs == 0, "Tried to free output "
"which is still referenced by transactions")) {
return;
}
- free(output->name);
- free(output->formatted_title);
- wlr_texture_destroy(output->title_focused);
- wlr_texture_destroy(output->title_focused_inactive);
- wlr_texture_destroy(output->title_unfocused);
- wlr_texture_destroy(output->title_urgent);
- list_free(output->children);
- list_free(output->current.children);
- list_free(output->outputs);
+ list_free(output->workspaces);
+ list_free(output->current.workspaces);
free(output);
-
- // NOTE: We don't actually destroy the sway_output here
}
static void untrack_output(struct sway_container *con, void *data) {
@@ -186,76 +186,128 @@ static void untrack_output(struct sway_container *con, void *data) {
}
}
-void output_begin_destroy(struct sway_container *output) {
- if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
+void output_disable(struct sway_output *output) {
+ if (!sway_assert(output->enabled, "Expected an enabled output")) {
return;
}
- wlr_log(WLR_DEBUG, "OUTPUT: Destroying output '%s'", output->name);
+ wlr_log(WLR_DEBUG, "Disabling output '%s'", output->wlr_output->name);
wl_signal_emit(&output->events.destroy, output);
output_evacuate(output);
- output->destroying = true;
- container_set_dirty(output);
+ root_for_each_container(untrack_output, output);
+
+ int index = list_find(root->outputs, output);
+ list_del(root->outputs, index);
+
+ wl_list_remove(&output->mode.link);
+ wl_list_remove(&output->transform.link);
+ wl_list_remove(&output->scale.link);
+ wl_list_remove(&output->damage_destroy.link);
+ wl_list_remove(&output->damage_frame.link);
+
+ output->enabled = false;
+
+ arrange_root();
+}
+
+void output_begin_destroy(struct sway_output *output) {
+ if (!sway_assert(!output->enabled, "Expected a disabled output")) {
+ return;
+ }
+ wlr_log(WLR_DEBUG, "Destroying output '%s'", output->wlr_output->name);
+
+ output->node.destroying = true;
+ node_set_dirty(&output->node);
+
+ wl_list_remove(&output->link);
+ wl_list_remove(&output->destroy.link);
+ output->wlr_output->data = NULL;
+ output->wlr_output = NULL;
+}
- root_for_each_container(untrack_output, output->sway_output);
+struct output_config *output_find_config(struct sway_output *output) {
+ const char *name = output->wlr_output->name;
+ char identifier[128];
+ output_get_identifier(identifier, sizeof(identifier), output);
- wl_list_remove(&output->sway_output->mode.link);
- wl_list_remove(&output->sway_output->transform.link);
- wl_list_remove(&output->sway_output->scale.link);
- wl_list_remove(&output->sway_output->damage_destroy.link);
- wl_list_remove(&output->sway_output->damage_frame.link);
+ struct output_config *oc = NULL, *all = NULL;
+ for (int i = 0; i < config->output_configs->length; ++i) {
+ struct output_config *cur = config->output_configs->items[i];
- output->sway_output->swayc = NULL;
- output->sway_output = NULL;
+ if (strcasecmp(name, cur->name) == 0 ||
+ strcasecmp(identifier, cur->name) == 0) {
+ wlr_log(WLR_DEBUG, "Matched output config for %s", name);
+ oc = cur;
+ }
+ if (strcasecmp("*", cur->name) == 0) {
+ wlr_log(WLR_DEBUG, "Matched wildcard output config for %s", name);
+ all = cur;
+ }
- if (output->parent) {
- container_remove_child(output);
+ if (oc && all) {
+ break;
+ }
+ }
+ if (!oc) {
+ oc = all;
}
+
+ return oc;
}
-struct sway_container *output_from_wlr_output(struct wlr_output *output) {
- if (output == NULL) {
+struct sway_output *output_from_wlr_output(struct wlr_output *output) {
+ return output->data;
+}
+
+struct sway_output *output_get_in_direction(struct sway_output *reference,
+ enum movement_direction direction) {
+ enum wlr_direction wlr_dir = 0;
+ if (!sway_assert(sway_dir_to_wlr(direction, &wlr_dir),
+ "got invalid direction: %d", direction)) {
return NULL;
}
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *o = root_container.children->items[i];
- if (o->type == C_OUTPUT && o->sway_output->wlr_output == output) {
- return o;
- }
+ int lx = reference->wlr_output->lx + reference->width / 2;
+ int ly = reference->wlr_output->ly + reference->height / 2;
+ struct wlr_output *wlr_adjacent = wlr_output_layout_adjacent_output(
+ root->output_layout, wlr_dir, reference->wlr_output, lx, ly);
+ if (!wlr_adjacent) {
+ return NULL;
}
- return NULL;
+ return output_from_wlr_output(wlr_adjacent);
}
-void output_for_each_workspace(struct sway_container *output,
- void (*f)(struct sway_container *con, void *data), void *data) {
- if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
- return;
+void output_add_workspace(struct sway_output *output,
+ struct sway_workspace *workspace) {
+ if (workspace->output) {
+ workspace_detach(workspace);
}
- for (int i = 0; i < output->children->length; ++i) {
- struct sway_container *workspace = output->children->items[i];
+ list_add(output->workspaces, workspace);
+ workspace->output = output;
+ node_set_dirty(&output->node);
+ node_set_dirty(&workspace->node);
+}
+
+void output_for_each_workspace(struct sway_output *output,
+ void (*f)(struct sway_workspace *ws, void *data), void *data) {
+ for (int i = 0; i < output->workspaces->length; ++i) {
+ struct sway_workspace *workspace = output->workspaces->items[i];
f(workspace, data);
}
}
-void output_for_each_container(struct sway_container *output,
+void output_for_each_container(struct sway_output *output,
void (*f)(struct sway_container *con, void *data), void *data) {
- if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
- return;
- }
- for (int i = 0; i < output->children->length; ++i) {
- struct sway_container *workspace = output->children->items[i];
+ for (int i = 0; i < output->workspaces->length; ++i) {
+ struct sway_workspace *workspace = output->workspaces->items[i];
workspace_for_each_container(workspace, f, data);
}
}
-struct sway_container *output_find_workspace(struct sway_container *output,
- bool (*test)(struct sway_container *con, void *data), void *data) {
- if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
- return NULL;
- }
- for (int i = 0; i < output->children->length; ++i) {
- struct sway_container *workspace = output->children->items[i];
+struct sway_workspace *output_find_workspace(struct sway_output *output,
+ bool (*test)(struct sway_workspace *ws, void *data), void *data) {
+ for (int i = 0; i < output->workspaces->length; ++i) {
+ struct sway_workspace *workspace = output->workspaces->items[i];
if (test(workspace, data)) {
return workspace;
}
@@ -263,14 +315,11 @@ struct sway_container *output_find_workspace(struct sway_container *output,
return NULL;
}
-struct sway_container *output_find_container(struct sway_container *output,
+struct sway_container *output_find_container(struct sway_output *output,
bool (*test)(struct sway_container *con, void *data), void *data) {
- if (!sway_assert(output->type == C_OUTPUT, "Expected an output")) {
- return NULL;
- }
struct sway_container *result = NULL;
- for (int i = 0; i < output->children->length; ++i) {
- struct sway_container *workspace = output->children->items[i];
+ for (int i = 0; i < output->workspaces->length; ++i) {
+ struct sway_workspace *workspace = output->workspaces->items[i];
if ((result = workspace_find_container(workspace, test, data))) {
return result;
}
@@ -279,8 +328,8 @@ struct sway_container *output_find_container(struct sway_container *output,
}
static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
- struct sway_container *a = *(void **)_a;
- struct sway_container *b = *(void **)_b;
+ struct sway_workspace *a = *(void **)_a;
+ struct sway_workspace *b = *(void **)_b;
if (isdigit(a->name[0]) && isdigit(b->name[0])) {
int a_num = strtol(a->name, NULL, 10);
@@ -294,6 +343,27 @@ static int sort_workspace_cmp_qsort(const void *_a, const void *_b) {
return 0;
}
-void output_sort_workspaces(struct sway_container *output) {
- list_stable_sort(output->children, sort_workspace_cmp_qsort);
+void output_sort_workspaces(struct sway_output *output) {
+ list_stable_sort(output->workspaces, sort_workspace_cmp_qsort);
+}
+
+void output_get_box(struct sway_output *output, struct wlr_box *box) {
+ box->x = output->lx;
+ box->y = output->ly;
+ box->width = output->width;
+ box->height = output->height;
+}
+
+enum sway_container_layout output_get_default_layout(
+ struct sway_output *output) {
+ if (config->default_layout != L_NONE) {
+ return config->default_layout;
+ }
+ if (config->default_orientation != L_NONE) {
+ return config->default_orientation;
+ }
+ if (output->height > output->width) {
+ return L_VERT;
+ }
+ return L_HORIZ;
}
diff --git a/sway/tree/root.c b/sway/tree/root.c
index b42371de..ecc04ddb 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -14,54 +14,45 @@
#include "log.h"
#include "util.h"
-struct sway_container root_container;
+struct sway_root *root;
static void output_layout_handle_change(struct wl_listener *listener,
void *data) {
- arrange_windows(&root_container);
+ arrange_root();
transaction_commit_dirty();
}
-void root_create(void) {
- root_container.id = 0; // normally assigned in new_swayc()
- root_container.type = C_ROOT;
- root_container.layout = L_NONE;
- root_container.name = strdup("root");
- root_container.children = create_list();
- root_container.current.children = create_list();
- wl_signal_init(&root_container.events.destroy);
-
- root_container.sway_root = calloc(1, sizeof(*root_container.sway_root));
- root_container.sway_root->output_layout = wlr_output_layout_create();
- wl_list_init(&root_container.sway_root->all_outputs);
+struct sway_root *root_create(void) {
+ struct sway_root *root = calloc(1, sizeof(struct sway_root));
+ if (!root) {
+ wlr_log(WLR_ERROR, "Unable to allocate sway_root");
+ return NULL;
+ }
+ node_init(&root->node, N_ROOT, root);
+ root->output_layout = wlr_output_layout_create();
+ wl_list_init(&root->all_outputs);
#ifdef HAVE_XWAYLAND
- wl_list_init(&root_container.sway_root->xwayland_unmanaged);
+ wl_list_init(&root->xwayland_unmanaged);
#endif
- wl_list_init(&root_container.sway_root->drag_icons);
- wl_signal_init(&root_container.sway_root->events.new_container);
- root_container.sway_root->scratchpad = create_list();
- root_container.sway_root->saved_workspaces = create_list();
-
- root_container.sway_root->output_layout_change.notify =
- output_layout_handle_change;
- wl_signal_add(&root_container.sway_root->output_layout->events.change,
- &root_container.sway_root->output_layout_change);
+ wl_list_init(&root->drag_icons);
+ wl_signal_init(&root->events.new_node);
+ root->outputs = create_list();
+ root->scratchpad = create_list();
+ root->saved_workspaces = create_list();
+
+ root->output_layout_change.notify = output_layout_handle_change;
+ wl_signal_add(&root->output_layout->events.change,
+ &root->output_layout_change);
+ return root;
}
-void root_destroy(void) {
- // sway_root
- wl_list_remove(&root_container.sway_root->output_layout_change.link);
- list_free(root_container.sway_root->scratchpad);
- list_free(root_container.sway_root->saved_workspaces);
- wlr_output_layout_destroy(root_container.sway_root->output_layout);
- free(root_container.sway_root);
-
- // root_container
- list_free(root_container.children);
- list_free(root_container.current.children);
- free(root_container.name);
-
- memset(&root_container, 0, sizeof(root_container));
+void root_destroy(struct sway_root *root) {
+ wl_list_remove(&root->output_layout_change.link);
+ list_free(root->scratchpad);
+ list_free(root->saved_workspaces);
+ list_free(root->outputs);
+ wlr_output_layout_destroy(root->output_layout);
+ free(root);
}
void root_scratchpad_add_container(struct sway_container *con) {
@@ -69,15 +60,21 @@ void root_scratchpad_add_container(struct sway_container *con) {
return;
}
con->scratchpad = true;
- list_add(root_container.sway_root->scratchpad, con);
+ list_add(root->scratchpad, con);
struct sway_container *parent = con->parent;
+ struct sway_workspace *workspace = con->workspace;
container_set_floating(con, true);
- container_remove_child(con);
- arrange_windows(parent);
+ container_detach(con);
struct sway_seat *seat = input_manager_current_seat(input_manager);
- seat_set_focus(seat, seat_get_focus_inactive(seat, parent));
+ if (parent) {
+ arrange_container(parent);
+ seat_set_focus(seat, seat_get_focus_inactive(seat, &parent->node));
+ } else {
+ arrange_workspace(workspace);
+ seat_set_focus(seat, seat_get_focus_inactive(seat, &workspace->node));
+ }
}
void root_scratchpad_remove_container(struct sway_container *con) {
@@ -85,28 +82,25 @@ void root_scratchpad_remove_container(struct sway_container *con) {
return;
}
con->scratchpad = false;
- int index = list_find(root_container.sway_root->scratchpad, con);
+ int index = list_find(root->scratchpad, con);
if (index != -1) {
- list_del(root_container.sway_root->scratchpad, index);
+ list_del(root->scratchpad, index);
}
}
void root_scratchpad_show(struct sway_container *con) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *ws = seat_get_focus(seat);
- if (ws->type != C_WORKSPACE) {
- ws = container_parent(ws, C_WORKSPACE);
- }
+ struct sway_workspace *ws = seat_get_focused_workspace(seat);
// If the current con or any of its parents are in fullscreen mode, we
// first need to disable it before showing the scratchpad con.
- if (ws->sway_workspace->fullscreen) {
- container_set_fullscreen(ws->sway_workspace->fullscreen, false);
+ if (ws->fullscreen) {
+ container_set_fullscreen(ws->fullscreen, false);
}
// Show the container
- if (con->parent) {
- container_remove_child(con);
+ if (con->workspace) {
+ container_detach(con);
}
workspace_add_floating(ws, con);
@@ -115,7 +109,7 @@ void root_scratchpad_show(struct sway_container *con) {
double center_ly = con->y + con->height / 2;
struct wlr_box workspace_box;
- container_get_box(ws, &workspace_box);
+ workspace_get_box(ws, &workspace_box);
if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) {
// Maybe resize it
if (con->width > ws->width || con->height > ws->height) {
@@ -128,23 +122,21 @@ void root_scratchpad_show(struct sway_container *con) {
container_floating_move_to(con, new_lx, new_ly);
}
- arrange_windows(ws);
- seat_set_focus(seat, seat_get_focus_inactive(seat, con));
-
- container_set_dirty(con->parent);
+ arrange_workspace(ws);
+ seat_set_focus(seat, seat_get_focus_inactive(seat, &con->node));
}
void root_scratchpad_hide(struct sway_container *con) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = seat_get_focus(seat);
- struct sway_container *ws = container_parent(con, C_WORKSPACE);
+ struct sway_node *focus = seat_get_focus(seat);
+ struct sway_workspace *ws = con->workspace;
- container_remove_child(con);
- arrange_windows(ws);
- if (con == focus) {
- seat_set_focus(seat, seat_get_focus_inactive(seat, ws));
+ container_detach(con);
+ arrange_workspace(ws);
+ if (&con->node == focus) {
+ seat_set_focus(seat, seat_get_focus_inactive(seat, &ws->node));
}
- list_move_to_end(root_container.sway_root->scratchpad, con);
+ list_move_to_end(root->scratchpad, con);
}
struct pid_workspace {
@@ -152,7 +144,7 @@ struct pid_workspace {
char *workspace;
struct timespec time_added;
- struct sway_container *output;
+ struct sway_output *output;
struct wl_listener output_destroy;
struct wl_list link;
@@ -160,13 +152,13 @@ struct pid_workspace {
static struct wl_list pid_workspaces;
-struct sway_container *root_workspace_for_pid(pid_t pid) {
+struct sway_workspace *root_workspace_for_pid(pid_t pid) {
if (!pid_workspaces.prev && !pid_workspaces.next) {
wl_list_init(&pid_workspaces);
return NULL;
}
- struct sway_container *ws = NULL;
+ struct sway_workspace *ws = NULL;
struct pid_workspace *pw = NULL;
wlr_log(WLR_DEBUG, "Looking up workspace for pid %d", pid);
@@ -219,16 +211,12 @@ void root_record_workspace_pid(pid_t pid) {
}
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *ws =
- seat_get_focus_inactive(seat, &root_container);
- if (ws && ws->type != C_WORKSPACE) {
- ws = container_parent(ws, C_WORKSPACE);
- }
+ struct sway_workspace *ws = seat_get_focused_workspace(seat);
if (!ws) {
wlr_log(WLR_DEBUG, "Bailing out, no workspace");
return;
}
- struct sway_container *output = ws->parent;
+ struct sway_output *output = ws->output;
if (!output) {
wlr_log(WLR_DEBUG, "Bailing out, no output");
return;
@@ -255,30 +243,28 @@ void root_record_workspace_pid(pid_t pid) {
pw->pid = pid;
memcpy(&pw->time_added, &now, sizeof(struct timespec));
pw->output_destroy.notify = pw_handle_output_destroy;
- wl_signal_add(&output->sway_output->wlr_output->events.destroy,
- &pw->output_destroy);
+ wl_signal_add(&output->wlr_output->events.destroy, &pw->output_destroy);
wl_list_insert(&pid_workspaces, &pw->link);
}
-void root_for_each_workspace(void (*f)(struct sway_container *con, void *data),
+void root_for_each_workspace(void (*f)(struct sway_workspace *ws, void *data),
void *data) {
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
output_for_each_workspace(output, f, data);
}
}
void root_for_each_container(void (*f)(struct sway_container *con, void *data),
void *data) {
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
output_for_each_container(output, f, data);
}
// Scratchpad
- for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) {
- struct sway_container *container =
- root_container.sway_root->scratchpad->items[i];
+ for (int i = 0; i < root->scratchpad->length; ++i) {
+ struct sway_container *container = root->scratchpad->items[i];
// If the container has a parent then it's visible on a workspace
// and will have been iterated in the previous for loop. So we only
// iterate the hidden scratchpad containers here.
@@ -289,10 +275,10 @@ void root_for_each_container(void (*f)(struct sway_container *con, void *data),
}
}
-struct sway_container *root_find_output(
- bool (*test)(struct sway_container *con, void *data), void *data) {
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
+struct sway_output *root_find_output(
+ bool (*test)(struct sway_output *output, void *data), void *data) {
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
if (test(output, data)) {
return output;
}
@@ -300,11 +286,11 @@ struct sway_container *root_find_output(
return NULL;
}
-struct sway_container *root_find_workspace(
- bool (*test)(struct sway_container *con, void *data), void *data) {
- struct sway_container *result = NULL;
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
+struct sway_workspace *root_find_workspace(
+ bool (*test)(struct sway_workspace *ws, void *data), void *data) {
+ struct sway_workspace *result = NULL;
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
if ((result = output_find_workspace(output, test, data))) {
return result;
}
@@ -315,17 +301,16 @@ struct sway_container *root_find_workspace(
struct sway_container *root_find_container(
bool (*test)(struct sway_container *con, void *data), void *data) {
struct sway_container *result = NULL;
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *output = root_container.children->items[i];
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
if ((result = output_find_container(output, test, data))) {
return result;
}
}
// Scratchpad
- for (int i = 0; i < root_container.sway_root->scratchpad->length; ++i) {
- struct sway_container *container =
- root_container.sway_root->scratchpad->items[i];
+ for (int i = 0; i < root->scratchpad->length; ++i) {
+ struct sway_container *container = root->scratchpad->items[i];
if (!container->parent) {
if (test(container, data)) {
return container;
@@ -337,3 +322,10 @@ struct sway_container *root_find_container(
}
return NULL;
}
+
+void root_get_box(struct sway_root *root, struct wlr_box *box) {
+ box->x = root->x;
+ box->y = root->y;
+ box->width = root->width;
+ box->height = root->height;
+}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 6bd0ef67..f63a35b5 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -33,6 +33,8 @@ void view_init(struct sway_view *view, enum sway_view_type type,
view->marks = create_list();
view->allow_request_urgent = true;
wl_signal_init(&view->events.unmap);
+
+ view->container = container_create(view);
}
void view_destroy(struct sway_view *view) {
@@ -43,8 +45,8 @@ void view_destroy(struct sway_view *view) {
"Tried to free view which wasn't marked as destroying")) {
return;
}
- if (!sway_assert(view->swayc == NULL,
- "Tried to free view which still has a swayc "
+ if (!sway_assert(view->container == NULL,
+ "Tried to free view which still has a container "
"(might have a pending transaction?)")) {
return;
}
@@ -57,6 +59,7 @@ void view_destroy(struct sway_view *view) {
wlr_texture_destroy(view->marks_focused_inactive);
wlr_texture_destroy(view->marks_unfocused);
wlr_texture_destroy(view->marks_urgent);
+ free(view->title_format);
if (view->impl->destroy) {
view->impl->destroy(view);
@@ -65,23 +68,13 @@ void view_destroy(struct sway_view *view) {
}
}
-/**
- * The view may or may not be involved in a transaction. For example, a view may
- * unmap then attempt to destroy itself before we've applied the new layout. If
- * an unmapping view is still involved in a transaction then it'll still have a
- * swayc.
- *
- * If there's no transaction we can simply free the view. Otherwise the
- * destroying flag will make the view get freed when the transaction is
- * finished.
- */
void view_begin_destroy(struct sway_view *view) {
if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) {
return;
}
view->destroying = true;
- if (!view->swayc) {
+ if (!view->container) {
view_destroy(view);
}
}
@@ -171,30 +164,31 @@ uint32_t view_configure(struct sway_view *view, double lx, double ly, int width,
}
void view_autoconfigure(struct sway_view *view) {
- if (!sway_assert(view->swayc,
- "Called view_autoconfigure() on a view without a swayc")) {
+ if (!view->container->workspace) {
+ // Hidden in the scratchpad
return;
}
+ struct sway_output *output = view->container->workspace->output;
- struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
-
- if (view->swayc->is_fullscreen) {
- view->x = output->x;
- view->y = output->y;
+ if (view->container->is_fullscreen) {
+ view->x = output->lx;
+ view->y = output->ly;
view->width = output->width;
view->height = output->height;
return;
}
- struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
+ struct sway_workspace *ws = view->container->workspace;
- int other_views = 0;
+ bool other_views = false;
if (config->hide_edge_borders == E_SMART) {
- struct sway_container *con = view->swayc;
- while (con != output) {
- if (con->layout != L_TABBED && con->layout != L_STACKED) {
- other_views += con->children ? con->children->length - 1 : 0;
- if (other_views > 0) {
+ struct sway_container *con = view->container;
+ while (con) {
+ enum sway_container_layout layout = container_parent_layout(con);
+ if (layout != L_TABBED && layout != L_STACKED) {
+ list_t *siblings = container_get_siblings(con);
+ if (siblings && siblings->length > 1) {
+ other_views = true;
break;
}
}
@@ -202,7 +196,7 @@ void view_autoconfigure(struct sway_view *view) {
}
}
- struct sway_container *con = view->swayc;
+ struct sway_container *con = view->container;
view->border_top = view->border_bottom = true;
view->border_left = view->border_right = true;
@@ -228,7 +222,8 @@ void view_autoconfigure(struct sway_view *view) {
// In a tabbed or stacked container, the swayc's y is the bottom of the
// title area. We have to disable any top border because the title bar is
// rendered by the parent.
- if (con->parent->layout == L_TABBED || con->parent->layout == L_STACKED) {
+ enum sway_container_layout layout = container_parent_layout(con);
+ if (layout == L_TABBED || layout == L_STACKED) {
view->border_top = false;
} else {
y_offset = container_titlebar_height();
@@ -281,13 +276,16 @@ void view_set_activated(struct sway_view *view, bool activated) {
}
void view_request_activate(struct sway_view *view) {
- struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
+ struct sway_workspace *ws = view->container->workspace;
+ if (!ws) { // hidden scratchpad container
+ return;
+ }
struct sway_seat *seat = input_manager_current_seat(input_manager);
switch (config->focus_on_window_activation) {
case FOWA_SMART:
if (workspace_is_visible(ws)) {
- seat_set_focus(seat, view->swayc);
+ seat_set_focus(seat, &view->container->node);
} else {
view_set_urgent(view, true);
}
@@ -296,7 +294,7 @@ void view_request_activate(struct sway_view *view) {
view_set_urgent(view, true);
break;
case FOWA_FOCUS:
- seat_set_focus(seat, view->swayc);
+ seat_set_focus(seat, &view->container->node);
break;
case FOWA_NONE:
break;
@@ -331,23 +329,12 @@ void view_close_popups(struct sway_view *view) {
}
void view_damage_from(struct sway_view *view) {
- for (int i = 0; i < root_container.children->length; ++i) {
- struct sway_container *cont = root_container.children->items[i];
- if (cont->type == C_OUTPUT) {
- output_damage_from_view(cont->sway_output, view);
- }
+ for (int i = 0; i < root->outputs->length; ++i) {
+ struct sway_output *output = root->outputs->items[i];
+ output_damage_from_view(output, view);
}
}
-static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) {
- struct sway_container *output = container_parent(view->swayc, C_OUTPUT);
-
- box->x = output->x + view->swayc->x;
- box->y = output->y + view->swayc->y;
- box->width = view->width;
- box->height = view->height;
-}
-
void view_for_each_surface(struct sway_view *view,
wlr_surface_iterator_func_t iterator, void *user_data) {
if (!view->surface) {
@@ -396,11 +383,8 @@ static bool view_has_executed_criteria(struct sway_view *view,
}
void view_execute_criteria(struct sway_view *view) {
- if (!view->swayc) {
- return;
- }
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *prior_focus = seat_get_focus(seat);
+ struct sway_node *prior_focus = seat_get_focus(seat);
list_t *criterias = criteria_for_view(view, CT_COMMAND);
for (int i = 0; i < criterias->length; i++) {
struct criteria *criteria = criterias->items[i];
@@ -411,7 +395,7 @@ void view_execute_criteria(struct sway_view *view) {
}
wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
criteria->raw, view, criteria->cmdlist);
- seat_set_focus(seat, view->swayc);
+ seat_set_focus(seat, &view->container->node);
list_add(view->executed_criteria, criteria);
struct cmd_results *res = execute_command(criteria->cmdlist, NULL);
if (res->status != CMD_SUCCESS) {
@@ -423,19 +407,19 @@ void view_execute_criteria(struct sway_view *view) {
seat_set_focus(seat, prior_focus);
}
-static struct sway_container *select_workspace(struct sway_view *view) {
+static struct sway_workspace *select_workspace(struct sway_view *view) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
// Check if there's any `assign` criteria for the view
list_t *criterias = criteria_for_view(view,
CT_ASSIGN_WORKSPACE | CT_ASSIGN_WORKSPACE_NUMBER | CT_ASSIGN_OUTPUT);
- struct sway_container *ws = NULL;
+ struct sway_workspace *ws = NULL;
for (int i = 0; i < criterias->length; ++i) {
struct criteria *criteria = criterias->items[i];
if (criteria->type == CT_ASSIGN_OUTPUT) {
- struct sway_container *output = output_by_name(criteria->target);
+ struct sway_output *output = output_by_name(criteria->target);
if (output) {
- ws = seat_get_active_child(seat, output);
+ ws = output_get_active_workspace(output);
break;
}
} else {
@@ -484,20 +468,14 @@ static struct sway_container *select_workspace(struct sway_view *view) {
}
// Use the focused workspace
- ws = seat_get_focus_inactive(seat, &root_container);
- if (ws->type != C_WORKSPACE) {
- ws = container_parent(ws, C_WORKSPACE);
- }
- return ws;
+ return seat_get_focused_workspace(seat);
}
static bool should_focus(struct sway_view *view) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *prev_focus =
- seat_get_focus_inactive(seat, &root_container);
- struct sway_container *prev_ws = prev_focus->type == C_WORKSPACE ?
- prev_focus : container_parent(prev_focus, C_WORKSPACE);
- struct sway_container *map_ws = container_parent(view->swayc, C_WORKSPACE);
+ struct sway_container *prev_con = seat_get_focused_container(seat);
+ struct sway_workspace *prev_ws = seat_get_focused_workspace(seat);
+ struct sway_workspace *map_ws = view->container->workspace;
// Views can only take focus if they are mapped into the active workspace
if (prev_ws != map_ws) {
@@ -506,10 +484,9 @@ static bool should_focus(struct sway_view *view) {
// If the view is the only one in the focused workspace, it'll get focus
// regardless of any no_focus criteria.
- struct sway_container *parent = view->swayc->parent;
- if (parent->type == C_WORKSPACE && prev_focus == parent) {
- size_t num_children = parent->children->length +
- parent->sway_workspace->floating->length;
+ if (!view->container->parent && !prev_con) {
+ size_t num_children = view->container->workspace->tiling->length +
+ view->container->workspace->floating->length;
if (num_children == 1) {
return true;
}
@@ -529,16 +506,24 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
view->surface = wlr_surface;
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *ws = select_workspace(view);
- struct sway_container *target_sibling = seat_get_focus_inactive(seat, ws);
+ struct sway_workspace *ws = select_workspace(view);
+ struct sway_node *node = seat_get_focus_inactive(seat, &ws->node);
+ struct sway_container *target_sibling = node->type == N_CONTAINER ?
+ node->sway_container : NULL;
// If we're about to launch the view into the floating container, then
// launch it as a tiled view in the root of the workspace instead.
- if (container_is_floating(target_sibling)) {
- target_sibling = target_sibling->parent;
+ if (target_sibling && container_is_floating(target_sibling)) {
+ target_sibling = NULL;
}
- view->swayc = container_view_create(target_sibling, view);
+ view->container = container_create(view);
+ if (target_sibling) {
+ container_add_sibling(target_sibling, view->container);
+ } else {
+ workspace_add_tiling(ws, view->container);
+ }
+ ipc_event_window(view->container, "new");
view_init_subsurfaces(view, wlr_surface);
wl_signal_add(&wlr_surface->events.new_subsurface,
@@ -548,7 +533,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
if (view->impl->wants_floating && view->impl->wants_floating(view)) {
view->border = config->floating_border;
view->border_thickness = config->floating_border_thickness;
- container_set_floating(view->swayc, true);
+ container_set_floating(view->container, true);
} else {
view->border = config->border;
view->border_thickness = config->border_thickness;
@@ -556,11 +541,11 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
}
if (should_focus(view)) {
- input_manager_set_focus(input_manager, view->swayc);
+ input_manager_set_focus(input_manager, &view->container->node);
}
view_update_title(view, false);
- container_notify_subtree_changed(view->swayc->parent);
+ container_update_representation(view->container);
view_execute_criteria(view);
}
@@ -574,17 +559,17 @@ void view_unmap(struct sway_view *view) {
view->urgent_timer = NULL;
}
- bool was_fullscreen = view->swayc->is_fullscreen;
- struct sway_container *parent = view->swayc->parent;
- container_begin_destroy(view->swayc);
- struct sway_container *surviving_ancestor = container_reap_empty(parent);
+ struct sway_container *parent = view->container->parent;
+ struct sway_workspace *ws = view->container->workspace;
+ container_begin_destroy(view->container);
+ if (parent) {
+ container_reap_empty(parent);
+ } else if (ws) {
+ workspace_consider_destroy(ws);
+ }
- // If the workspace wasn't reaped
- if (surviving_ancestor && surviving_ancestor->type >= C_WORKSPACE) {
- struct sway_container *ws = surviving_ancestor->type == C_WORKSPACE ?
- surviving_ancestor :
- container_parent(surviving_ancestor, C_WORKSPACE);
- arrange_windows(was_fullscreen ? ws : surviving_ancestor);
+ if (ws && !ws->node.destroying) {
+ arrange_workspace(ws);
workspace_detect_urgent(ws);
}
@@ -593,15 +578,15 @@ void view_unmap(struct sway_view *view) {
}
void view_update_size(struct sway_view *view, int width, int height) {
- if (!sway_assert(container_is_floating(view->swayc),
+ if (!sway_assert(container_is_floating(view->container),
"Expected a floating container")) {
return;
}
view->width = width;
view->height = height;
- view->swayc->current.view_width = width;
- view->swayc->current.view_height = height;
- container_set_geometry_from_floating_view(view->swayc);
+ view->container->current.view_width = width;
+ view->container->current.view_height = height;
+ container_set_geometry_from_floating_view(view->container);
}
static void view_subsurface_create(struct sway_view *view,
@@ -670,27 +655,18 @@ void view_child_init(struct sway_view_child *child,
wl_signal_add(&view->events.unmap, &child->view_unmap);
child->view_unmap.notify = view_child_handle_view_unmap;
- struct sway_container *output = child->view->swayc->parent;
- if (output != NULL) {
- if (output->type != C_OUTPUT) {
- output = container_parent(output, C_OUTPUT);
- }
- wlr_surface_send_enter(child->surface, output->sway_output->wlr_output);
- }
+ struct sway_output *output = child->view->container->workspace->output;
+ wlr_surface_send_enter(child->surface, output->wlr_output);
view_init_subsurfaces(child->view, surface);
// TODO: only damage the whole child
- if (child->view->swayc) {
- container_damage_whole(child->view->swayc);
- }
+ container_damage_whole(child->view->container);
}
void view_child_destroy(struct sway_view_child *child) {
// TODO: only damage the whole child
- if (child->view->swayc) {
- container_damage_whole(child->view->swayc);
- }
+ container_damage_whole(child->view->container);
wl_list_remove(&child->surface_commit.link);
wl_list_remove(&child->surface_destroy.link);
@@ -808,22 +784,20 @@ static char *escape_title(char *buffer) {
}
void view_update_title(struct sway_view *view, bool force) {
- if (!view->swayc) {
- return;
- }
const char *title = view_get_title(view);
if (!force) {
- if (title && view->swayc->name && strcmp(title, view->swayc->name) == 0) {
+ if (title && view->container->title &&
+ strcmp(title, view->container->title) == 0) {
return;
}
- if (!title && !view->swayc->name) {
+ if (!title && !view->container->title) {
return;
}
}
- free(view->swayc->name);
- free(view->swayc->formatted_title);
+ free(view->container->title);
+ free(view->container->formatted_title);
if (title) {
size_t len = parse_title_format(view, NULL);
char *buffer = calloc(len + 1, sizeof(char));
@@ -836,25 +810,25 @@ void view_update_title(struct sway_view *view, bool force) {
buffer = escape_title(buffer);
}
- view->swayc->name = strdup(title);
- view->swayc->formatted_title = buffer;
+ view->container->title = strdup(title);
+ view->container->formatted_title = buffer;
} else {
- view->swayc->name = NULL;
- view->swayc->formatted_title = NULL;
+ view->container->title = NULL;
+ view->container->formatted_title = NULL;
}
- container_calculate_title_height(view->swayc);
+ container_calculate_title_height(view->container);
config_update_font_height(false);
// Update title after the global font height is updated
- container_update_title_textures(view->swayc);
+ container_update_title_textures(view->container);
- ipc_event_window(view->swayc, "title");
+ ipc_event_window(view->container, "title");
}
static bool find_by_mark_iterator(struct sway_container *con,
void *data) {
char *mark = data;
- return con->type == C_VIEW && view_has_mark(con->sway_view, mark);
+ return con->view && view_has_mark(con->view, mark);
}
struct sway_view *view_find_mark(char *mark) {
@@ -863,7 +837,7 @@ struct sway_view *view_find_mark(char *mark) {
if (!container) {
return NULL;
}
- return container->sway_view;
+ return container->view;
}
bool view_find_and_unmark(char *mark) {
@@ -872,7 +846,7 @@ bool view_find_and_unmark(char *mark) {
if (!container) {
return false;
}
- struct sway_view *view = container->sway_view;
+ struct sway_view *view = container->view;
for (int i = 0; i < view->marks->length; ++i) {
char *view_mark = view->marks->items[i];
@@ -888,10 +862,9 @@ bool view_find_and_unmark(char *mark) {
}
void view_clear_marks(struct sway_view *view) {
- while (view->marks->length) {
- list_del(view->marks, 0);
- ipc_event_window(view->swayc, "mark");
- }
+ list_foreach(view->marks, free);
+ view->marks->length = 0;
+ ipc_event_window(view->container, "mark");
}
bool view_has_mark(struct sway_view *view, char *mark) {
@@ -906,12 +879,13 @@ bool view_has_mark(struct sway_view *view, char *mark) {
void view_add_mark(struct sway_view *view, char *mark) {
list_add(view->marks, strdup(mark));
- ipc_event_window(view->swayc, "mark");
+ ipc_event_window(view->container, "mark");
}
static void update_marks_texture(struct sway_view *view,
struct wlr_texture **texture, struct border_colors *class) {
- struct sway_output *output = container_get_effective_output(view->swayc);
+ struct sway_output *output =
+ container_get_effective_output(view->container);
if (!output) {
return;
}
@@ -949,7 +923,7 @@ static void update_marks_texture(struct sway_view *view,
double scale = output->wlr_output->scale;
int width = 0;
- int height = view->swayc->title_height * scale;
+ int height = view->container->title_height * scale;
cairo_t *c = cairo_create(NULL);
get_text_size(c, config->font, &width, NULL, scale, false, "%s", buffer);
@@ -994,44 +968,40 @@ void view_update_marks_textures(struct sway_view *view) {
&config->border_colors.unfocused);
update_marks_texture(view, &view->marks_urgent,
&config->border_colors.urgent);
- container_damage_whole(view->swayc);
+ container_damage_whole(view->container);
}
bool view_is_visible(struct sway_view *view) {
- if (!view->swayc || view->swayc->destroying) {
+ if (view->container->node.destroying) {
return false;
}
- struct sway_container *workspace =
- container_parent(view->swayc, C_WORKSPACE);
+ struct sway_workspace *workspace = view->container->workspace;
if (!workspace) {
return false;
}
- // Determine if view is nested inside a floating container which is sticky.
- // A simple floating view will have this ancestry:
- // C_VIEW -> floating -> workspace
- // A more complex ancestry could be:
- // C_VIEW -> C_CONTAINER (tabbed) -> floating -> workspace
- struct sway_container *floater = view->swayc;
- while (floater->parent->type != C_WORKSPACE
- && floater->parent->parent->type != C_WORKSPACE) {
+ // Determine if view is nested inside a floating container which is sticky
+ struct sway_container *floater = view->container;
+ while (floater->parent) {
floater = floater->parent;
}
bool is_sticky = container_is_floating(floater) && floater->is_sticky;
// Check view isn't in a tabbed or stacked container on an inactive tab
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *container = view->swayc;
- while (container->type != C_WORKSPACE) {
- if (container->parent->layout == L_TABBED ||
- container->parent->layout == L_STACKED) {
- if (seat_get_active_child(seat, container->parent) != container) {
+ struct sway_container *container = view->container;
+ while (container) {
+ enum sway_container_layout layout = container_parent_layout(container);
+ if (layout == L_TABBED || layout == L_STACKED) {
+ struct sway_node *parent = container->parent ?
+ &container->parent->node : &container->workspace->node;
+ if (seat_get_active_child(seat, parent) != &container->node) {
return false;
}
}
container = container->parent;
}
// Check view isn't hidden by another fullscreen view
- if (workspace->sway_workspace->fullscreen &&
- !container_is_fullscreen_or_child(view->swayc)) {
+ if (workspace->fullscreen &&
+ !container_is_fullscreen_or_child(view->container)) {
return false;
}
// Check the workspace is visible
@@ -1047,7 +1017,7 @@ void view_set_urgent(struct sway_view *view, bool enable) {
}
if (enable) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
- if (seat_get_focus(seat) == view->swayc) {
+ if (seat_get_focused_container(seat) == view->container) {
return;
}
clock_gettime(CLOCK_MONOTONIC, &view->urgent);
@@ -1058,12 +1028,13 @@ void view_set_urgent(struct sway_view *view, bool enable) {
view->urgent_timer = NULL;
}
}
- container_damage_whole(view->swayc);
+ container_damage_whole(view->container);
- ipc_event_window(view->swayc, "urgent");
+ ipc_event_window(view->container, "urgent");
- struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
- workspace_detect_urgent(ws);
+ if (view->container->workspace) {
+ workspace_detect_urgent(view->container->workspace);
+ }
}
bool view_is_urgent(struct sway_view *view) {
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 1957d94f..bb1ded22 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -12,128 +12,105 @@
#include "sway/output.h"
#include "sway/tree/arrange.h"
#include "sway/tree/container.h"
+#include "sway/tree/node.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
#include "list.h"
#include "log.h"
#include "util.h"
-struct sway_container *workspace_get_initial_output(const char *name) {
- struct sway_container *parent;
+struct sway_output *workspace_get_initial_output(const char *name) {
// Search for workspace<->output pair
- int e = config->workspace_outputs->length;
for (int i = 0; i < config->workspace_outputs->length; ++i) {
struct workspace_output *wso = config->workspace_outputs->items[i];
if (strcasecmp(wso->workspace, name) == 0) {
// Find output to use if it exists
- e = root_container.children->length;
- for (i = 0; i < e; ++i) {
- parent = root_container.children->items[i];
- if (strcmp(parent->name, wso->output) == 0) {
- return parent;
- }
+ struct sway_output *output = output_by_name(wso->output);
+ if (output) {
+ return output;
}
break;
}
}
// Otherwise put it on the focused output
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus =
- seat_get_focus_inactive(seat, &root_container);
- parent = focus;
- parent = container_parent(parent, C_OUTPUT);
- return parent;
+ struct sway_workspace *focus = seat_get_focused_workspace(seat);
+ return focus->output;
}
-struct sway_container *workspace_create(struct sway_container *output,
+struct sway_workspace *workspace_create(struct sway_output *output,
const char *name) {
if (output == NULL) {
output = workspace_get_initial_output(name);
}
- wlr_log(WLR_DEBUG, "Added workspace %s for output %s", name, output->name);
- struct sway_container *workspace = container_create(C_WORKSPACE);
-
- workspace->x = output->x;
- workspace->y = output->y;
- workspace->width = output->width;
- workspace->height = output->height;
- workspace->name = !name ? NULL : strdup(name);
- workspace->prev_split_layout = L_NONE;
- workspace->layout = container_get_default_layout(output);
+ wlr_log(WLR_DEBUG, "Adding workspace %s for output %s", name,
+ output->wlr_output->name);
- struct sway_workspace *swayws = calloc(1, sizeof(struct sway_workspace));
- if (!swayws) {
+ struct sway_workspace *ws = calloc(1, sizeof(struct sway_workspace));
+ if (!ws) {
+ wlr_log(WLR_ERROR, "Unable to allocate sway_workspace");
return NULL;
}
- swayws->swayc = workspace;
- swayws->floating = create_list();
- swayws->output_priority = create_list();
- workspace->sway_workspace = swayws;
- workspace_output_add_priority(workspace, output);
-
- container_add_child(output, workspace);
+ node_init(&ws->node, N_WORKSPACE, ws);
+ ws->x = output->lx;
+ ws->y = output->ly;
+ ws->width = output->width;
+ ws->height = output->height;
+ ws->name = name ? strdup(name) : NULL;
+ ws->prev_split_layout = L_NONE;
+ ws->layout = output_get_default_layout(output);
+ ws->floating = create_list();
+ ws->tiling = create_list();
+ ws->output_priority = create_list();
+ workspace_output_add_priority(ws, output);
+
+ output_add_workspace(output, ws);
output_sort_workspaces(output);
- container_create_notify(workspace);
- return workspace;
+ ipc_event_workspace(NULL, ws, "init");
+ wl_signal_emit(&root->events.new_node, &ws->node);
+
+ return ws;
}
-void workspace_destroy(struct sway_container *workspace) {
- if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
- return;
- }
- if (!sway_assert(workspace->destroying,
+void workspace_destroy(struct sway_workspace *workspace) {
+ if (!sway_assert(workspace->node.destroying,
"Tried to free workspace which wasn't marked as destroying")) {
return;
}
- if (!sway_assert(workspace->ntxnrefs == 0, "Tried to free workspace "
+ if (!sway_assert(workspace->node.ntxnrefs == 0, "Tried to free workspace "
"which is still referenced by transactions")) {
return;
}
- // sway_workspace
- struct sway_workspace *ws = workspace->sway_workspace;
- list_foreach(ws->output_priority, free);
- list_free(ws->output_priority);
- list_free(ws->floating);
- free(ws);
- // swayc
free(workspace->name);
- free(workspace->formatted_title);
- wlr_texture_destroy(workspace->title_focused);
- wlr_texture_destroy(workspace->title_focused_inactive);
- wlr_texture_destroy(workspace->title_unfocused);
- wlr_texture_destroy(workspace->title_urgent);
- list_free(workspace->children);
- list_free(workspace->current.children);
- list_free(workspace->outputs);
+ free(workspace->representation);
+ list_foreach(workspace->output_priority, free);
+ list_free(workspace->output_priority);
+ list_free(workspace->floating);
+ list_free(workspace->tiling);
+ list_free(workspace->current.floating);
+ list_free(workspace->current.tiling);
free(workspace);
}
-void workspace_begin_destroy(struct sway_container *workspace) {
- if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
- return;
- }
+void workspace_begin_destroy(struct sway_workspace *workspace) {
wlr_log(WLR_DEBUG, "Destroying workspace '%s'", workspace->name);
- wl_signal_emit(&workspace->events.destroy, workspace);
ipc_event_workspace(NULL, workspace, "empty"); // intentional
+ wl_signal_emit(&workspace->node.events.destroy, &workspace->node);
- workspace->destroying = true;
- container_set_dirty(workspace);
-
- if (workspace->parent) {
- container_remove_child(workspace);
+ if (workspace->output) {
+ workspace_detach(workspace);
}
+
+ workspace->node.destroying = true;
+ node_set_dirty(&workspace->node);
}
-void workspace_consider_destroy(struct sway_container *ws) {
- if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
- return;
- }
- struct sway_seat *seat = input_manager_current_seat(input_manager);
- if (ws->children->length == 0 && ws->sway_workspace->floating->length == 0
- && seat_get_active_child(seat, ws->parent) != ws) {
+void workspace_consider_destroy(struct sway_workspace *ws) {
+ if (ws->tiling->length == 0 && ws->floating->length == 0
+ && output_get_active_workspace(ws->output) != ws) {
workspace_begin_destroy(ws);
}
}
@@ -272,59 +249,49 @@ char *workspace_next_name(const char *output_name) {
}
// As a fall back, get the current number of active workspaces
// and return that + 1 for the next workspace's name
- int ws_num = root_container.children->length;
+ int ws_num = root->outputs->length;
int l = snprintf(NULL, 0, "%d", ws_num);
char *name = malloc(l + 1);
- if (!sway_assert(name, "Cloud not allocate workspace name")) {
+ if (!sway_assert(name, "Could not allocate workspace name")) {
return NULL;
}
sprintf(name, "%d", ws_num++);
return name;
}
-static bool _workspace_by_number(struct sway_container *view, void *data) {
- if (view->type != C_WORKSPACE) {
- return false;
- }
+static bool _workspace_by_number(struct sway_workspace *ws, void *data) {
char *name = data;
- char *view_name = view->name;
+ char *ws_name = ws->name;
while (isdigit(*name)) {
- if (*name++ != *view_name++) {
+ if (*name++ != *ws_name++) {
return false;
}
}
- return !isdigit(*view_name);
+ return !isdigit(*ws_name);
}
-struct sway_container *workspace_by_number(const char* name) {
+struct sway_workspace *workspace_by_number(const char* name) {
return root_find_workspace(_workspace_by_number, (void *) name);
}
-static bool _workspace_by_name(struct sway_container *view, void *data) {
- return (view->type == C_WORKSPACE) &&
- (strcasecmp(view->name, (char *) data) == 0);
+static bool _workspace_by_name(struct sway_workspace *ws, void *data) {
+ return strcasecmp(ws->name, data) == 0;
}
-struct sway_container *workspace_by_name(const char *name) {
+struct sway_workspace *workspace_by_name(const char *name) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *current_workspace = NULL, *current_output = NULL;
- struct sway_container *focus = seat_get_focus(seat);
- if (focus) {
- current_workspace = focus->type == C_WORKSPACE ?
- focus : container_parent(focus, C_WORKSPACE);
- current_output = container_parent(focus, C_OUTPUT);
- }
+ struct sway_workspace *current = seat_get_focused_workspace(seat);
if (strcmp(name, "prev") == 0) {
- return workspace_prev(current_workspace);
+ return workspace_prev(current);
} else if (strcmp(name, "prev_on_output") == 0) {
- return workspace_output_prev(current_output);
+ return workspace_output_prev(current);
} else if (strcmp(name, "next") == 0) {
- return workspace_next(current_workspace);
+ return workspace_next(current);
} else if (strcmp(name, "next_on_output") == 0) {
- return workspace_output_next(current_output);
+ return workspace_output_next(current);
} else if (strcmp(name, "current") == 0) {
- return current_workspace;
+ return current;
} else if (strcasecmp(name, "back_and_forth") == 0) {
return prev_workspace_name ?
root_find_workspace(_workspace_by_name, (void*)prev_workspace_name)
@@ -339,97 +306,68 @@ struct sway_container *workspace_by_name(const char *name) {
* the end and beginning. If next is false, the previous workspace is returned,
* otherwise the next one is returned.
*/
-static struct sway_container *workspace_output_prev_next_impl(
- struct sway_container *output, int dir) {
- if (!output) {
- return NULL;
- }
- if (!sway_assert(output->type == C_OUTPUT,
- "Argument must be an output, is %d", output->type)) {
- return NULL;
- }
-
+static struct sway_workspace *workspace_output_prev_next_impl(
+ struct sway_output *output, int dir) {
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = seat_get_focus_inactive(seat, output);
- struct sway_container *workspace = (focus->type == C_WORKSPACE ?
- focus :
- container_parent(focus, C_WORKSPACE));
+ struct sway_workspace *workspace = seat_get_focused_workspace(seat);
- int index = list_find(output->children, workspace);
- size_t new_index = wrap(index + dir, output->children->length);
- return output->children->items[new_index];
+ int index = list_find(output->workspaces, workspace);
+ size_t new_index = wrap(index + dir, output->workspaces->length);
+ return output->workspaces->items[new_index];
}
/**
* Get the previous or next workspace. If the first/last workspace on an output
* is active, proceed to the previous/next output's previous/next workspace.
*/
-static struct sway_container *workspace_prev_next_impl(
- struct sway_container *workspace, int dir) {
- if (!workspace) {
- return NULL;
- }
- if (!sway_assert(workspace->type == C_WORKSPACE,
- "Argument must be a workspace, is %d", workspace->type)) {
- return NULL;
- }
-
- struct sway_container *output = workspace->parent;
- int index = list_find(output->children, workspace);
+static struct sway_workspace *workspace_prev_next_impl(
+ struct sway_workspace *workspace, int dir) {
+ struct sway_output *output = workspace->output;
+ int index = list_find(output->workspaces, workspace);
int new_index = index + dir;
- if (new_index >= 0 && new_index < output->children->length) {
- return output->children->items[index + dir];
+ if (new_index >= 0 && new_index < output->workspaces->length) {
+ return output->workspaces->items[new_index];
}
// Look on a different output
- int output_index = list_find(root_container.children, output);
- new_index = wrap(output_index + dir, root_container.children->length);
- output = root_container.children->items[new_index];
+ int output_index = list_find(root->outputs, output);
+ new_index = wrap(output_index + dir, root->outputs->length);
+ output = root->outputs->items[new_index];
if (dir == 1) {
- return output->children->items[0];
+ return output->workspaces->items[0];
} else {
- return output->children->items[output->children->length - 1];
+ return output->workspaces->items[output->workspaces->length - 1];
}
}
-struct sway_container *workspace_output_next(struct sway_container *current) {
- return workspace_output_prev_next_impl(current, 1);
+struct sway_workspace *workspace_output_next(struct sway_workspace *current) {
+ return workspace_output_prev_next_impl(current->output, 1);
}
-struct sway_container *workspace_next(struct sway_container *current) {
+struct sway_workspace *workspace_next(struct sway_workspace *current) {
return workspace_prev_next_impl(current, 1);
}
-struct sway_container *workspace_output_prev(struct sway_container *current) {
- return workspace_output_prev_next_impl(current, -1);
+struct sway_workspace *workspace_output_prev(struct sway_workspace *current) {
+ return workspace_output_prev_next_impl(current->output, -1);
}
-struct sway_container *workspace_prev(struct sway_container *current) {
+struct sway_workspace *workspace_prev(struct sway_workspace *current) {
return workspace_prev_next_impl(current, -1);
}
-bool workspace_switch(struct sway_container *workspace,
+bool workspace_switch(struct sway_workspace *workspace,
bool no_auto_back_and_forth) {
- if (!workspace) {
- return false;
- }
struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus =
- seat_get_focus_inactive(seat, &root_container);
- if (!seat || !focus) {
- return false;
- }
- struct sway_container *active_ws = focus;
- if (active_ws->type != C_WORKSPACE) {
- active_ws = container_parent(focus, C_WORKSPACE);
- }
+ struct sway_node *focus = seat_get_focus_inactive(seat, &root->node);
+ struct sway_workspace *active_ws = seat_get_focused_workspace(seat);
if (!no_auto_back_and_forth && config->auto_back_and_forth
&& active_ws == workspace
&& prev_workspace_name) {
- struct sway_container *new_ws = workspace_by_name(prev_workspace_name);
+ struct sway_workspace *new_ws = workspace_by_name(prev_workspace_name);
workspace = new_ws ?
new_ws :
workspace_create(NULL, prev_workspace_name);
@@ -447,21 +385,21 @@ bool workspace_switch(struct sway_container *workspace,
}
// Move sticky containers to new workspace
- struct sway_container *next_output = workspace->parent;
- struct sway_container *next_output_prev_ws =
- seat_get_active_child(seat, next_output);
- list_t *floating = next_output_prev_ws->sway_workspace->floating;
+ struct sway_output *next_output = workspace->output;
+ struct sway_workspace *next_output_prev_ws =
+ output_get_active_workspace(next_output);
bool has_sticky = false;
if (workspace != next_output_prev_ws) {
- for (int i = 0; i < floating->length; ++i) {
- struct sway_container *floater = floating->items[i];
+ for (int i = 0; i < next_output_prev_ws->floating->length; ++i) {
+ struct sway_container *floater =
+ next_output_prev_ws->floating->items[i];
if (floater->is_sticky) {
has_sticky = true;
- container_remove_child(floater);
+ container_detach(floater);
workspace_add_floating(workspace, floater);
- if (floater == focus) {
+ if (&floater->node == focus) {
seat_set_focus(seat, NULL);
- seat_set_focus(seat, floater);
+ seat_set_focus(seat, &floater->node);
}
--i;
}
@@ -470,9 +408,9 @@ bool workspace_switch(struct sway_container *workspace,
wlr_log(WLR_DEBUG, "Switching to workspace %p:%s",
workspace, workspace->name);
- struct sway_container *next = seat_get_focus_inactive(seat, workspace);
+ struct sway_node *next = seat_get_focus_inactive(seat, &workspace->node);
if (next == NULL) {
- next = workspace;
+ next = &workspace->node;
}
if (has_sticky) {
// If there's a sticky container, we might be setting focus to the same
@@ -483,35 +421,24 @@ bool workspace_switch(struct sway_container *workspace,
workspace_consider_destroy(active_ws);
}
seat_set_focus(seat, next);
- struct sway_container *output = container_parent(workspace, C_OUTPUT);
- arrange_windows(output);
+ arrange_workspace(workspace);
return true;
}
-bool workspace_is_visible(struct sway_container *ws) {
- if (ws->destroying) {
+bool workspace_is_visible(struct sway_workspace *ws) {
+ if (ws->node.destroying) {
return false;
}
- struct sway_container *output = container_parent(ws, C_OUTPUT);
- struct sway_seat *seat = input_manager_current_seat(input_manager);
- struct sway_container *focus = seat_get_focus_inactive(seat, output);
- if (focus->type != C_WORKSPACE) {
- focus = container_parent(focus, C_WORKSPACE);
- }
- return focus == ws;
+ return output_get_active_workspace(ws->output) == ws;
}
-bool workspace_is_empty(struct sway_container *ws) {
- if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
- return false;
- }
- if (ws->children->length) {
+bool workspace_is_empty(struct sway_workspace *ws) {
+ if (ws->tiling->length) {
return false;
}
// Sticky views are not considered to be part of this workspace
- list_t *floating = ws->sway_workspace->floating;
- for (int i = 0; i < floating->length; ++i) {
- struct sway_container *floater = floating->items[i];
+ for (int i = 0; i < ws->floating->length; ++i) {
+ struct sway_container *floater = ws->floating->items[i];
if (!floater->is_sticky) {
return false;
}
@@ -523,20 +450,19 @@ static int find_output(const void *id1, const void *id2) {
return strcmp(id1, id2) ? 0 : 1;
}
-void workspace_output_raise_priority(struct sway_container *workspace,
- struct sway_container *old_output, struct sway_container *output) {
- struct sway_workspace *ws = workspace->sway_workspace;
-
+void workspace_output_raise_priority(struct sway_workspace *ws,
+ struct sway_output *old_output, struct sway_output *output) {
int old_index = list_seq_find(ws->output_priority, find_output,
- old_output->name);
+ old_output->wlr_output->name);
if (old_index < 0) {
return;
}
int new_index = list_seq_find(ws->output_priority, find_output,
- output->name);
+ output->wlr_output->name);
if (new_index < 0) {
- list_insert(ws->output_priority, old_index, strdup(output->name));
+ list_insert(ws->output_priority, old_index,
+ strdup(output->wlr_output->name));
} else if (new_index > old_index) {
char *name = ws->output_priority->items[new_index];
list_del(ws->output_priority, new_index);
@@ -544,29 +470,24 @@ void workspace_output_raise_priority(struct sway_container *workspace,
}
}
-void workspace_output_add_priority(struct sway_container *workspace,
- struct sway_container *output) {
- int index = list_seq_find(workspace->sway_workspace->output_priority,
- find_output, output->name);
+void workspace_output_add_priority(struct sway_workspace *workspace,
+ struct sway_output *output) {
+ int index = list_seq_find(workspace->output_priority,
+ find_output, output->wlr_output->name);
if (index < 0) {
- list_add(workspace->sway_workspace->output_priority,
- strdup(output->name));
+ list_add(workspace->output_priority, strdup(output->wlr_output->name));
}
}
-static bool _output_by_name(struct sway_container *output, void *data) {
- return output->type == C_OUTPUT && strcasecmp(output->name, data) == 0;
-}
-
-struct sway_container *workspace_output_get_highest_available(
- struct sway_container *ws, struct sway_container *exclude) {
- for (int i = 0; i < ws->sway_workspace->output_priority->length; i++) {
- char *name = ws->sway_workspace->output_priority->items[i];
- if (exclude && strcasecmp(name, exclude->name) == 0) {
+struct sway_output *workspace_output_get_highest_available(
+ struct sway_workspace *ws, struct sway_output *exclude) {
+ for (int i = 0; i < ws->output_priority->length; i++) {
+ char *name = ws->output_priority->items[i];
+ if (exclude && strcasecmp(name, exclude->wlr_output->name) == 0) {
continue;
}
- struct sway_container *output = root_find_output(_output_by_name, name);
+ struct sway_output *output = output_by_name(name);
if (output) {
return output;
}
@@ -576,49 +497,42 @@ struct sway_container *workspace_output_get_highest_available(
}
static bool find_urgent_iterator(struct sway_container *con, void *data) {
- return con->type == C_VIEW && view_is_urgent(con->sway_view);
+ return con->view && view_is_urgent(con->view);
}
-void workspace_detect_urgent(struct sway_container *workspace) {
+void workspace_detect_urgent(struct sway_workspace *workspace) {
bool new_urgent = (bool)workspace_find_container(workspace,
find_urgent_iterator, NULL);
- if (workspace->sway_workspace->urgent != new_urgent) {
- workspace->sway_workspace->urgent = new_urgent;
+ if (workspace->urgent != new_urgent) {
+ workspace->urgent = new_urgent;
ipc_event_workspace(NULL, workspace, "urgent");
- container_damage_whole(workspace);
+ output_damage_whole(workspace->output);
}
}
-void workspace_for_each_container(struct sway_container *ws,
+void workspace_for_each_container(struct sway_workspace *ws,
void (*f)(struct sway_container *con, void *data), void *data) {
- if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
- return;
- }
// Tiling
- for (int i = 0; i < ws->children->length; ++i) {
- struct sway_container *container = ws->children->items[i];
+ for (int i = 0; i < ws->tiling->length; ++i) {
+ struct sway_container *container = ws->tiling->items[i];
f(container, data);
container_for_each_child(container, f, data);
}
// Floating
- for (int i = 0; i < ws->sway_workspace->floating->length; ++i) {
- struct sway_container *container =
- ws->sway_workspace->floating->items[i];
+ for (int i = 0; i < ws->floating->length; ++i) {
+ struct sway_container *container = ws->floating->items[i];
f(container, data);
container_for_each_child(container, f, data);
}
}
-struct sway_container *workspace_find_container(struct sway_container *ws,
+struct sway_container *workspace_find_container(struct sway_workspace *ws,
bool (*test)(struct sway_container *con, void *data), void *data) {
- if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
- return NULL;
- }
struct sway_container *result = NULL;
// Tiling
- for (int i = 0; i < ws->children->length; ++i) {
- struct sway_container *child = ws->children->items[i];
+ for (int i = 0; i < ws->tiling->length; ++i) {
+ struct sway_container *child = ws->tiling->items[i];
if (test(child, data)) {
return child;
}
@@ -627,8 +541,8 @@ struct sway_container *workspace_find_container(struct sway_container *ws,
}
}
// Floating
- for (int i = 0; i < ws->sway_workspace->floating->length; ++i) {
- struct sway_container *child = ws->sway_workspace->floating->items[i];
+ for (int i = 0; i < ws->floating->length; ++i) {
+ struct sway_container *child = ws->floating->items[i];
if (test(child, data)) {
return child;
}
@@ -639,37 +553,76 @@ struct sway_container *workspace_find_container(struct sway_container *ws,
return NULL;
}
-struct sway_container *workspace_wrap_children(struct sway_container *ws) {
- struct sway_container *middle = container_create(C_CONTAINER);
+struct sway_container *workspace_wrap_children(struct sway_workspace *ws) {
+ struct sway_container *middle = container_create(NULL);
middle->layout = ws->layout;
- while (ws->children->length) {
- struct sway_container *child = ws->children->items[0];
- container_remove_child(child);
+ while (ws->tiling->length) {
+ struct sway_container *child = ws->tiling->items[0];
+ container_detach(child);
container_add_child(middle, child);
}
- container_add_child(ws, middle);
+ workspace_add_tiling(ws, middle);
return middle;
}
-void workspace_add_floating(struct sway_container *workspace,
- struct sway_container *con) {
- if (!sway_assert(workspace->type == C_WORKSPACE, "Expected a workspace")) {
- return;
+void workspace_detach(struct sway_workspace *workspace) {
+ struct sway_output *output = workspace->output;
+ int index = list_find(output->workspaces, workspace);
+ if (index != -1) {
+ list_del(output->workspaces, index);
}
- if (!sway_assert(con->parent == NULL, "Expected an orphan container")) {
- return;
+ workspace->output = NULL;
+
+ node_set_dirty(&workspace->node);
+ node_set_dirty(&output->node);
+}
+
+static void set_workspace(struct sway_container *container, void *data) {
+ container->workspace = container->parent->workspace;
+}
+
+void workspace_add_tiling(struct sway_workspace *workspace,
+ struct sway_container *con) {
+ if (con->workspace) {
+ container_detach(con);
}
+ list_add(workspace->tiling, con);
+ con->workspace = workspace;
+ container_for_each_child(con, set_workspace, NULL);
+ container_handle_fullscreen_reparent(con);
+ workspace_update_representation(workspace);
+ node_set_dirty(&workspace->node);
+ node_set_dirty(&con->node);
+}
- list_add(workspace->sway_workspace->floating, con);
- con->parent = workspace;
- container_set_dirty(workspace);
- container_set_dirty(con);
+void workspace_add_floating(struct sway_workspace *workspace,
+ struct sway_container *con) {
+ if (con->workspace) {
+ container_detach(con);
+ }
+ list_add(workspace->floating, con);
+ con->workspace = workspace;
+ container_for_each_child(con, set_workspace, NULL);
+ container_handle_fullscreen_reparent(con);
+ node_set_dirty(&workspace->node);
+ node_set_dirty(&con->node);
}
-void workspace_remove_gaps(struct sway_container *ws) {
- if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
- return;
+void workspace_insert_tiling(struct sway_workspace *workspace,
+ struct sway_container *con, int index) {
+ if (con->workspace) {
+ container_detach(con);
}
+ list_insert(workspace->tiling, index, con);
+ con->workspace = workspace;
+ container_for_each_child(con, set_workspace, NULL);
+ container_handle_fullscreen_reparent(con);
+ workspace_update_representation(workspace);
+ node_set_dirty(&workspace->node);
+ node_set_dirty(&con->node);
+}
+
+void workspace_remove_gaps(struct sway_workspace *ws) {
if (ws->current_gaps == 0) {
return;
}
@@ -681,15 +634,12 @@ void workspace_remove_gaps(struct sway_container *ws) {
ws->current_gaps = 0;
}
-void workspace_add_gaps(struct sway_container *ws) {
- if (!sway_assert(ws->type == C_WORKSPACE, "Expected a workspace")) {
- return;
- }
+void workspace_add_gaps(struct sway_workspace *ws) {
if (ws->current_gaps > 0) {
return;
}
bool should_apply =
- config->edge_gaps || (config->smart_gaps && ws->children->length > 1);
+ config->edge_gaps || (config->smart_gaps && ws->tiling->length > 1);
if (!should_apply) {
return;
}
@@ -708,3 +658,36 @@ void workspace_add_gaps(struct sway_container *ws) {
ws->width -= 2 * ws->current_gaps;
ws->height -= 2 * ws->current_gaps;
}
+
+struct sway_container *workspace_split(struct sway_workspace *workspace,
+ enum sway_container_layout layout) {
+ if (workspace->tiling->length == 0) {
+ workspace->prev_split_layout = workspace->layout;
+ workspace->layout = layout;
+ return NULL;
+ }
+
+ enum sway_container_layout old_layout = workspace->layout;
+ struct sway_container *middle = workspace_wrap_children(workspace);
+ workspace->layout = layout;
+ middle->layout = old_layout;
+
+ return middle;
+}
+
+void workspace_update_representation(struct sway_workspace *ws) {
+ size_t len = container_build_representation(ws->layout, ws->tiling, NULL);
+ free(ws->representation);
+ ws->representation = calloc(len + 1, sizeof(char));
+ if (!sway_assert(ws->representation, "Unable to allocate title string")) {
+ return;
+ }
+ container_build_representation(ws->layout, ws->tiling, ws->representation);
+}
+
+void workspace_get_box(struct sway_workspace *workspace, struct wlr_box *box) {
+ box->x = workspace->x;
+ box->y = workspace->y;
+ box->width = workspace->width;
+ box->height = workspace->height;
+}