From db4c93028d2c807694be8a9fa36e581239d1ee77 Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Wed, 20 Oct 2021 18:16:27 +0200 Subject: [PATCH] scene: add wlr_scene_output_for_each_surface This allows compositors to more easily implement sending wl_surface.frame callback done events. --- include/wlr/types/wlr_scene.h | 8 ++++++++ types/scene/wlr_scene.c | 38 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 7a0801c0..17516aaf 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -270,6 +270,14 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output, */ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output); +/** + * Call `iterator` on each surface in the scene-graph visible on the output, + * with the surface's position in layout coordinates. The function is called + * from root to leaves (in rendering order). + */ +void wlr_scene_output_for_each_surface(struct wlr_scene_output *scene_output, + wlr_surface_iterator_func_t iterator, void *user_data); + /** * Attach an output layout to a scene. * diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 30d5deb9..ddb6f21c 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -887,3 +887,41 @@ bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) { return wlr_output_commit(output); } + +static void scene_output_for_each_surface(const struct wlr_box *output_box, + struct wlr_scene_node *node, int lx, int ly, + wlr_surface_iterator_func_t user_iterator, void *user_data) { + if (!node->state.enabled) { + return; + } + + lx += node->state.x; + ly += node->state.y; + + if (node->type == WLR_SCENE_NODE_SURFACE) { + struct wlr_box node_box = { .x = lx, .y = ly }; + scene_node_get_size(node, &node_box.width, &node_box.height); + + struct wlr_box intersection; + if (wlr_box_intersection(&intersection, output_box, &node_box)) { + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_from_node(node); + user_iterator(scene_surface->surface, lx, ly, user_data); + } + } + + struct wlr_scene_node *child; + wl_list_for_each(child, &node->state.children, state.link) { + scene_output_for_each_surface(output_box, child, lx, ly, + user_iterator, user_data); + } +} + +void wlr_scene_output_for_each_surface(struct wlr_scene_output *scene_output, + wlr_surface_iterator_func_t iterator, void *user_data) { + struct wlr_box box = { .x = scene_output->x, .y = scene_output->y }; + wlr_output_effective_resolution(scene_output->output, + &box.width, &box.height); + scene_output_for_each_surface(&box, &scene_output->scene->node, 0, 0, + iterator, user_data); +}