diff options
| author | Alexander Orzechowski <[email protected]> | 2022-08-11 03:14:14 -0400 | 
|---|---|---|
| committer | Alexander Orzechowski <[email protected]> | 2022-08-14 01:39:20 -0400 | 
| commit | 26c910a62daf3463541fd1619ded32029602381f (patch) | |
| tree | 8f26cae0bfccab8af5638b7f4e2a49588364b0a9 | |
| parent | d165c3d5454d47ea25fa81d07f68e3a963d80310 (diff) | |
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.
| -rw-r--r-- | wlr_scene.c | 125 | 
1 files changed, 85 insertions, 40 deletions
diff --git a/wlr_scene.c b/wlr_scene.c index 3c45811..64b898d 100644 --- a/wlr_scene.c +++ b/wlr_scene.c @@ -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;  | 
