aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Alexander Orzechowski <alex@ozal.ski>2024-01-18 10:00:45 -0500
committerLibravatar Kirill Primak <vyivel@eclair.cafe>2024-01-18 18:36:54 +0300
commit1eb16d136774c8fb3c9085df45156264f0db8814 (patch)
tree9c348ab37edae50b76a388d7e8d8dcd011cea33b
parentview: init function should return a success bool (diff)
downloadsway-1eb16d136774c8fb3c9085df45156264f0db8814.tar.gz
sway-1eb16d136774c8fb3c9085df45156264f0db8814.tar.zst
sway-1eb16d136774c8fb3c9085df45156264f0db8814.zip
scene_graph: Maintain `wlr_scene_node`s for the sway tree.
-rw-r--r--include/sway/output.h15
-rw-r--r--include/sway/tree/container.h21
-rw-r--r--include/sway/tree/node.h12
-rw-r--r--include/sway/tree/root.h26
-rw-r--r--include/sway/tree/view.h4
-rw-r--r--include/sway/tree/workspace.h7
-rw-r--r--sway/desktop/output.c18
-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
13 files changed, 288 insertions, 7 deletions
diff --git a/include/sway/output.h b/include/sway/output.h
index 96bd10db..691ac8dd 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -5,6 +5,7 @@
5#include <wayland-server-core.h> 5#include <wayland-server-core.h>
6#include <wlr/types/wlr_damage_ring.h> 6#include <wlr/types/wlr_damage_ring.h>
7#include <wlr/types/wlr_output.h> 7#include <wlr/types/wlr_output.h>
8#include <wlr/types/wlr_scene.h>
8#include "config.h" 9#include "config.h"
9#include "sway/tree/node.h" 10#include "sway/tree/node.h"
10#include "sway/tree/view.h" 11#include "sway/tree/view.h"
@@ -19,7 +20,21 @@ struct sway_output_state {
19 20
20struct sway_output { 21struct sway_output {
21 struct sway_node node; 22 struct sway_node node;
23
24 struct {
25 struct wlr_scene_tree *tiling;
26 struct wlr_scene_tree *fullscreen;
27 } layers;
28
29 // when a container is fullscreen, in case the fullscreen surface is
30 // translucent (can see behind) we must make sure that the background is a
31 // solid color in order to conform to the wayland protocol. This rect
32 // ensures that when looking through a surface, all that will be seen
33 // is black.
34 struct wlr_scene_rect *fullscreen_background;
35
22 struct wlr_output *wlr_output; 36 struct wlr_output *wlr_output;
37 struct wlr_scene_output *scene_output;
23 struct sway_server *server; 38 struct sway_server *server;
24 struct wl_list link; 39 struct wl_list link;
25 40
diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h
index fe3ee8a8..ee22a0d0 100644
--- a/include/sway/tree/container.h
+++ b/include/sway/tree/container.h
@@ -3,6 +3,7 @@
3#include <stdint.h> 3#include <stdint.h>
4#include <sys/types.h> 4#include <sys/types.h>
5#include <wlr/types/wlr_compositor.h> 5#include <wlr/types/wlr_compositor.h>
6#include <wlr/types/wlr_scene.h>
6#include "list.h" 7#include "list.h"
7#include "sway/tree/node.h" 8#include "sway/tree/node.h"
8 9
@@ -68,6 +69,26 @@ struct sway_container {
68 struct sway_node node; 69 struct sway_node node;
69 struct sway_view *view; 70 struct sway_view *view;
70 71
72 struct wlr_scene_tree *scene_tree;
73
74 struct {
75 struct wlr_scene_tree *tree;
76
77 struct wlr_scene_tree *border;
78 struct wlr_scene_tree *background;
79 } title_bar;
80
81 struct {
82 struct wlr_scene_tree *tree;
83
84 struct wlr_scene_rect *top;
85 struct wlr_scene_rect *bottom;
86 struct wlr_scene_rect *left;
87 struct wlr_scene_rect *right;
88 } border;
89
90 struct wlr_scene_tree *content_tree;
91
71 struct sway_container_state current; 92 struct sway_container_state current;
72 struct sway_container_state pending; 93 struct sway_container_state pending;
73 94
diff --git a/include/sway/tree/node.h b/include/sway/tree/node.h
index 03a389a4..e2dbcdf0 100644
--- a/include/sway/tree/node.h
+++ b/include/sway/tree/node.h
@@ -2,6 +2,7 @@
2#define _SWAY_NODE_H 2#define _SWAY_NODE_H
3#include <wayland-server-core.h> 3#include <wayland-server-core.h>
4#include <stdbool.h> 4#include <stdbool.h>
5#include <wlr/types/wlr_scene.h>
5#include "list.h" 6#include "list.h"
6 7
7#define MIN_SANE_W 100 8#define MIN_SANE_W 100
@@ -75,4 +76,15 @@ list_t *node_get_children(struct sway_node *node);
75 76
76bool node_has_ancestor(struct sway_node *node, struct sway_node *ancestor); 77bool node_has_ancestor(struct sway_node *node, struct sway_node *ancestor);
77 78
79// when destroying a sway tree, it's not known which order the tree will be
80// destroyed. To prevent freeing of scene_nodes recursing up the tree,
81// let's use this helper function to disown them to the staging node.
82void scene_node_disown_children(struct wlr_scene_tree *tree);
83
84// a helper function used to allocate tree nodes. If an allocation failure
85// occurs a flag is flipped that can be checked later to destroy a parent
86// of this scene node preventing memory leaks.
87struct wlr_scene_tree *alloc_scene_tree(struct wlr_scene_tree *parent,
88 bool *failed);
89
78#endif 90#endif
diff --git a/include/sway/tree/root.h b/include/sway/tree/root.h
index b3dda12f..9cb3d7bf 100644
--- a/include/sway/tree/root.h
+++ b/include/sway/tree/root.h
@@ -3,6 +3,7 @@
3#include <wayland-server-core.h> 3#include <wayland-server-core.h>
4#include <wayland-util.h> 4#include <wayland-util.h>
5#include <wlr/types/wlr_output_layout.h> 5#include <wlr/types/wlr_output_layout.h>
6#include <wlr/types/wlr_scene.h>
6#include <wlr/render/wlr_texture.h> 7#include <wlr/render/wlr_texture.h>
7#include "sway/tree/container.h" 8#include "sway/tree/container.h"
8#include "sway/tree/node.h" 9#include "sway/tree/node.h"
@@ -16,6 +17,31 @@ struct sway_root {
16 struct wlr_output_layout *output_layout; 17 struct wlr_output_layout *output_layout;
17 18
18 struct wl_listener output_layout_change; 19 struct wl_listener output_layout_change;
20
21 // scene node layout:
22 // - root
23 // - staging
24 // - layer shell stuff
25 // - tiling
26 // - floating
27 // - fullscreen stuff
28 // - seat stuff
29 // - ext_session_lock
30 struct wlr_scene *root_scene;
31
32 // since wlr_scene nodes can't be orphaned and must always
33 // have a parent, use this staging scene_tree so that a
34 // node always have a valid parent. Nothing in this
35 // staging node will be visible.
36 struct wlr_scene_tree *staging;
37
38 struct {
39 struct wlr_scene_tree *tiling;
40 struct wlr_scene_tree *floating;
41 struct wlr_scene_tree *fullscreen;
42 struct wlr_scene_tree *fullscreen_global;
43 } layers;
44
19#if HAVE_XWAYLAND 45#if HAVE_XWAYLAND
20 struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link 46 struct wl_list xwayland_unmanaged; // sway_xwayland_unmanaged::link
21#endif 47#endif
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 822e7bb3..4aaed9e3 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -2,6 +2,7 @@
2#define _SWAY_VIEW_H 2#define _SWAY_VIEW_H
3#include <wayland-server-core.h> 3#include <wayland-server-core.h>
4#include <wlr/types/wlr_compositor.h> 4#include <wlr/types/wlr_compositor.h>
5#include <wlr/types/wlr_scene.h>
5#include "sway/config.h" 6#include "sway/config.h"
6#if HAVE_XWAYLAND 7#if HAVE_XWAYLAND
7#include <wlr/xwayland.h> 8#include <wlr/xwayland.h>
@@ -69,6 +70,9 @@ struct sway_view {
69 enum sway_view_type type; 70 enum sway_view_type type;
70 const struct sway_view_impl *impl; 71 const struct sway_view_impl *impl;
71 72
73 struct wlr_scene_tree *scene_tree;
74 struct wlr_scene_tree *content_tree;
75
72 struct sway_container *container; // NULL if unmapped and transactions finished 76 struct sway_container *container; // NULL if unmapped and transactions finished
73 struct wlr_surface *surface; // NULL for unmapped views 77 struct wlr_surface *surface; // NULL for unmapped views
74 struct sway_xdg_decoration *xdg_decoration; 78 struct sway_xdg_decoration *xdg_decoration;
diff --git a/include/sway/tree/workspace.h b/include/sway/tree/workspace.h
index b0fef4ca..58bde20c 100644
--- a/include/sway/tree/workspace.h
+++ b/include/sway/tree/workspace.h
@@ -2,6 +2,7 @@
2#define _SWAY_WORKSPACE_H 2#define _SWAY_WORKSPACE_H
3 3
4#include <stdbool.h> 4#include <stdbool.h>
5#include <wlr/types/wlr_scene.h>
5#include "sway/config.h" 6#include "sway/config.h"
6#include "sway/tree/container.h" 7#include "sway/tree/container.h"
7#include "sway/tree/node.h" 8#include "sway/tree/node.h"
@@ -23,6 +24,12 @@ struct sway_workspace_state {
23 24
24struct sway_workspace { 25struct sway_workspace {
25 struct sway_node node; 26 struct sway_node node;
27
28 struct {
29 struct wlr_scene_tree *tiling;
30 struct wlr_scene_tree *fullscreen;
31 } layers;
32
26 struct sway_container *fullscreen; 33 struct sway_container *fullscreen;
27 34
28 char *name; 35 char *name;
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 928c77d6..288ccc7c 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -856,9 +856,6 @@ void output_damage_whole_container(struct sway_output *output,
856 .height = con->current.height + 2, 856 .height = con->current.height + 2,
857 }; 857 };
858 scale_box(&box, output->wlr_output->scale); 858 scale_box(&box, output->wlr_output->scale);
859 if (wlr_damage_ring_add_box(&output->damage_ring, &box)) {
860 wlr_output_schedule_frame(output->wlr_output);
861 }
862 // Damage subsurfaces as well, which may extend outside the box 859 // Damage subsurfaces as well, which may extend outside the box
863 if (con->view) { 860 if (con->view) {
864 damage_child_views_iterator(con, output); 861 damage_child_views_iterator(con, output);
@@ -914,6 +911,8 @@ static void begin_destroy(struct sway_output *output) {
914 911
915 wlr_damage_ring_finish(&output->damage_ring); 912 wlr_damage_ring_finish(&output->damage_ring);
916 913
914 wlr_scene_output_destroy(output->scene_output);
915 output->scene_output = NULL;
917 output->wlr_output->data = NULL; 916 output->wlr_output->data = NULL;
918 output->wlr_output = NULL; 917 output->wlr_output = NULL;
919 918
@@ -1039,11 +1038,24 @@ void handle_new_output(struct wl_listener *listener, void *data) {
1039 return; 1038 return;
1040 } 1039 }
1041 1040
1041 // Create the scene output here so we're not accidentally creating one for
1042 // the fallback output
1043 struct wlr_scene_output *scene_output =
1044 wlr_scene_output_create(root->root_scene, wlr_output);
1045 if (!scene_output) {
1046 sway_log(SWAY_ERROR, "Failed to create a scene output");
1047 return;
1048 }
1049
1042 struct sway_output *output = output_create(wlr_output); 1050 struct sway_output *output = output_create(wlr_output);
1043 if (!output) { 1051 if (!output) {
1052 sway_log(SWAY_ERROR, "Failed to create a sway output");
1053 wlr_scene_output_destroy(scene_output);
1044 return; 1054 return;
1045 } 1055 }
1056
1046 output->server = server; 1057 output->server = server;
1058 output->scene_output = scene_output;
1047 wlr_damage_ring_init(&output->damage_ring); 1059 wlr_damage_ring_init(&output->damage_ring);
1048 1060
1049 wl_signal_add(&root->output_layout->events.destroy, &output->layout_destroy); 1061 wl_signal_add(&root->output_layout->events.destroy, &output->layout_destroy);
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 @@
27#include "log.h" 27#include "log.h"
28#include "stringop.h" 28#include "stringop.h"
29 29
30static struct wlr_scene_rect *alloc_rect_node(struct wlr_scene_tree *parent,
31 bool *failed) {
32 if (*failed) {
33 return NULL;
34 }
35
36 // just pass in random values. These will be overwritten when
37 // they need to be used.
38 struct wlr_scene_rect *rect = wlr_scene_rect_create(
39 parent, 0, 0, (float[4]){0.f, 0.f, 0.f, 1.f});
40 if (!rect) {
41 sway_log(SWAY_ERROR, "Failed to allocate a wlr_scene_rect");
42 *failed = true;
43 }
44
45 return rect;
46}
47
30struct sway_container *container_create(struct sway_view *view) { 48struct sway_container *container_create(struct sway_view *view) {
31 struct sway_container *c = calloc(1, sizeof(struct sway_container)); 49 struct sway_container *c = calloc(1, sizeof(struct sway_container));
32 if (!c) { 50 if (!c) {
@@ -34,14 +52,62 @@ struct sway_container *container_create(struct sway_view *view) {
34 return NULL; 52 return NULL;
35 } 53 }
36 node_init(&c->node, N_CONTAINER, c); 54 node_init(&c->node, N_CONTAINER, c);
37 c->pending.layout = L_NONE; 55
38 c->view = view; 56 // Container tree structure
39 c->alpha = 1.0f; 57 // - scene tree
58 // - title bar
59 // - border
60 // - background
61 // - title text
62 // - marks text
63 // - border
64 // - border top/bottom/left/right
65 // - content_tree (we put the content node here so when we disable the
66 // border everything gets disabled. We only render the content iff there
67 // is a border as well)
68 bool failed = false;
69 c->scene_tree = alloc_scene_tree(root->staging, &failed);
70
71 c->title_bar.tree = alloc_scene_tree(c->scene_tree, &failed);
72 c->title_bar.border = alloc_scene_tree(c->title_bar.tree, &failed);
73 c->title_bar.background = alloc_scene_tree(c->title_bar.tree, &failed);
74
75 // for opacity purposes we need to carfully create the scene such that
76 // none of our rect nodes as well as text buffers don't overlap. To do
77 // this we have to create rects such that they go around text buffers
78 for (int i = 0; i < 4; i++) {
79 alloc_rect_node(c->title_bar.border, &failed);
80 }
81
82 for (int i = 0; i < 5; i++) {
83 alloc_rect_node(c->title_bar.background, &failed);
84 }
85
86 c->border.tree = alloc_scene_tree(c->scene_tree, &failed);
87 c->content_tree = alloc_scene_tree(c->border.tree, &failed);
88
89 if (view) {
90 // only containers with views can have borders
91 c->border.top = alloc_rect_node(c->border.tree, &failed);
92 c->border.bottom = alloc_rect_node(c->border.tree, &failed);
93 c->border.left = alloc_rect_node(c->border.tree, &failed);
94 c->border.right = alloc_rect_node(c->border.tree, &failed);
95 }
96
97 if (failed) {
98 wlr_scene_node_destroy(&c->scene_tree->node);
99 free(c);
100 return NULL;
101 }
40 102
41 if (!view) { 103 if (!view) {
42 c->pending.children = create_list(); 104 c->pending.children = create_list();
43 c->current.children = create_list(); 105 c->current.children = create_list();
44 } 106 }
107
108 c->pending.layout = L_NONE;
109 c->view = view;
110 c->alpha = 1.0f;
45 c->marks = create_list(); 111 c->marks = create_list();
46 c->outputs = create_list(); 112 c->outputs = create_list();
47 113
@@ -85,6 +151,8 @@ void container_destroy(struct sway_container *con) {
85 } 151 }
86 } 152 }
87 153
154 scene_node_disown_children(con->content_tree);
155 wlr_scene_node_destroy(&con->scene_tree->node);
88 free(con); 156 free(con);
89} 157}
90 158
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) {
159 } 159 }
160 return false; 160 return false;
161} 161}
162
163void scene_node_disown_children(struct wlr_scene_tree *tree) {
164 // this function can be called as part of destruction code that will be invoked
165 // upon an allocation failure. Let's not crash on NULL due to an allocation error.
166 if (!tree) {
167 return;
168 }
169
170 struct wlr_scene_node *child, *tmp_child;
171 wl_list_for_each_safe(child, tmp_child, &tree->children, link) {
172 wlr_scene_node_reparent(child, root->staging);
173 }
174}
175
176struct wlr_scene_tree *alloc_scene_tree(struct wlr_scene_tree *parent,
177 bool *failed) {
178 // fallthrough
179 if (*failed) {
180 return NULL;
181 }
182
183 struct wlr_scene_tree *tree = wlr_scene_tree_create(parent);
184 if (!tree) {
185 sway_log(SWAY_ERROR, "Failed to allocate a scene node");
186 *failed = true;
187 }
188
189 return tree;
190}
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) {
87 output_sort_workspaces(output); 87 output_sort_workspaces(output);
88} 88}
89 89
90static void destroy_scene_layers(struct sway_output *output) {
91 wlr_scene_node_destroy(&output->fullscreen_background->node);
92
93 scene_node_disown_children(output->layers.tiling);
94 scene_node_disown_children(output->layers.fullscreen);
95
96 wlr_scene_node_destroy(&output->layers.tiling->node);
97 wlr_scene_node_destroy(&output->layers.fullscreen->node);
98}
99
90struct sway_output *output_create(struct wlr_output *wlr_output) { 100struct sway_output *output_create(struct wlr_output *wlr_output) {
91 struct sway_output *output = calloc(1, sizeof(struct sway_output)); 101 struct sway_output *output = calloc(1, sizeof(struct sway_output));
92 node_init(&output->node, N_OUTPUT, output); 102 node_init(&output->node, N_OUTPUT, output);
103
104 bool failed = false;
105 output->layers.tiling = alloc_scene_tree(root->staging, &failed);
106 output->layers.fullscreen = alloc_scene_tree(root->staging, &failed);
107
108 if (!failed) {
109 output->fullscreen_background = wlr_scene_rect_create(
110 output->layers.fullscreen, 0, 0, (float[4]){0.f, 0.f, 0.f, 1.f});
111
112 if (!output->fullscreen_background) {
113 sway_log(SWAY_ERROR, "Unable to allocate a background rect");
114 failed = true;
115 }
116 }
117
118 if (failed) {
119 destroy_scene_layers(output);
120 wlr_scene_output_destroy(output->scene_output);
121 free(output);
122 return NULL;
123 }
124
93 output->wlr_output = wlr_output; 125 output->wlr_output = wlr_output;
94 wlr_output->data = output; 126 wlr_output->data = output;
95 output->detected_subpixel = wlr_output->subpixel; 127 output->detected_subpixel = wlr_output->subpixel;
@@ -238,6 +270,8 @@ void output_destroy(struct sway_output *output) {
238 "which is still referenced by transactions")) { 270 "which is still referenced by transactions")) {
239 return; 271 return;
240 } 272 }
273
274 destroy_scene_layers(output);
241 list_free(output->workspaces); 275 list_free(output->workspaces);
242 list_free(output->current.workspaces); 276 list_free(output->current.workspaces);
243 wl_event_source_remove(output->repaint_timer); 277 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 @@
3#include <stdlib.h> 3#include <stdlib.h>
4#include <string.h> 4#include <string.h>
5#include <wlr/types/wlr_output_layout.h> 5#include <wlr/types/wlr_output_layout.h>
6#include <wlr/types/wlr_scene.h>
6#include <wlr/util/transform.h> 7#include <wlr/util/transform.h>
7#include "sway/desktop/transaction.h" 8#include "sway/desktop/transaction.h"
8#include "sway/input/seat.h" 9#include "sway/input/seat.h"
@@ -30,7 +31,33 @@ struct sway_root *root_create(struct wl_display *wl_display) {
30 sway_log(SWAY_ERROR, "Unable to allocate sway_root"); 31 sway_log(SWAY_ERROR, "Unable to allocate sway_root");
31 return NULL; 32 return NULL;
32 } 33 }
34
35 struct wlr_scene *root_scene = wlr_scene_create();
36 if (!root_scene) {
37 sway_log(SWAY_ERROR, "Unable to allocate root scene node");
38 free(root);
39 return NULL;
40 }
41
33 node_init(&root->node, N_ROOT, root); 42 node_init(&root->node, N_ROOT, root);
43 root->root_scene = root_scene;
44
45 bool failed = false;
46 root->staging = alloc_scene_tree(&root_scene->tree, &failed);
47
48 root->layers.tiling = alloc_scene_tree(&root_scene->tree, &failed);
49 root->layers.floating = alloc_scene_tree(&root_scene->tree, &failed);
50 root->layers.fullscreen = alloc_scene_tree(&root_scene->tree, &failed);
51 root->layers.fullscreen_global = alloc_scene_tree(&root_scene->tree, &failed);
52
53 if (failed) {
54 wlr_scene_node_destroy(&root_scene->tree.node);
55 free(root);
56 return NULL;
57 }
58
59 wlr_scene_node_set_enabled(&root->staging->node, false);
60
34 root->output_layout = wlr_output_layout_create(wl_display); 61 root->output_layout = wlr_output_layout_create(wl_display);
35 wl_list_init(&root->all_outputs); 62 wl_list_init(&root->all_outputs);
36#if HAVE_XWAYLAND 63#if HAVE_XWAYLAND
@@ -53,6 +80,7 @@ void root_destroy(struct sway_root *root) {
53 list_free(root->scratchpad); 80 list_free(root->scratchpad);
54 list_free(root->non_desktop_outputs); 81 list_free(root->non_desktop_outputs);
55 list_free(root->outputs); 82 list_free(root->outputs);
83 wlr_scene_node_destroy(&root->root_scene->tree.node);
56 free(root); 84 free(root);
57} 85}
58 86
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 @@
37 37
38bool view_init(struct sway_view *view, enum sway_view_type type, 38bool view_init(struct sway_view *view, enum sway_view_type type,
39 const struct sway_view_impl *impl) { 39 const struct sway_view_impl *impl) {
40 bool failed = false;
41 view->scene_tree = alloc_scene_tree(root->staging, &failed);
42 view->content_tree = alloc_scene_tree(view->scene_tree, &failed);
43 if (failed) {
44 wlr_scene_node_destroy(&view->scene_tree->node);
45 return false;
46 }
47
40 view->type = type; 48 view->type = type;
41 view->impl = impl; 49 view->impl = impl;
42 view->executed_criteria = create_list(); 50 view->executed_criteria = create_list();
@@ -67,7 +75,7 @@ void view_destroy(struct sway_view *view) {
67 list_free(view->executed_criteria); 75 list_free(view->executed_criteria);
68 76
69 view_assign_ctx(view, NULL); 77 view_assign_ctx(view, NULL);
70 78 wlr_scene_node_destroy(&view->scene_tree->node);
71 free(view->title_format); 79 free(view->title_format);
72 80
73 if (view->impl->destroy) { 81 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,
71 return NULL; 71 return NULL;
72 } 72 }
73 node_init(&ws->node, N_WORKSPACE, ws); 73 node_init(&ws->node, N_WORKSPACE, ws);
74
75 bool failed = false;
76 ws->layers.tiling = alloc_scene_tree(root->staging, &failed);
77 ws->layers.fullscreen = alloc_scene_tree(root->staging, &failed);
78
79 if (failed) {
80 wlr_scene_node_destroy(&ws->layers.tiling->node);
81 wlr_scene_node_destroy(&ws->layers.fullscreen->node);
82 free(ws);
83 return NULL;
84 }
85
74 ws->name = strdup(name); 86 ws->name = strdup(name);
75 ws->prev_split_layout = L_NONE; 87 ws->prev_split_layout = L_NONE;
76 ws->layout = output_get_default_layout(output); 88 ws->layout = output_get_default_layout(output);
@@ -131,6 +143,11 @@ void workspace_destroy(struct sway_workspace *workspace) {
131 return; 143 return;
132 } 144 }
133 145
146 scene_node_disown_children(workspace->layers.tiling);
147 scene_node_disown_children(workspace->layers.fullscreen);
148 wlr_scene_node_destroy(&workspace->layers.tiling->node);
149 wlr_scene_node_destroy(&workspace->layers.fullscreen->node);
150
134 free(workspace->name); 151 free(workspace->name);
135 free(workspace->representation); 152 free(workspace->representation);
136 list_free_items_and_destroy(workspace->output_priority); 153 list_free_items_and_destroy(workspace->output_priority);