aboutsummaryrefslogtreecommitdiff
path: root/sway/tree
diff options
context:
space:
mode:
Diffstat (limited to 'sway/tree')
-rw-r--r--sway/tree/container.c74
-rw-r--r--sway/tree/node.c29
-rw-r--r--sway/tree/output.c34
-rw-r--r--sway/tree/root.c28
-rw-r--r--sway/tree/view.c10
-rw-r--r--sway/tree/workspace.c17
6 files changed, 188 insertions, 4 deletions
diff --git a/sway/tree/container.c b/sway/tree/container.c
index 8c344a6d..9ed08929 100644
--- a/sway/tree/container.c
+++ b/sway/tree/container.c
@@ -27,6 +27,24 @@
#include "log.h"
#include "stringop.h"
+static struct wlr_scene_rect *alloc_rect_node(struct wlr_scene_tree *parent,
+ bool *failed) {
+ if (*failed) {
+ return NULL;
+ }
+
+ // just pass in random values. These will be overwritten when
+ // they need to be used.
+ struct wlr_scene_rect *rect = wlr_scene_rect_create(
+ parent, 0, 0, (float[4]){0.f, 0.f, 0.f, 1.f});
+ if (!rect) {
+ sway_log(SWAY_ERROR, "Failed to allocate a wlr_scene_rect");
+ *failed = true;
+ }
+
+ return rect;
+}
+
struct sway_container *container_create(struct sway_view *view) {
struct sway_container *c = calloc(1, sizeof(struct sway_container));
if (!c) {
@@ -34,14 +52,62 @@ struct sway_container *container_create(struct sway_view *view) {
return NULL;
}
node_init(&c->node, N_CONTAINER, c);
- c->pending.layout = L_NONE;
- c->view = view;
- c->alpha = 1.0f;
+
+ // Container tree structure
+ // - scene tree
+ // - title bar
+ // - border
+ // - background
+ // - title text
+ // - marks text
+ // - border
+ // - border top/bottom/left/right
+ // - content_tree (we put the content node here so when we disable the
+ // border everything gets disabled. We only render the content iff there
+ // is a border as well)
+ bool failed = false;
+ c->scene_tree = alloc_scene_tree(root->staging, &failed);
+
+ c->title_bar.tree = alloc_scene_tree(c->scene_tree, &failed);
+ c->title_bar.border = alloc_scene_tree(c->title_bar.tree, &failed);
+ c->title_bar.background = alloc_scene_tree(c->title_bar.tree, &failed);
+
+ // for opacity purposes we need to carfully create the scene such that
+ // none of our rect nodes as well as text buffers don't overlap. To do
+ // this we have to create rects such that they go around text buffers
+ for (int i = 0; i < 4; i++) {
+ alloc_rect_node(c->title_bar.border, &failed);
+ }
+
+ for (int i = 0; i < 5; i++) {
+ alloc_rect_node(c->title_bar.background, &failed);
+ }
+
+ c->border.tree = alloc_scene_tree(c->scene_tree, &failed);
+ c->content_tree = alloc_scene_tree(c->border.tree, &failed);
+
+ if (view) {
+ // only containers with views can have borders
+ c->border.top = alloc_rect_node(c->border.tree, &failed);
+ c->border.bottom = alloc_rect_node(c->border.tree, &failed);
+ c->border.left = alloc_rect_node(c->border.tree, &failed);
+ c->border.right = alloc_rect_node(c->border.tree, &failed);
+ }
+
+ if (failed) {
+ wlr_scene_node_destroy(&c->scene_tree->node);
+ free(c);
+ return NULL;
+ }
if (!view) {
c->pending.children = create_list();
c->current.children = create_list();
}
+
+ c->pending.layout = L_NONE;
+ c->view = view;
+ c->alpha = 1.0f;
c->marks = create_list();
c->outputs = create_list();
@@ -85,6 +151,8 @@ void container_destroy(struct sway_container *con) {
}
}
+ scene_node_disown_children(con->content_tree);
+ wlr_scene_node_destroy(&con->scene_tree->node);
free(con);
}
diff --git a/sway/tree/node.c b/sway/tree/node.c
index 12361c75..213cf0a6 100644
--- a/sway/tree/node.c
+++ b/sway/tree/node.c
@@ -159,3 +159,32 @@ bool node_has_ancestor(struct sway_node *node, struct sway_node *ancestor) {
}
return false;
}
+
+void scene_node_disown_children(struct wlr_scene_tree *tree) {
+ // this function can be called as part of destruction code that will be invoked
+ // upon an allocation failure. Let's not crash on NULL due to an allocation error.
+ if (!tree) {
+ return;
+ }
+
+ struct wlr_scene_node *child, *tmp_child;
+ wl_list_for_each_safe(child, tmp_child, &tree->children, link) {
+ wlr_scene_node_reparent(child, root->staging);
+ }
+}
+
+struct wlr_scene_tree *alloc_scene_tree(struct wlr_scene_tree *parent,
+ bool *failed) {
+ // fallthrough
+ if (*failed) {
+ return NULL;
+ }
+
+ struct wlr_scene_tree *tree = wlr_scene_tree_create(parent);
+ if (!tree) {
+ sway_log(SWAY_ERROR, "Failed to allocate a scene node");
+ *failed = true;
+ }
+
+ return tree;
+}
diff --git a/sway/tree/output.c b/sway/tree/output.c
index 2186ad0c..12a2f969 100644
--- a/sway/tree/output.c
+++ b/sway/tree/output.c
@@ -87,9 +87,41 @@ static void restore_workspaces(struct sway_output *output) {
output_sort_workspaces(output);
}
+static void destroy_scene_layers(struct sway_output *output) {
+ wlr_scene_node_destroy(&output->fullscreen_background->node);
+
+ scene_node_disown_children(output->layers.tiling);
+ scene_node_disown_children(output->layers.fullscreen);
+
+ wlr_scene_node_destroy(&output->layers.tiling->node);
+ wlr_scene_node_destroy(&output->layers.fullscreen->node);
+}
+
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);
+
+ bool failed = false;
+ output->layers.tiling = alloc_scene_tree(root->staging, &failed);
+ output->layers.fullscreen = alloc_scene_tree(root->staging, &failed);
+
+ if (!failed) {
+ output->fullscreen_background = wlr_scene_rect_create(
+ output->layers.fullscreen, 0, 0, (float[4]){0.f, 0.f, 0.f, 1.f});
+
+ if (!output->fullscreen_background) {
+ sway_log(SWAY_ERROR, "Unable to allocate a background rect");
+ failed = true;
+ }
+ }
+
+ if (failed) {
+ destroy_scene_layers(output);
+ wlr_scene_output_destroy(output->scene_output);
+ free(output);
+ return NULL;
+ }
+
output->wlr_output = wlr_output;
wlr_output->data = output;
output->detected_subpixel = wlr_output->subpixel;
@@ -238,6 +270,8 @@ void output_destroy(struct sway_output *output) {
"which is still referenced by transactions")) {
return;
}
+
+ destroy_scene_layers(output);
list_free(output->workspaces);
list_free(output->current.workspaces);
wl_event_source_remove(output->repaint_timer);
diff --git a/sway/tree/root.c b/sway/tree/root.c
index dc51c3be..75fb63f1 100644
--- a/sway/tree/root.c
+++ b/sway/tree/root.c
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_scene.h>
#include <wlr/util/transform.h>
#include "sway/desktop/transaction.h"
#include "sway/input/seat.h"
@@ -30,7 +31,33 @@ struct sway_root *root_create(struct wl_display *wl_display) {
sway_log(SWAY_ERROR, "Unable to allocate sway_root");
return NULL;
}
+
+ struct wlr_scene *root_scene = wlr_scene_create();
+ if (!root_scene) {
+ sway_log(SWAY_ERROR, "Unable to allocate root scene node");
+ free(root);
+ return NULL;
+ }
+
node_init(&root->node, N_ROOT, root);
+ root->root_scene = root_scene;
+
+ bool failed = false;
+ root->staging = alloc_scene_tree(&root_scene->tree, &failed);
+
+ root->layers.tiling = alloc_scene_tree(&root_scene->tree, &failed);
+ root->layers.floating = alloc_scene_tree(&root_scene->tree, &failed);
+ root->layers.fullscreen = alloc_scene_tree(&root_scene->tree, &failed);
+ root->layers.fullscreen_global = alloc_scene_tree(&root_scene->tree, &failed);
+
+ if (failed) {
+ wlr_scene_node_destroy(&root_scene->tree.node);
+ free(root);
+ return NULL;
+ }
+
+ wlr_scene_node_set_enabled(&root->staging->node, false);
+
root->output_layout = wlr_output_layout_create(wl_display);
wl_list_init(&root->all_outputs);
#if HAVE_XWAYLAND
@@ -53,6 +80,7 @@ void root_destroy(struct sway_root *root) {
list_free(root->scratchpad);
list_free(root->non_desktop_outputs);
list_free(root->outputs);
+ wlr_scene_node_destroy(&root->root_scene->tree.node);
free(root);
}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index d62a0667..bc968edc 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -37,6 +37,14 @@
bool view_init(struct sway_view *view, enum sway_view_type type,
const struct sway_view_impl *impl) {
+ bool failed = false;
+ view->scene_tree = alloc_scene_tree(root->staging, &failed);
+ view->content_tree = alloc_scene_tree(view->scene_tree, &failed);
+ if (failed) {
+ wlr_scene_node_destroy(&view->scene_tree->node);
+ return false;
+ }
+
view->type = type;
view->impl = impl;
view->executed_criteria = create_list();
@@ -67,7 +75,7 @@ void view_destroy(struct sway_view *view) {
list_free(view->executed_criteria);
view_assign_ctx(view, NULL);
-
+ wlr_scene_node_destroy(&view->scene_tree->node);
free(view->title_format);
if (view->impl->destroy) {
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 18218768..f60b2366 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -71,6 +71,18 @@ struct sway_workspace *workspace_create(struct sway_output *output,
return NULL;
}
node_init(&ws->node, N_WORKSPACE, ws);
+
+ bool failed = false;
+ ws->layers.tiling = alloc_scene_tree(root->staging, &failed);
+ ws->layers.fullscreen = alloc_scene_tree(root->staging, &failed);
+
+ if (failed) {
+ wlr_scene_node_destroy(&ws->layers.tiling->node);
+ wlr_scene_node_destroy(&ws->layers.fullscreen->node);
+ free(ws);
+ return NULL;
+ }
+
ws->name = strdup(name);
ws->prev_split_layout = L_NONE;
ws->layout = output_get_default_layout(output);
@@ -131,6 +143,11 @@ void workspace_destroy(struct sway_workspace *workspace) {
return;
}
+ scene_node_disown_children(workspace->layers.tiling);
+ scene_node_disown_children(workspace->layers.fullscreen);
+ wlr_scene_node_destroy(&workspace->layers.tiling->node);
+ wlr_scene_node_destroy(&workspace->layers.fullscreen->node);
+
free(workspace->name);
free(workspace->representation);
list_free_items_and_destroy(workspace->output_priority);