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);
 | 
					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
 | 
					// 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 or scene output change. It is not necessary to call when a scene
 | 
				
			||||||
// buffer's node is enabled/disabled or obscured by other nodes.
 | 
					// 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);
 | 
						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,
 | 
					struct node_at_data {
 | 
				
			||||||
		double lx, double ly, double *nx, double *ny) {
 | 
						double lx, ly;
 | 
				
			||||||
	if (!node->enabled) {
 | 
						double rx, ry;
 | 
				
			||||||
		return NULL;
 | 
						struct wlr_scene_node *node;
 | 
				
			||||||
	}
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: optimize by storing a bounding box in each node?
 | 
					static bool scene_node_at_iterator(struct wlr_scene_node *node,
 | 
				
			||||||
	lx -= node->x;
 | 
							int lx, int ly, void *data) {
 | 
				
			||||||
	ly -= node->y;
 | 
						struct node_at_data *at_data = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool intersects = false;
 | 
						double rx = at_data->lx - lx;
 | 
				
			||||||
	switch (node->type) {
 | 
						double ry = at_data->ly - ly;
 | 
				
			||||||
	case WLR_SCENE_NODE_TREE:;
 | 
					
 | 
				
			||||||
		struct wlr_scene_tree *scene_tree = scene_tree_from_node(node);
 | 
						if (node->type == WLR_SCENE_NODE_BUFFER) {
 | 
				
			||||||
		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:;
 | 
					 | 
				
			||||||
		struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
 | 
							struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (scene_buffer->point_accepts_input) {
 | 
							if (scene_buffer->point_accepts_input &&
 | 
				
			||||||
			intersects = scene_buffer->point_accepts_input(scene_buffer, lx, ly);
 | 
									!scene_buffer->point_accepts_input(scene_buffer, rx, ry)) {
 | 
				
			||||||
		} else {
 | 
								return false;
 | 
				
			||||||
			int width, height;
 | 
					 | 
				
			||||||
			scene_node_get_size(node, &width, &height);
 | 
					 | 
				
			||||||
			intersects = lx >= 0 && lx < width && ly >= 0 && ly < height;
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		break;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (intersects) {
 | 
						at_data->rx = rx;
 | 
				
			||||||
		if (nx != NULL) {
 | 
						at_data->ry = ry;
 | 
				
			||||||
			*nx = lx;
 | 
						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) {
 | 
							if (ny) {
 | 
				
			||||||
			*ny = ly;
 | 
								*ny = data.ry;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return node;
 | 
							return data.node;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue