diff options
author | Alexander Orzechowski <alex@ozal.ski> | 2024-01-18 10:00:45 -0500 |
---|---|---|
committer | Kirill Primak <vyivel@eclair.cafe> | 2024-01-18 18:36:54 +0300 |
commit | 1eb16d136774c8fb3c9085df45156264f0db8814 (patch) | |
tree | 9c348ab37edae50b76a388d7e8d8dcd011cea33b | |
parent | view: init function should return a success bool (diff) | |
download | sway-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.h | 15 | ||||
-rw-r--r-- | include/sway/tree/container.h | 21 | ||||
-rw-r--r-- | include/sway/tree/node.h | 12 | ||||
-rw-r--r-- | include/sway/tree/root.h | 26 | ||||
-rw-r--r-- | include/sway/tree/view.h | 4 | ||||
-rw-r--r-- | include/sway/tree/workspace.h | 7 | ||||
-rw-r--r-- | sway/desktop/output.c | 18 | ||||
-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 |
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 | ||
20 | struct sway_output { | 21 | struct 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 | ||
76 | bool node_has_ancestor(struct sway_node *node, struct sway_node *ancestor); | 77 | bool 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. | ||
82 | void 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. | ||
87 | struct 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 | ||
24 | struct sway_workspace { | 25 | struct 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 | ||
30 | static 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 | |||
30 | struct sway_container *container_create(struct sway_view *view) { | 48 | struct 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 | |||
163 | void 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 | |||
176 | struct 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 | ||
90 | static 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 | |||
90 | struct sway_output *output_create(struct wlr_output *wlr_output) { | 100 | struct 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 | ||
38 | bool view_init(struct sway_view *view, enum sway_view_type type, | 38 | bool 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); |