scene: Allow orphaned nodes

This commit is contained in:
Ben Mather 2024-01-20 09:55:28 +00:00
parent c752270be7
commit f7dbf5dceb
2 changed files with 44 additions and 20 deletions

View file

@ -91,6 +91,8 @@ struct wlr_scene_tree {
struct wlr_scene_node node;
struct wl_list children; // wlr_scene_node.link
bool is_root;
};
/** The root scene-graph node. */

View file

@ -59,6 +59,11 @@ struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) {
while (tree->node.parent != NULL) {
tree = tree->node.parent;
}
if (!tree->is_root) {
return NULL;
}
struct wlr_scene *scene = wl_container_of(tree, scene, tree);
return scene;
}
@ -111,11 +116,11 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
if (node->type == WLR_SCENE_NODE_BUFFER) {
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
uint64_t active = scene_buffer->active_outputs;
if (active) {
uint64_t active_outputs = scene_buffer->active_outputs;
if (scene != NULL && active_outputs) {
struct wlr_scene_output *scene_output;
wl_list_for_each(scene_output, &scene->outputs, link) {
if (active & (1ull << scene_output->index)) {
if (active_outputs & (1ull << scene_output->index)) {
wl_signal_emit_mutable(&scene_buffer->events.output_leave,
scene_output);
}
@ -139,8 +144,6 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
wl_list_remove(&scene->linux_dmabuf_v1_destroy.link);
wl_list_remove(&scene->gamma_control_manager_v1_destroy.link);
wl_list_remove(&scene->gamma_control_manager_v1_set_gamma.link);
} else {
assert(node->parent);
}
struct wlr_scene_node *child, *child_tmp;
@ -149,8 +152,9 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
wlr_scene_node_destroy(child);
}
}
wl_list_remove(&node->link);
if (node->parent != NULL) {
wl_list_remove(&node->link);
}
pixman_region32_fini(&node->visible);
free(node);
}
@ -169,6 +173,7 @@ struct wlr_scene *wlr_scene_create(void) {
}
scene_tree_init(&scene->tree, NULL);
scene->tree.is_root = true;
wl_list_init(&scene->outputs);
wl_list_init(&scene->linux_dmabuf_v1_destroy.link);
@ -191,8 +196,6 @@ struct wlr_scene *wlr_scene_create(void) {
}
struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) {
assert(parent);
struct wlr_scene_tree *tree = calloc(1, sizeof(*tree));
if (tree == NULL) {
return NULL;
@ -654,6 +657,9 @@ static void scene_update_region(struct wlr_scene *scene,
static void scene_node_update(struct wlr_scene_node *node,
pixman_region32_t *damage) {
struct wlr_scene *scene = scene_node_get_root(node);
if (scene == NULL) {
return;
}
int x, y;
if (!wlr_scene_node_coords(node, &x, &y)) {
@ -804,7 +810,6 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent,
if (scene_buffer == NULL) {
return NULL;
}
assert(parent);
scene_node_init(&scene_buffer->node, WLR_SCENE_NODE_BUFFER, parent);
wl_signal_init(&scene_buffer->events.outputs_update);
@ -1139,6 +1144,7 @@ void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) {
void wlr_scene_node_place_above(struct wlr_scene_node *node,
struct wlr_scene_node *sibling) {
assert(node != sibling);
assert(node->parent);
assert(node->parent == sibling->parent);
if (node->link.prev == &sibling->link) {
@ -1153,6 +1159,7 @@ void wlr_scene_node_place_above(struct wlr_scene_node *node,
void wlr_scene_node_place_below(struct wlr_scene_node *node,
struct wlr_scene_node *sibling) {
assert(node != sibling);
assert(node->parent);
assert(node->parent == sibling->parent);
if (node->link.next == &sibling->link) {
@ -1165,6 +1172,7 @@ void wlr_scene_node_place_below(struct wlr_scene_node *node,
}
void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) {
assert(node->parent);
struct wlr_scene_node *current_top = wl_container_of(
node->parent->children.prev, current_top, link);
if (node == current_top) {
@ -1174,6 +1182,7 @@ void wlr_scene_node_raise_to_top(struct wlr_scene_node *node) {
}
void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node) {
assert(node->parent);
struct wlr_scene_node *current_bottom = wl_container_of(
node->parent->children.next, current_bottom, link);
if (node == current_bottom) {
@ -1184,8 +1193,6 @@ void wlr_scene_node_lower_to_bottom(struct wlr_scene_node *node) {
void wlr_scene_node_reparent(struct wlr_scene_node *node,
struct wlr_scene_tree *new_parent) {
assert(new_parent != NULL);
if (node->parent == new_parent) {
return;
}
@ -1196,17 +1203,31 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node,
assert(&ancestor->node != node);
}
int x, y;
pixman_region32_t visible;
pixman_region32_init(&visible);
if (wlr_scene_node_coords(node, &x, &y)) {
scene_node_visibility(node, &visible);
if (node->parent != NULL) {
int x, y;
pixman_region32_t visible;
pixman_region32_init(&visible);
if (wlr_scene_node_coords(node, &x, &y)) {
scene_node_visibility(node, &visible);
}
scene_node_update(node, &visible);
wl_list_remove(&node->link);
}
wl_list_remove(&node->link);
node->parent = new_parent;
wl_list_insert(new_parent->children.prev, &node->link);
scene_node_update(node, &visible);
if (node->parent != NULL) {
wl_list_insert(new_parent->children.prev, &node->link);
int x, y;
pixman_region32_t visible;
pixman_region32_init(&visible);
if (wlr_scene_node_coords(node, &x, &y)) {
scene_node_visibility(node, &visible);
}
scene_node_update(node, &visible);
}
}
bool wlr_scene_node_coords(struct wlr_scene_node *node,
@ -1220,6 +1241,7 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node,
ly += node->y;
enabled = enabled && node->enabled;
if (node->parent == NULL) {
enabled = enabled && (scene_node_get_root(node) != NULL);
break;
}