mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	wlr_scene: Introduce scene_nodes_in_box
Will query the scene for all nodes that appear in the given wlr_box. The nodes will be sent to the iterator from closest to farthest from the eye. Refactor wlr_scene_node_at to use this new function.
This commit is contained in:
		
							parent
							
								
									c2359d0321
								
							
						
					
					
						commit
						7f17774d18
					
				
					 1 changed files with 85 additions and 40 deletions
				
			
		| 
						 | 
				
			
			@ -195,6 +195,50 @@ 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);
 | 
			
		||||
 | 
			
		||||
typedef bool (*scene_node_box_iterator_func_t)(struct wlr_scene_node *node,
 | 
			
		||||
	int sx, int sy, void *data);
 | 
			
		||||
 | 
			
		||||
static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box, 
 | 
			
		||||
		scene_node_box_iterator_func_t iterator, void *user_data, int lx, int ly) {
 | 
			
		||||
	if (!node->enabled) {
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch (node->type) {
 | 
			
		||||
	case WLR_SCENE_NODE_TREE:;
 | 
			
		||||
		struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
 | 
			
		||||
		struct wlr_scene_node *child;
 | 
			
		||||
		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)) {
 | 
			
		||||
				return true;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case WLR_SCENE_NODE_RECT:
 | 
			
		||||
	case WLR_SCENE_NODE_BUFFER:;
 | 
			
		||||
		struct wlr_box node_box = { .x = lx, .y = ly };
 | 
			
		||||
		scene_node_get_size(node, &node_box.width, &node_box.height);
 | 
			
		||||
		bool intersects;
 | 
			
		||||
 | 
			
		||||
		intersects = wlr_box_intersection(&node_box, &node_box, box);
 | 
			
		||||
 | 
			
		||||
		if (intersects && iterator(node, lx, ly, user_data)) {
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box, 
 | 
			
		||||
		scene_node_box_iterator_func_t iterator, void *user_data) {
 | 
			
		||||
	int x, y;
 | 
			
		||||
	wlr_scene_node_coords(node, &x, &y);
 | 
			
		||||
 | 
			
		||||
	return _scene_nodes_in_box(node, box, iterator, user_data, x, y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function must be called whenever the coordinates/dimensions of a scene
 | 
			
		||||
// buffer or scene output change. It is not necessary to call when a scene
 | 
			
		||||
// buffer's node is enabled/disabled or obscured by other nodes.
 | 
			
		||||
| 
						 | 
				
			
			@ -745,55 +789,56 @@ void wlr_scene_node_for_each_buffer(struct wlr_scene_node *node,
 | 
			
		|||
	scene_node_for_each_scene_buffer(node, 0, 0, user_iterator, user_data);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
 | 
			
		||||
		double lx, double ly, double *nx, double *ny) {
 | 
			
		||||
	if (!node->enabled) {
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
struct node_at_data {
 | 
			
		||||
	double lx, ly;
 | 
			
		||||
	double rx, ry;
 | 
			
		||||
	struct wlr_scene_node *node;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
	// TODO: optimize by storing a bounding box in each node?
 | 
			
		||||
	lx -= node->x;
 | 
			
		||||
	ly -= node->y;
 | 
			
		||||
static bool scene_node_at_iterator(struct wlr_scene_node *node,
 | 
			
		||||
		int lx, int ly, void *data) {
 | 
			
		||||
	struct node_at_data *at_data = data;
 | 
			
		||||
 | 
			
		||||
	bool intersects = false;
 | 
			
		||||
	switch (node->type) {
 | 
			
		||||
	case WLR_SCENE_NODE_TREE:;
 | 
			
		||||
		struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
 | 
			
		||||
		struct wlr_scene_node *child;
 | 
			
		||||
		wl_list_for_each_reverse(child, &scene_tree->children, link) {
 | 
			
		||||
			struct wlr_scene_node *node =
 | 
			
		||||
				wlr_scene_node_at(child, lx, ly, nx, ny);
 | 
			
		||||
			if (node != NULL) {
 | 
			
		||||
				return node;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case WLR_SCENE_NODE_RECT:;
 | 
			
		||||
		int width, height;
 | 
			
		||||
		scene_node_get_size(node, &width, &height);
 | 
			
		||||
		intersects = lx >= 0 && lx < width && ly >= 0 && ly < height;
 | 
			
		||||
		break;
 | 
			
		||||
	case WLR_SCENE_NODE_BUFFER:;
 | 
			
		||||
	double rx = at_data->lx - lx;
 | 
			
		||||
	double ry = at_data->ly - ly;
 | 
			
		||||
 | 
			
		||||
	if (node->type == WLR_SCENE_NODE_BUFFER) {
 | 
			
		||||
		struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
 | 
			
		||||
 | 
			
		||||
		if (scene_buffer->point_accepts_input) {
 | 
			
		||||
			intersects = scene_buffer->point_accepts_input(scene_buffer, lx, ly);
 | 
			
		||||
		} else {
 | 
			
		||||
			int width, height;
 | 
			
		||||
			scene_node_get_size(node, &width, &height);
 | 
			
		||||
			intersects = lx >= 0 && lx < width && ly >= 0 && ly < height;
 | 
			
		||||
		if (scene_buffer->point_accepts_input &&
 | 
			
		||||
				!scene_buffer->point_accepts_input(scene_buffer, rx, ry)) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (intersects) {
 | 
			
		||||
		if (nx != NULL) {
 | 
			
		||||
			*nx = lx;
 | 
			
		||||
	at_data->rx = rx;
 | 
			
		||||
	at_data->ry = ry;
 | 
			
		||||
	at_data->node = node;
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
 | 
			
		||||
		double lx, double ly, double *nx, double *ny) {
 | 
			
		||||
	struct wlr_box box = {
 | 
			
		||||
		.x = floor(lx),
 | 
			
		||||
		.y = floor(ly),
 | 
			
		||||
		.width = 1,
 | 
			
		||||
		.height = 1
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	struct node_at_data data = {
 | 
			
		||||
		.lx = lx,
 | 
			
		||||
		.ly = ly
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (scene_nodes_in_box(node, &box, scene_node_at_iterator, &data)) {
 | 
			
		||||
		if (nx) {
 | 
			
		||||
			*nx = data.rx;
 | 
			
		||||
		}
 | 
			
		||||
		if (ny != NULL) {
 | 
			
		||||
			*ny = ly;
 | 
			
		||||
		if (ny) {
 | 
			
		||||
			*ny = data.ry;
 | 
			
		||||
		}
 | 
			
		||||
		return node;
 | 
			
		||||
		return data.node;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue