diff options
Diffstat (limited to 'sway/tree')
-rw-r--r-- | sway/tree/container.c | 74 | ||||
-rw-r--r-- | sway/tree/node.c | 29 | ||||
-rw-r--r-- | sway/tree/output.c | 34 | ||||
-rw-r--r-- | sway/tree/root.c | 28 | ||||
-rw-r--r-- | sway/tree/view.c | 10 | ||||
-rw-r--r-- | sway/tree/workspace.c | 17 |
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); |