From a093049ec6c44b4f005cd598814bf438634cf6c2 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 12:26:41 -0400 Subject: [PATCH 1/8] wlr_scene: Rename wlr_scene_subsurface_tree with _surface suffix This struct doesn't represent the entire tree, it represents just a surface. --- types/scene/subsurface_tree.c | 56 +++++++++++++++++------------------ 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index 4e0a3f999..c4a5a1d54 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -11,7 +11,7 @@ * * `tree` contains `scene_surface` and one node per sub-surface. */ -struct wlr_scene_subsurface_tree { +struct wlr_scene_subsurface_tree_surface { struct wlr_scene_tree *tree; struct wlr_surface *surface; struct wlr_scene_surface *scene_surface; @@ -22,7 +22,7 @@ struct wlr_scene_subsurface_tree { struct wl_listener surface_unmap; struct wl_listener surface_new_subsurface; - struct wlr_scene_subsurface_tree *parent; // NULL for the top-level surface + struct wlr_scene_subsurface_tree_surface *parent; // NULL for the top-level surface struct wlr_addon scene_addon; @@ -36,7 +36,7 @@ struct wlr_scene_subsurface_tree { }; static void subsurface_tree_addon_destroy(struct wlr_addon *addon) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(addon, subsurface_tree, scene_addon); // tree and scene_surface will be cleaned up by scene_node_finish if (subsurface_tree->parent) { @@ -54,19 +54,19 @@ static void subsurface_tree_addon_destroy(struct wlr_addon *addon) { static const struct wlr_addon_interface subsurface_tree_surface_addon_impl; -static struct wlr_scene_subsurface_tree *subsurface_tree_from_subsurface( - struct wlr_scene_subsurface_tree *parent, +static struct wlr_scene_subsurface_tree_surface *subsurface_tree_from_subsurface( + struct wlr_scene_subsurface_tree_surface *parent, struct wlr_subsurface *subsurface) { struct wlr_addon *addon = wlr_addon_find(&subsurface->surface->addons, parent, &subsurface_tree_surface_addon_impl); assert(addon != NULL); - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(addon, subsurface_tree, surface_addon); return subsurface_tree; } static bool subsurface_tree_reconfigure_clip( - struct wlr_scene_subsurface_tree *subsurface_tree) { + struct wlr_scene_subsurface_tree_surface *subsurface_tree) { if (subsurface_tree->parent) { subsurface_tree->clip = (struct wlr_box){ .x = subsurface_tree->parent->clip.x - subsurface_tree->tree->node.x, @@ -102,7 +102,7 @@ static bool subsurface_tree_reconfigure_clip( } static void subsurface_tree_reconfigure( - struct wlr_scene_subsurface_tree *subsurface_tree) { + struct wlr_scene_subsurface_tree_surface *subsurface_tree) { bool has_clip = subsurface_tree_reconfigure_clip(subsurface_tree); struct wlr_surface *surface = subsurface_tree->surface; @@ -111,7 +111,7 @@ static void subsurface_tree_reconfigure( struct wlr_subsurface *subsurface; wl_list_for_each(subsurface, &surface->current.subsurfaces_below, current.link) { - struct wlr_scene_subsurface_tree *child = + struct wlr_scene_subsurface_tree_surface *child = subsurface_tree_from_subsurface(subsurface_tree, subsurface); if (prev != NULL) { wlr_scene_node_place_above(&child->tree->node, prev); @@ -133,7 +133,7 @@ static void subsurface_tree_reconfigure( wl_list_for_each(subsurface, &surface->current.subsurfaces_above, current.link) { - struct wlr_scene_subsurface_tree *child = + struct wlr_scene_subsurface_tree_surface *child = subsurface_tree_from_subsurface(subsurface_tree, subsurface); wlr_scene_node_place_above(&child->tree->node, prev); prev = &child->tree->node; @@ -149,14 +149,14 @@ static void subsurface_tree_reconfigure( static void subsurface_tree_handle_surface_destroy(struct wl_listener *listener, void *data) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(listener, subsurface_tree, surface_destroy); wlr_scene_node_destroy(&subsurface_tree->tree->node); } static void subsurface_tree_handle_surface_commit(struct wl_listener *listener, void *data) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(listener, subsurface_tree, surface_commit); // TODO: only do this on subsurface order or position change @@ -165,14 +165,14 @@ static void subsurface_tree_handle_surface_commit(struct wl_listener *listener, static void subsurface_tree_handle_subsurface_destroy(struct wl_listener *listener, void *data) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(listener, subsurface_tree, subsurface_destroy); wlr_scene_node_destroy(&subsurface_tree->tree->node); } static void subsurface_tree_handle_surface_map(struct wl_listener *listener, void *data) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(listener, subsurface_tree, surface_map); wlr_scene_node_set_enabled(&subsurface_tree->tree->node, true); @@ -180,30 +180,30 @@ static void subsurface_tree_handle_surface_map(struct wl_listener *listener, static void subsurface_tree_handle_surface_unmap(struct wl_listener *listener, void *data) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(listener, subsurface_tree, surface_unmap); wlr_scene_node_set_enabled(&subsurface_tree->tree->node, false); } static void subsurface_tree_surface_addon_destroy(struct wlr_addon *addon) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(addon, subsurface_tree, surface_addon); wlr_scene_node_destroy(&subsurface_tree->tree->node); } static const struct wlr_addon_interface subsurface_tree_surface_addon_impl = { - .name = "wlr_scene_subsurface_tree", + .name = "wlr_scene_subsurface_tree_surface", .destroy = subsurface_tree_surface_addon_destroy, }; -static struct wlr_scene_subsurface_tree *scene_surface_tree_create( +static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create( struct wlr_scene_tree *parent, struct wlr_surface *surface); static bool subsurface_tree_create_subsurface( - struct wlr_scene_subsurface_tree *parent, + struct wlr_scene_subsurface_tree_surface *parent, struct wlr_subsurface *subsurface) { - struct wlr_scene_subsurface_tree *child = scene_surface_tree_create( + struct wlr_scene_subsurface_tree_surface *child = scene_surface_tree_create( parent->tree, subsurface->surface); if (child == NULL) { return false; @@ -222,7 +222,7 @@ static bool subsurface_tree_create_subsurface( static void subsurface_tree_handle_surface_new_subsurface( struct wl_listener *listener, void *data) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(listener, subsurface_tree, surface_new_subsurface); struct wlr_subsurface *subsurface = data; if (!subsurface_tree_create_subsurface(subsurface_tree, subsurface)) { @@ -231,13 +231,13 @@ static void subsurface_tree_handle_surface_new_subsurface( } static const struct wlr_addon_interface subsurface_tree_addon_impl = { - .name = "wlr_scene_subsurface_tree", + .name = "wlr_scene_subsurface_tree_surface", .destroy = subsurface_tree_addon_destroy, }; -static struct wlr_scene_subsurface_tree *scene_surface_tree_create( +static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create( struct wlr_scene_tree *parent, struct wlr_surface *surface) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = calloc(1, sizeof(*subsurface_tree)); if (subsurface_tree == NULL) { return NULL; @@ -305,7 +305,7 @@ error_surface_tree: struct wlr_scene_tree *wlr_scene_subsurface_tree_create( struct wlr_scene_tree *parent, struct wlr_surface *surface) { - struct wlr_scene_subsurface_tree *subsurface_tree = + struct wlr_scene_subsurface_tree_surface *subsurface_tree = scene_surface_tree_create(parent, surface); if (subsurface_tree == NULL) { return NULL; @@ -313,14 +313,14 @@ struct wlr_scene_tree *wlr_scene_subsurface_tree_create( return subsurface_tree->tree; } -static struct wlr_scene_subsurface_tree *get_subsurface_tree_from_node( +static struct wlr_scene_subsurface_tree_surface *get_subsurface_tree_from_node( struct wlr_scene_node *node) { struct wlr_addon *addon = wlr_addon_find(&node->addons, NULL, &subsurface_tree_addon_impl); if (!addon) { return NULL; } - struct wlr_scene_subsurface_tree *tree = + struct wlr_scene_subsurface_tree_surface *tree = wl_container_of(addon, tree, scene_addon); return tree; } @@ -332,7 +332,7 @@ static bool subsurface_tree_set_clip(struct wlr_scene_node *node, } bool discovered_subsurface_tree = false; - struct wlr_scene_subsurface_tree *tree = get_subsurface_tree_from_node(node); + struct wlr_scene_subsurface_tree_surface *tree = get_subsurface_tree_from_node(node); if (tree) { if (tree->parent == NULL) { if (wlr_box_equal(&tree->clip, clip)) { From 1901c34e819deedc7ef66dae08f8cada2754db0e Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 12:40:44 -0400 Subject: [PATCH 2/8] wlr_scene: Introduce struct wlr_scene_subsurface_tree --- include/wlr/types/wlr_scene.h | 6 +++++- types/scene/drag_icon.c | 4 ++-- types/scene/layer_shell_v1.c | 2 +- types/scene/subsurface_tree.c | 32 +++++++++++++++++++++++--------- types/scene/xdg_shell.c | 4 ++-- 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index a8fc21595..85587a380 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -131,6 +131,10 @@ struct wlr_scene_surface { struct wl_listener surface_commit; }; +struct wlr_scene_subsurface_tree { + struct wlr_scene_tree *tree; +}; + /** A scene-graph node displaying a solid-colored rectangle */ struct wlr_scene_rect { struct wlr_scene_node node; @@ -547,7 +551,7 @@ void wlr_scene_output_layout_add_output(struct wlr_scene_output_layout *sol, * Add a node displaying a surface and all of its sub-surfaces to the * scene-graph. */ -struct wlr_scene_tree *wlr_scene_subsurface_tree_create( +struct wlr_scene_subsurface_tree *wlr_scene_subsurface_tree_create( struct wlr_scene_tree *parent, struct wlr_surface *surface); /** diff --git a/types/scene/drag_icon.c b/types/scene/drag_icon.c index 84b202c3d..91c5866ec 100644 --- a/types/scene/drag_icon.c +++ b/types/scene/drag_icon.c @@ -5,7 +5,7 @@ struct wlr_scene_drag_icon { struct wlr_scene_tree *tree; - struct wlr_scene_tree *surface_tree; + struct wlr_scene_subsurface_tree *surface_tree; struct wlr_drag_icon *drag_icon; struct wl_listener tree_destroy; @@ -17,7 +17,7 @@ static void drag_icon_handle_surface_commit(struct wl_listener *listener, void * struct wlr_scene_drag_icon *icon = wl_container_of(listener, icon, drag_icon_surface_commit); struct wlr_surface *surface = icon->drag_icon->surface; - struct wlr_scene_node *node = &icon->surface_tree->node; + struct wlr_scene_node *node = &icon->surface_tree->tree->node; wlr_scene_node_set_position(node, node->x + surface->current.dx, node->y + surface->current.dy); } diff --git a/types/scene/layer_shell_v1.c b/types/scene/layer_shell_v1.c index 4ae736ddf..bf34256eb 100644 --- a/types/scene/layer_shell_v1.c +++ b/types/scene/layer_shell_v1.c @@ -142,7 +142,7 @@ struct wlr_scene_layer_surface_v1 *wlr_scene_layer_surface_v1_create( return NULL; } - struct wlr_scene_tree *surface_tree = wlr_scene_subsurface_tree_create( + struct wlr_scene_subsurface_tree *surface_tree = wlr_scene_subsurface_tree_create( scene_layer_surface->tree, layer_surface->surface); if (surface_tree == NULL) { wlr_scene_node_destroy(&scene_layer_surface->tree->node); diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index c4a5a1d54..c165ece87 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -15,6 +15,7 @@ struct wlr_scene_subsurface_tree_surface { struct wlr_scene_tree *tree; struct wlr_surface *surface; struct wlr_scene_surface *scene_surface; + struct wlr_scene_subsurface_tree *subsurface_tree; struct wl_listener surface_destroy; struct wl_listener surface_commit; @@ -42,6 +43,8 @@ static void subsurface_tree_addon_destroy(struct wlr_addon *addon) { if (subsurface_tree->parent) { wlr_addon_finish(&subsurface_tree->surface_addon); wl_list_remove(&subsurface_tree->subsurface_destroy.link); + } else { + free(subsurface_tree->subsurface_tree); } wlr_addon_finish(&subsurface_tree->scene_addon); wl_list_remove(&subsurface_tree->surface_destroy.link); @@ -197,14 +200,15 @@ static const struct wlr_addon_interface subsurface_tree_surface_addon_impl = { .destroy = subsurface_tree_surface_addon_destroy, }; -static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create( +static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surface( + struct wlr_scene_subsurface_tree *tree, struct wlr_scene_tree *parent, struct wlr_surface *surface); static bool subsurface_tree_create_subsurface( struct wlr_scene_subsurface_tree_surface *parent, struct wlr_subsurface *subsurface) { - struct wlr_scene_subsurface_tree_surface *child = scene_surface_tree_create( - parent->tree, subsurface->surface); + struct wlr_scene_subsurface_tree_surface *child = scene_surface_tree_create_surface( + parent->subsurface_tree, parent->tree, subsurface->surface); if (child == NULL) { return false; } @@ -235,7 +239,8 @@ static const struct wlr_addon_interface subsurface_tree_addon_impl = { .destroy = subsurface_tree_addon_destroy, }; -static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create( +static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surface( + struct wlr_scene_subsurface_tree *tree, struct wlr_scene_tree *parent, struct wlr_surface *surface) { struct wlr_scene_subsurface_tree_surface *subsurface_tree = calloc(1, sizeof(*subsurface_tree)); @@ -243,6 +248,7 @@ static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create( return NULL; } + subsurface_tree->subsurface_tree = tree; subsurface_tree->tree = wlr_scene_tree_create(parent); if (subsurface_tree->tree == NULL) { goto error_surface_tree; @@ -303,14 +309,22 @@ error_surface_tree: return NULL; } -struct wlr_scene_tree *wlr_scene_subsurface_tree_create( +struct wlr_scene_subsurface_tree *wlr_scene_subsurface_tree_create( struct wlr_scene_tree *parent, struct wlr_surface *surface) { - struct wlr_scene_subsurface_tree_surface *subsurface_tree = - scene_surface_tree_create(parent, surface); - if (subsurface_tree == NULL) { + struct wlr_scene_subsurface_tree *subsurface_tree = calloc(1, sizeof(*subsurface_tree)); + if (!subsurface_tree) { return NULL; } - return subsurface_tree->tree; + + struct wlr_scene_subsurface_tree_surface *subsurface_tree_surface = + scene_surface_tree_create_surface(subsurface_tree, parent, surface); + if (subsurface_tree_surface == NULL) { + free(subsurface_tree); + return NULL; + } + + subsurface_tree->tree = subsurface_tree_surface->tree; + return subsurface_tree; } static struct wlr_scene_subsurface_tree_surface *get_subsurface_tree_from_node( diff --git a/types/scene/xdg_shell.c b/types/scene/xdg_shell.c index ed792633d..f9668f933 100644 --- a/types/scene/xdg_shell.c +++ b/types/scene/xdg_shell.c @@ -5,7 +5,7 @@ struct wlr_scene_xdg_surface { struct wlr_scene_tree *tree; struct wlr_xdg_surface *xdg_surface; - struct wlr_scene_tree *surface_tree; + struct wlr_scene_subsurface_tree *surface_tree; struct wl_listener tree_destroy; struct wl_listener xdg_surface_destroy; @@ -36,7 +36,7 @@ static void scene_xdg_surface_update_position( struct wlr_box geo = {0}; wlr_xdg_surface_get_geometry(xdg_surface, &geo); - wlr_scene_node_set_position(&scene_xdg_surface->surface_tree->node, + wlr_scene_node_set_position(&scene_xdg_surface->surface_tree->tree->node, -geo.x, -geo.y); if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { From 3a997b74542ead7799248e06a957e0b8a1959bcd Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 12:46:27 -0400 Subject: [PATCH 3/8] wlr_scene: Keep track of all surfaces for subsurface_tree --- include/wlr/types/wlr_scene.h | 4 ++++ types/scene/subsurface_tree.c | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 85587a380..c1b4b6345 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -133,6 +133,10 @@ struct wlr_scene_surface { struct wlr_scene_subsurface_tree { struct wlr_scene_tree *tree; + + // private state + + struct wl_list surfaces; }; /** A scene-graph node displaying a solid-colored rectangle */ diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index c165ece87..e7ba5bbb0 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -28,6 +28,7 @@ struct wlr_scene_subsurface_tree_surface { struct wlr_addon scene_addon; struct wlr_box clip; + struct wl_list link; // Only valid if the surface is a sub-surface @@ -52,6 +53,7 @@ static void subsurface_tree_addon_destroy(struct wlr_addon *addon) { wl_list_remove(&subsurface_tree->surface_map.link); wl_list_remove(&subsurface_tree->surface_unmap.link); wl_list_remove(&subsurface_tree->surface_new_subsurface.link); + wl_list_remove(&subsurface_tree->link); free(subsurface_tree); } @@ -276,6 +278,7 @@ static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surfa } } + wl_list_insert(&tree->surfaces, &subsurface_tree->link); subsurface_tree_reconfigure(subsurface_tree); wlr_addon_init(&subsurface_tree->scene_addon, &subsurface_tree->tree->node.addons, @@ -316,6 +319,8 @@ struct wlr_scene_subsurface_tree *wlr_scene_subsurface_tree_create( return NULL; } + wl_list_init(&subsurface_tree->surfaces); + struct wlr_scene_subsurface_tree_surface *subsurface_tree_surface = scene_surface_tree_create_surface(subsurface_tree, parent, surface); if (subsurface_tree_surface == NULL) { From 9be258994deba79dc97f31940bdc4e5a2bd562c5 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 13:13:52 -0400 Subject: [PATCH 4/8] wlr_scene: wlr_scene_subsurface_tree_set_clip takes struct wlr_scene_subsurface_tree --- include/wlr/types/wlr_scene.h | 4 ++- types/scene/subsurface_tree.c | 61 ++++++++--------------------------- 2 files changed, 16 insertions(+), 49 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index c1b4b6345..4568c670a 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -131,12 +131,14 @@ struct wlr_scene_surface { struct wl_listener surface_commit; }; +struct wlr_scene_subsurface_tree_surface; struct wlr_scene_subsurface_tree { struct wlr_scene_tree *tree; // private state struct wl_list surfaces; + struct wlr_scene_subsurface_tree_surface *root; }; /** A scene-graph node displaying a solid-colored rectangle */ @@ -565,7 +567,7 @@ struct wlr_scene_subsurface_tree *wlr_scene_subsurface_tree_create( * * A NULL or empty clip will disable clipping */ -void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_node *node, +void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_subsurface_tree *tree, const struct wlr_box *clip); /** diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index e7ba5bbb0..494d07e13 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -328,62 +328,27 @@ struct wlr_scene_subsurface_tree *wlr_scene_subsurface_tree_create( return NULL; } + subsurface_tree->root = subsurface_tree_surface; subsurface_tree->tree = subsurface_tree_surface->tree; return subsurface_tree; } -static struct wlr_scene_subsurface_tree_surface *get_subsurface_tree_from_node( - struct wlr_scene_node *node) { - struct wlr_addon *addon = wlr_addon_find(&node->addons, NULL, &subsurface_tree_addon_impl); - if (!addon) { - return NULL; - } - - struct wlr_scene_subsurface_tree_surface *tree = - wl_container_of(addon, tree, scene_addon); - return tree; -} - -static bool subsurface_tree_set_clip(struct wlr_scene_node *node, +void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_subsurface_tree *tree, const struct wlr_box *clip) { - if (node->type != WLR_SCENE_NODE_TREE) { - return false; + if (wlr_box_equal(&tree->root->clip, clip)) { + return; } - bool discovered_subsurface_tree = false; - struct wlr_scene_subsurface_tree_surface *tree = get_subsurface_tree_from_node(node); - if (tree) { - if (tree->parent == NULL) { - if (wlr_box_equal(&tree->clip, clip)) { - return true; - } - - if (clip) { - tree->clip = *clip; - } else { - tree->clip = (struct wlr_box){0}; - } - } - - discovered_subsurface_tree = true; - subsurface_tree_reconfigure_clip(tree); + if (clip) { + tree->root->clip = *clip; + } else { + tree->root->clip = (struct wlr_box){0}; } - struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node); - struct wlr_scene_node *child; - wl_list_for_each(child, &scene_tree->children, link) { - discovered_subsurface_tree |= subsurface_tree_set_clip(child, clip); + // iterate in reverse because children of parent subsurface will appear + // earlier in the list. + struct wlr_scene_subsurface_tree_surface *surface; + wl_list_for_each_reverse(surface, &tree->surfaces, link) { + subsurface_tree_reconfigure_clip(surface); } - - return discovered_subsurface_tree; -} - -void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_node *node, - const struct wlr_box *clip) { -#ifndef NDEBUG - bool found = -#endif - subsurface_tree_set_clip(node, clip); - - assert(found); } From 327ae353070efc45db613700147fb822f0e4aad9 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 13:12:32 -0400 Subject: [PATCH 5/8] wlr_scene: Stop using addon to scene for subsurface_tree Not needed anymore --- types/scene/subsurface_tree.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index 494d07e13..840f70e6d 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -22,11 +22,10 @@ struct wlr_scene_subsurface_tree_surface { struct wl_listener surface_map; struct wl_listener surface_unmap; struct wl_listener surface_new_subsurface; + struct wl_listener scene_destroy; struct wlr_scene_subsurface_tree_surface *parent; // NULL for the top-level surface - struct wlr_addon scene_addon; - struct wlr_box clip; struct wl_list link; @@ -37,9 +36,9 @@ struct wlr_scene_subsurface_tree_surface { struct wl_listener subsurface_destroy; }; -static void subsurface_tree_addon_destroy(struct wlr_addon *addon) { +static void subsurface_tree_handle_scene_destroy(struct wl_listener *listener, void *data) { struct wlr_scene_subsurface_tree_surface *subsurface_tree = - wl_container_of(addon, subsurface_tree, scene_addon); + wl_container_of(listener, subsurface_tree, scene_destroy); // tree and scene_surface will be cleaned up by scene_node_finish if (subsurface_tree->parent) { wlr_addon_finish(&subsurface_tree->surface_addon); @@ -47,12 +46,12 @@ static void subsurface_tree_addon_destroy(struct wlr_addon *addon) { } else { free(subsurface_tree->subsurface_tree); } - wlr_addon_finish(&subsurface_tree->scene_addon); wl_list_remove(&subsurface_tree->surface_destroy.link); wl_list_remove(&subsurface_tree->surface_commit.link); wl_list_remove(&subsurface_tree->surface_map.link); wl_list_remove(&subsurface_tree->surface_unmap.link); wl_list_remove(&subsurface_tree->surface_new_subsurface.link); + wl_list_remove(&subsurface_tree->scene_destroy.link); wl_list_remove(&subsurface_tree->link); free(subsurface_tree); } @@ -236,11 +235,6 @@ static void subsurface_tree_handle_surface_new_subsurface( } } -static const struct wlr_addon_interface subsurface_tree_addon_impl = { - .name = "wlr_scene_subsurface_tree_surface", - .destroy = subsurface_tree_addon_destroy, -}; - static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surface( struct wlr_scene_subsurface_tree *tree, struct wlr_scene_tree *parent, struct wlr_surface *surface) { @@ -281,8 +275,8 @@ static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surfa wl_list_insert(&tree->surfaces, &subsurface_tree->link); subsurface_tree_reconfigure(subsurface_tree); - wlr_addon_init(&subsurface_tree->scene_addon, &subsurface_tree->tree->node.addons, - NULL, &subsurface_tree_addon_impl); + subsurface_tree->scene_destroy.notify = subsurface_tree_handle_scene_destroy; + wl_signal_add(&subsurface_tree->tree->node.events.destroy, &subsurface_tree->scene_destroy); subsurface_tree->surface_destroy.notify = subsurface_tree_handle_surface_destroy; wl_signal_add(&surface->events.destroy, &subsurface_tree->surface_destroy); From 21a4df624f60cbdfbf836ca37f020d89f959d2be Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 13:51:25 -0400 Subject: [PATCH 6/8] wlr_scene: Introduce wlr_scene_subsurface_tree.is_visible and event --- include/wlr/types/wlr_scene.h | 6 ++++++ types/scene/subsurface_tree.c | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 4568c670a..35a0d69ef 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -134,10 +134,16 @@ struct wlr_scene_surface { struct wlr_scene_subsurface_tree_surface; struct wlr_scene_subsurface_tree { struct wlr_scene_tree *tree; + bool is_visible; + + struct { + struct wl_signal visibility; + } events; // private state struct wl_list surfaces; + uint16_t visible_surfaces; struct wlr_scene_subsurface_tree_surface *root; }; diff --git a/types/scene/subsurface_tree.c b/types/scene/subsurface_tree.c index 840f70e6d..adba58825 100644 --- a/types/scene/subsurface_tree.c +++ b/types/scene/subsurface_tree.c @@ -22,12 +22,14 @@ struct wlr_scene_subsurface_tree_surface { struct wl_listener surface_map; struct wl_listener surface_unmap; struct wl_listener surface_new_subsurface; + struct wl_listener scene_outputs_update; struct wl_listener scene_destroy; struct wlr_scene_subsurface_tree_surface *parent; // NULL for the top-level surface struct wlr_box clip; struct wl_list link; + bool is_visible; // Only valid if the surface is a sub-surface @@ -36,9 +38,32 @@ struct wlr_scene_subsurface_tree_surface { struct wl_listener subsurface_destroy; }; +static void subsurface_tree_handle_update_visibility( + struct wlr_scene_subsurface_tree_surface *tree, bool is_destroying) { + bool is_visible = tree->scene_surface->buffer->primary_output && !is_destroying; + + if (is_visible && !tree->is_visible) { + tree->subsurface_tree->visible_surfaces++; + } else if (!is_visible && tree->is_visible) { + assert(tree->subsurface_tree->visible_surfaces > 0); + tree->subsurface_tree->visible_surfaces--; + } + + tree->is_visible = is_visible; + + bool is_tree_visible = tree->subsurface_tree->visible_surfaces > 0; + if (is_tree_visible != tree->subsurface_tree->is_visible) { + tree->subsurface_tree->is_visible = is_tree_visible; + wl_signal_emit_mutable(&tree->subsurface_tree->events.visibility, NULL); + } +} + static void subsurface_tree_handle_scene_destroy(struct wl_listener *listener, void *data) { struct wlr_scene_subsurface_tree_surface *subsurface_tree = wl_container_of(listener, subsurface_tree, scene_destroy); + + subsurface_tree_handle_update_visibility(subsurface_tree, true); + // tree and scene_surface will be cleaned up by scene_node_finish if (subsurface_tree->parent) { wlr_addon_finish(&subsurface_tree->surface_addon); @@ -235,6 +260,13 @@ static void subsurface_tree_handle_surface_new_subsurface( } } +static void subsurface_tree_handle_scene_outputs_update( + struct wl_listener *listener, void *data) { + struct wlr_scene_subsurface_tree_surface *subsurface_tree = + wl_container_of(listener, subsurface_tree, scene_outputs_update); + subsurface_tree_handle_update_visibility(subsurface_tree, false); +} + static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surface( struct wlr_scene_subsurface_tree *tree, struct wlr_scene_tree *parent, struct wlr_surface *surface) { @@ -278,6 +310,10 @@ static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surfa subsurface_tree->scene_destroy.notify = subsurface_tree_handle_scene_destroy; wl_signal_add(&subsurface_tree->tree->node.events.destroy, &subsurface_tree->scene_destroy); + subsurface_tree->scene_outputs_update.notify = subsurface_tree_handle_scene_outputs_update; + wl_signal_add(&subsurface_tree->scene_surface->buffer->events.outputs_update, + &subsurface_tree->scene_outputs_update); + subsurface_tree->surface_destroy.notify = subsurface_tree_handle_surface_destroy; wl_signal_add(&surface->events.destroy, &subsurface_tree->surface_destroy); @@ -296,6 +332,7 @@ static struct wlr_scene_subsurface_tree_surface *scene_surface_tree_create_surfa &subsurface_tree->surface_new_subsurface); wlr_scene_node_set_enabled(&subsurface_tree->tree->node, surface->mapped); + subsurface_tree_handle_update_visibility(subsurface_tree, false); return subsurface_tree; @@ -314,6 +351,7 @@ struct wlr_scene_subsurface_tree *wlr_scene_subsurface_tree_create( } wl_list_init(&subsurface_tree->surfaces); + wl_signal_init(&subsurface_tree->events.visibility); struct wlr_scene_subsurface_tree_surface *subsurface_tree_surface = scene_surface_tree_create_surface(subsurface_tree, parent, surface); From 6cb062aac1a2dcd6307bbdde772d3162cfd1d045 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 13:33:45 -0400 Subject: [PATCH 7/8] wlr_scene: Expose subsurface tree for layer_shell_v1 --- include/wlr/types/wlr_scene.h | 1 + types/scene/layer_shell_v1.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 35a0d69ef..acd28771c 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -250,6 +250,7 @@ struct wlr_scene_timer { /** A layer shell scene helper */ struct wlr_scene_layer_surface_v1 { struct wlr_scene_tree *tree; + struct wlr_scene_subsurface_tree *surface_tree; struct wlr_layer_surface_v1 *layer_surface; // private state diff --git a/types/scene/layer_shell_v1.c b/types/scene/layer_shell_v1.c index bf34256eb..fbfcd357b 100644 --- a/types/scene/layer_shell_v1.c +++ b/types/scene/layer_shell_v1.c @@ -142,9 +142,9 @@ struct wlr_scene_layer_surface_v1 *wlr_scene_layer_surface_v1_create( return NULL; } - struct wlr_scene_subsurface_tree *surface_tree = wlr_scene_subsurface_tree_create( + scene_layer_surface->surface_tree = wlr_scene_subsurface_tree_create( scene_layer_surface->tree, layer_surface->surface); - if (surface_tree == NULL) { + if (scene_layer_surface->surface_tree == NULL) { wlr_scene_node_destroy(&scene_layer_surface->tree->node); free(scene_layer_surface); return NULL; From 541ee0c45d42266262286763f10a4e97ac180f65 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Thu, 4 Jul 2024 13:38:33 -0400 Subject: [PATCH 8/8] wlr_scene: Expose wlr_scene_xdg_surface So that the compositor can access the subsurface tree --- include/wlr/types/wlr_scene.h | 14 +++++++++++++- tinywl/tinywl.c | 26 +++++++++++++------------- types/scene/xdg_shell.c | 14 ++------------ 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index acd28771c..8866e11bf 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -261,6 +261,18 @@ struct wlr_scene_layer_surface_v1 { struct wl_listener layer_surface_unmap; }; +struct wlr_scene_xdg_surface { + struct wlr_scene_tree *tree; + struct wlr_xdg_surface *xdg_surface; + struct wlr_scene_subsurface_tree *surface_tree; + + // private state + + struct wl_listener tree_destroy; + struct wl_listener xdg_surface_destroy; + struct wl_listener xdg_surface_commit; +}; + /** * Immediately destroy the scene-graph node. */ @@ -584,7 +596,7 @@ void wlr_scene_subsurface_tree_set_clip(struct wlr_scene_subsurface_tree *tree, * The origin of the returned scene-graph node will match the top-left corner * of the xdg_surface window geometry. */ -struct wlr_scene_tree *wlr_scene_xdg_surface_create( +struct wlr_scene_xdg_surface *wlr_scene_xdg_surface_create( struct wlr_scene_tree *parent, struct wlr_xdg_surface *xdg_surface); /** diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 6c043ed51..640373b74 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -82,7 +82,7 @@ struct tinywl_toplevel { struct wl_list link; struct tinywl_server *server; struct wlr_xdg_toplevel *xdg_toplevel; - struct wlr_scene_tree *scene_tree; + struct wlr_scene_xdg_surface *scene; struct wl_listener map; struct wl_listener unmap; struct wl_listener commit; @@ -135,7 +135,7 @@ static void focus_toplevel(struct tinywl_toplevel *toplevel, struct wlr_surface } struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat); /* Move the toplevel to the front */ - wlr_scene_node_raise_to_top(&toplevel->scene_tree->node); + wlr_scene_node_raise_to_top(&toplevel->scene->tree->node); wl_list_remove(&toplevel->link); wl_list_insert(&server->toplevels, &toplevel->link); /* Activate the new surface */ @@ -380,7 +380,7 @@ static void reset_cursor_mode(struct tinywl_server *server) { static void process_cursor_move(struct tinywl_server *server, uint32_t time) { /* Move the grabbed toplevel to the new position. */ struct tinywl_toplevel *toplevel = server->grabbed_toplevel; - wlr_scene_node_set_position(&toplevel->scene_tree->node, + wlr_scene_node_set_position(&toplevel->scene->tree->node, server->cursor->x - server->grab_x, server->cursor->y - server->grab_y); } @@ -429,7 +429,7 @@ static void process_cursor_resize(struct tinywl_server *server, uint32_t time) { struct wlr_box geo_box; wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geo_box); - wlr_scene_node_set_position(&toplevel->scene_tree->node, + wlr_scene_node_set_position(&toplevel->scene->tree->node, new_left - geo_box.x, new_top - geo_box.y); int new_width = new_right - new_left; @@ -724,22 +724,22 @@ static void begin_interactive(struct tinywl_toplevel *toplevel, server->cursor_mode = mode; if (mode == TINYWL_CURSOR_MOVE) { - server->grab_x = server->cursor->x - toplevel->scene_tree->node.x; - server->grab_y = server->cursor->y - toplevel->scene_tree->node.y; + server->grab_x = server->cursor->x - toplevel->scene->tree->node.x; + server->grab_y = server->cursor->y - toplevel->scene->tree->node.y; } else { struct wlr_box geo_box; wlr_xdg_surface_get_geometry(toplevel->xdg_toplevel->base, &geo_box); - double border_x = (toplevel->scene_tree->node.x + geo_box.x) + + double border_x = (toplevel->scene->tree->node.x + geo_box.x) + ((edges & WLR_EDGE_RIGHT) ? geo_box.width : 0); - double border_y = (toplevel->scene_tree->node.y + geo_box.y) + + double border_y = (toplevel->scene->tree->node.y + geo_box.y) + ((edges & WLR_EDGE_BOTTOM) ? geo_box.height : 0); server->grab_x = server->cursor->x - border_x; server->grab_y = server->cursor->y - border_y; server->grab_geobox = geo_box; - server->grab_geobox.x += toplevel->scene_tree->node.x; - server->grab_geobox.y += toplevel->scene_tree->node.y; + server->grab_geobox.x += toplevel->scene->tree->node.x; + server->grab_geobox.y += toplevel->scene->tree->node.y; server->resize_edges = edges; } @@ -803,10 +803,10 @@ static void server_new_xdg_toplevel(struct wl_listener *listener, void *data) { struct tinywl_toplevel *toplevel = calloc(1, sizeof(*toplevel)); toplevel->server = server; toplevel->xdg_toplevel = xdg_toplevel; - toplevel->scene_tree = + toplevel->scene = wlr_scene_xdg_surface_create(&toplevel->server->scene->tree, xdg_toplevel->base); - toplevel->scene_tree->node.data = toplevel; - xdg_toplevel->base->data = toplevel->scene_tree; + toplevel->scene->tree->node.data = toplevel; + xdg_toplevel->base->data = toplevel->scene->tree; /* Listen to the various events it can emit */ toplevel->map.notify = xdg_toplevel_map; diff --git a/types/scene/xdg_shell.c b/types/scene/xdg_shell.c index f9668f933..0d84b07ee 100644 --- a/types/scene/xdg_shell.c +++ b/types/scene/xdg_shell.c @@ -2,16 +2,6 @@ #include #include -struct wlr_scene_xdg_surface { - struct wlr_scene_tree *tree; - struct wlr_xdg_surface *xdg_surface; - struct wlr_scene_subsurface_tree *surface_tree; - - struct wl_listener tree_destroy; - struct wl_listener xdg_surface_destroy; - struct wl_listener xdg_surface_commit; -}; - static void scene_xdg_surface_handle_tree_destroy(struct wl_listener *listener, void *data) { struct wlr_scene_xdg_surface *scene_xdg_surface = @@ -55,7 +45,7 @@ static void scene_xdg_surface_handle_xdg_surface_commit(struct wl_listener *list scene_xdg_surface_update_position(scene_xdg_surface); } -struct wlr_scene_tree *wlr_scene_xdg_surface_create( +struct wlr_scene_xdg_surface *wlr_scene_xdg_surface_create( struct wlr_scene_tree *parent, struct wlr_xdg_surface *xdg_surface) { struct wlr_scene_xdg_surface *scene_xdg_surface = calloc(1, sizeof(*scene_xdg_surface)); @@ -95,5 +85,5 @@ struct wlr_scene_tree *wlr_scene_xdg_surface_create( scene_xdg_surface_update_position(scene_xdg_surface); - return scene_xdg_surface->tree; + return scene_xdg_surface; }