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 /sway/tree | |
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.
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 @@ | |||
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); |