ext_image_capture_source_v1/scene: fix extents

Currently the width/height of the extents is too small if the first node
visited has position/dimensions 0,0,100,100 and the second node has
position/dimensions -20,-20,10,10.

In this case the current code calculates total extents as
-20,-20,100,100 but the correct extents are -20,-20,120,120.

References: https://codeberg.org/river/river-classic/issues/17
This commit is contained in:
Isaac Freund 2026-03-30 11:45:54 +02:00
parent 334019f839
commit e22084f639
No known key found for this signature in database
GPG key ID: 86DED400DDFD7A11

View file

@ -34,13 +34,14 @@ struct scene_node_source_frame_event {
static size_t last_output_num = 0; static size_t last_output_num = 0;
static void _get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *box, int lx, int ly) { static void _get_scene_node_extents(struct wlr_scene_node *node, int lx, int ly,
int *x_min, int *y_min, int *x_max, int *y_max) {
switch (node->type) { switch (node->type) {
case WLR_SCENE_NODE_TREE:; case WLR_SCENE_NODE_TREE:;
struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node); struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node);
struct wlr_scene_node *child; struct wlr_scene_node *child;
wl_list_for_each(child, &scene_tree->children, link) { wl_list_for_each(child, &scene_tree->children, link) {
_get_scene_node_extents(child, box, lx + child->x, ly + child->y); _get_scene_node_extents(child, lx + child->x, ly + child->y, x_min, y_min, x_max, y_max);
} }
break; break;
case WLR_SCENE_NODE_RECT: case WLR_SCENE_NODE_RECT:
@ -48,27 +49,30 @@ static void _get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box
struct wlr_box node_box = { .x = lx, .y = ly }; struct wlr_box node_box = { .x = lx, .y = ly };
scene_node_get_size(node, &node_box.width, &node_box.height); scene_node_get_size(node, &node_box.width, &node_box.height);
if (node_box.x < box->x) { if (node_box.x < *x_min) {
box->x = node_box.x; *x_min = node_box.x;
} }
if (node_box.y < box->y) { if (node_box.y < *y_min) {
box->y = node_box.y; *y_min = node_box.y;
} }
if (node_box.x + node_box.width > box->x + box->width) { if (node_box.x + node_box.width > *x_max) {
box->width = node_box.x + node_box.width - box->x; *x_max = node_box.x + node_box.width;
} }
if (node_box.y + node_box.height > box->y + box->height) { if (node_box.y + node_box.height > *y_max) {
box->height = node_box.y + node_box.height - box->y; *y_max = node_box.y + node_box.height;
} }
break; break;
} }
} }
static void get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *box) { static void get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *box) {
*box = (struct wlr_box){ .x = INT_MAX, .y = INT_MAX };
int lx = 0, ly = 0; int lx = 0, ly = 0;
wlr_scene_node_coords(node, &lx, &ly); wlr_scene_node_coords(node, &lx, &ly);
_get_scene_node_extents(node, box, lx, ly); *box = (struct wlr_box){ .x = INT_MAX, .y = INT_MAX };
int x_max = INT_MIN, y_max = INT_MIN;
_get_scene_node_extents(node, lx, ly, &box->x, &box->y, &x_max, &y_max);
box->width = x_max - box->x;
box->height = y_max - box->y;
} }
static void source_render(struct scene_node_source *source) { static void source_render(struct scene_node_source *source) {