aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2021-10-20 18:16:27 +0200
committerIsaac Freund <mail@isaacfreund.com>2021-10-22 22:29:35 +0200
commitdb4c93028d2c807694be8a9fa36e581239d1ee77 (patch)
treee57f1e7c768a1fda9d4f383d5d0149f49427b0b4
parent70e8277175fc756b635650c1bbad295592b5ed94 (diff)
scene: add wlr_scene_output_for_each_surface
This allows compositors to more easily implement sending wl_surface.frame callback done events.
-rw-r--r--include/wlr/types/wlr_scene.h8
-rw-r--r--types/scene/wlr_scene.c38
2 files changed, 46 insertions, 0 deletions
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
@@ -271,6 +271,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.
*
* Outputs in the output layout are automatically added to the scene. Any
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);
+}