Merge branch 'scene-scaling' into 'master'

scene: Add scaling factor to nodes

See merge request wlroots/wlroots!5082
This commit is contained in:
Andri Yngvason 2025-06-16 07:44:47 +00:00
commit bba9a29e9b
2 changed files with 68 additions and 9 deletions

View file

@ -66,6 +66,7 @@ struct wlr_scene_node {
bool enabled; bool enabled;
int x, y; // relative to parent int x, y; // relative to parent
double scale;
struct { struct {
struct wl_signal destroy; struct wl_signal destroy;
@ -284,6 +285,11 @@ void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled);
* Set the position of the node relative to its parent. * Set the position of the node relative to its parent.
*/ */
void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y); void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y);
/**
* Set the scaling factor of the node. This scales the node's children
* accordingly.
*/
void wlr_scene_node_set_scale(struct wlr_scene_node *node, double scale);
/** /**
* Move the node right above the specified sibling. * Move the node right above the specified sibling.
* Asserts that node and sibling are distinct and share the same parent. * Asserts that node and sibling are distinct and share the same parent.

View file

@ -1,6 +1,7 @@
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include <wlr/backend.h> #include <wlr/backend.h>
#include <wlr/render/swapchain.h> #include <wlr/render/swapchain.h>
#include <wlr/render/drm_syncobj.h> #include <wlr/render/drm_syncobj.h>
@ -69,6 +70,7 @@ static void scene_node_init(struct wlr_scene_node *node,
.type = type, .type = type,
.parent = parent, .parent = parent,
.enabled = true, .enabled = true,
.scale = 1.0,
}; };
wl_list_init(&node->link); wl_list_init(&node->link);
@ -211,6 +213,8 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) {
} }
static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly); static void scene_node_get_size(struct wlr_scene_node *node, int *lx, int *ly);
static void scene_node_relative_coords(struct wlr_scene_node *node,
int *x, int *y);
typedef bool (*scene_node_box_iterator_func_t)(struct wlr_scene_node *node, typedef bool (*scene_node_box_iterator_func_t)(struct wlr_scene_node *node,
int sx, int sy, void *data); int sx, int sy, void *data);
@ -226,7 +230,10 @@ static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box
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_reverse(child, &scene_tree->children, link) { wl_list_for_each_reverse(child, &scene_tree->children, link) {
if (_scene_nodes_in_box(child, box, iterator, user_data, lx + child->x, ly + child->y)) { int x, y;
scene_node_relative_coords(child, &x, &y);
if (_scene_nodes_in_box(child, box, iterator, user_data,
lx + x, ly + y)) {
return true; return true;
} }
} }
@ -637,7 +644,9 @@ static void scene_node_bounds(struct wlr_scene_node *node,
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) {
scene_node_bounds(child, x + child->x, y + child->y, visible); int cx, cy;
scene_node_relative_coords(child, &cx, &cy);
scene_node_bounds(child, x + cx, y + cy, visible);
} }
return; return;
} }
@ -1120,7 +1129,20 @@ static struct wlr_texture *scene_buffer_get_texture(
return texture; return texture;
} }
static void scene_node_get_size(struct wlr_scene_node *node, static double _scene_node_get_scale(const struct wlr_scene_node *node,
double acc) {
if (!node) {
return acc;
}
return _scene_node_get_scale(node->parent ? &node->parent->node : NULL,
node->scale * acc);
}
static double scene_node_get_scale(const struct wlr_scene_node *node) {
return _scene_node_get_scale(node, 1.0);
}
static void scene_node_get_size_unscaled(struct wlr_scene_node *node,
int *width, int *height) { int *width, int *height) {
*width = 0; *width = 0;
*height = 0; *height = 0;
@ -1147,6 +1169,15 @@ static void scene_node_get_size(struct wlr_scene_node *node,
} }
} }
static void scene_node_get_size(struct wlr_scene_node *node,
int *width, int *height) {
double scale = scene_node_get_scale(node);
scene_node_get_size_unscaled(node, width, height);
*width = round(*width * scale);
*height = round(*height * scale);
}
void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) { void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) {
if (node->enabled == enabled) { if (node->enabled == enabled) {
return; return;
@ -1174,6 +1205,15 @@ void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) {
scene_node_update(node, NULL); scene_node_update(node, NULL);
} }
void wlr_scene_node_set_scale(struct wlr_scene_node *node, double scale) {
if (node->scale == scale) {
return;
}
node->scale = scale;
scene_node_update(node, NULL);
}
void wlr_scene_node_place_above(struct wlr_scene_node *node, void wlr_scene_node_place_above(struct wlr_scene_node *node,
struct wlr_scene_node *sibling) { struct wlr_scene_node *sibling) {
assert(node != sibling); assert(node != sibling);
@ -1247,6 +1287,13 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node,
scene_node_update(node, &visible); scene_node_update(node, &visible);
} }
static void scene_node_relative_coords(struct wlr_scene_node *node,
int *x, int *y) {
double parent_scale = node->parent ? scene_node_get_scale(&node->parent->node) : 1.0;
*x = round(parent_scale * node->x);
*y = round(parent_scale * node->y);
}
bool wlr_scene_node_coords(struct wlr_scene_node *node, bool wlr_scene_node_coords(struct wlr_scene_node *node,
int *lx_ptr, int *ly_ptr) { int *lx_ptr, int *ly_ptr) {
assert(node); assert(node);
@ -1254,8 +1301,10 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node,
int lx = 0, ly = 0; int lx = 0, ly = 0;
bool enabled = true; bool enabled = true;
while (true) { while (true) {
lx += node->x; int x, y;
ly += node->y; scene_node_relative_coords(node, &x, &y);
lx += x;
ly += y;
enabled = enabled && node->enabled; enabled = enabled && node->enabled;
if (node->parent == NULL) { if (node->parent == NULL) {
break; break;
@ -1276,8 +1325,10 @@ static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node,
return; return;
} }
lx += node->x; int x, y;
ly += node->y; scene_node_relative_coords(node, &x, &y);
lx += x;
ly += y;
if (node->type == WLR_SCENE_NODE_BUFFER) { if (node->type == WLR_SCENE_NODE_BUFFER) {
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
@ -2402,8 +2453,10 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box,
return; return;
} }
lx += node->x; int x, y;
ly += node->y; scene_node_relative_coords(node, &x, &y);
lx += x;
ly += y;
if (node->type == WLR_SCENE_NODE_BUFFER) { if (node->type == WLR_SCENE_NODE_BUFFER) {
struct wlr_box node_box = { .x = lx, .y = ly }; struct wlr_box node_box = { .x = lx, .y = ly };