mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	scene: send surface enter/leave events
This commit is contained in:
		
							parent
							
								
									679f5ed966
								
							
						
					
					
						commit
						1b80b9ddce
					
				
					 2 changed files with 80 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -67,6 +67,8 @@ struct wlr_scene_surface {
 | 
			
		|||
 | 
			
		||||
	// private state
 | 
			
		||||
 | 
			
		||||
	int prev_width, prev_height;
 | 
			
		||||
 | 
			
		||||
	struct wl_listener surface_destroy;
 | 
			
		||||
	struct wl_listener surface_commit;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -64,6 +64,7 @@ static void scene_node_finish(struct wlr_scene_node *node) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static void scene_node_damage_whole(struct wlr_scene_node *node);
 | 
			
		||||
static struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
 | 
			
		||||
 | 
			
		||||
void wlr_scene_node_destroy(struct wlr_scene_node *node) {
 | 
			
		||||
	if (node == NULL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -73,11 +74,11 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
 | 
			
		|||
	scene_node_damage_whole(node);
 | 
			
		||||
	scene_node_finish(node);
 | 
			
		||||
 | 
			
		||||
	struct wlr_scene *scene = scene_node_get_root(node);
 | 
			
		||||
	struct wlr_scene_output *scene_output;
 | 
			
		||||
	switch (node->type) {
 | 
			
		||||
	case WLR_SCENE_NODE_ROOT:;
 | 
			
		||||
		struct wlr_scene *scene = scene_root_from_node(node);
 | 
			
		||||
 | 
			
		||||
		struct wlr_scene_output *scene_output, *scene_output_tmp;
 | 
			
		||||
		struct wlr_scene_output *scene_output_tmp;
 | 
			
		||||
		wl_list_for_each_safe(scene_output, scene_output_tmp, &scene->outputs, link) {
 | 
			
		||||
			wlr_scene_output_destroy(scene_output);
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +87,11 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
 | 
			
		|||
		break;
 | 
			
		||||
	case WLR_SCENE_NODE_SURFACE:;
 | 
			
		||||
		struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node);
 | 
			
		||||
 | 
			
		||||
		wl_list_for_each(scene_output, &scene->outputs, link) {
 | 
			
		||||
			wlr_surface_send_leave(scene_surface->surface, scene_output->output);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		wl_list_remove(&scene_surface->surface_destroy.link);
 | 
			
		||||
		free(scene_surface);
 | 
			
		||||
		break;
 | 
			
		||||
| 
						 | 
				
			
			@ -120,6 +126,60 @@ static struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node) {
 | 
			
		|||
	return scene_root_from_node(node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void surface_update_outputs(struct wlr_surface *surface,
 | 
			
		||||
		struct wlr_scene *scene, int lx, int ly, bool enabled) {
 | 
			
		||||
	struct wlr_box surface_box = {0};
 | 
			
		||||
	if (enabled) {
 | 
			
		||||
		surface_box.x = lx;
 | 
			
		||||
		surface_box.y = ly;
 | 
			
		||||
		surface_box.width = surface->current.width;
 | 
			
		||||
		surface_box.height = surface->current.height;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct wlr_scene_output *scene_output;
 | 
			
		||||
	wl_list_for_each(scene_output, &scene->outputs, link) {
 | 
			
		||||
		struct wlr_box output_box = {
 | 
			
		||||
			.x = scene_output->x,
 | 
			
		||||
			.y = scene_output->y,
 | 
			
		||||
		};
 | 
			
		||||
		wlr_output_effective_resolution(scene_output->output,
 | 
			
		||||
			&output_box.width, &output_box.height);
 | 
			
		||||
 | 
			
		||||
		struct wlr_box intersection;
 | 
			
		||||
		if (wlr_box_intersection(&intersection, &surface_box, &output_box)) {
 | 
			
		||||
			wlr_surface_send_enter(surface, scene_output->output);
 | 
			
		||||
		} else {
 | 
			
		||||
			wlr_surface_send_leave(surface, scene_output->output);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _scene_node_update_surface_outputs(struct wlr_scene_node *node,
 | 
			
		||||
		struct wlr_scene *scene, int lx, int ly, bool enabled) {
 | 
			
		||||
	struct wlr_scene_node *child;
 | 
			
		||||
	wl_list_for_each(child, &node->state.children, state.link) {
 | 
			
		||||
		_scene_node_update_surface_outputs(node, scene,
 | 
			
		||||
			lx + child->state.x, ly + child->state.y,
 | 
			
		||||
			enabled && child->state.enabled);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (node->type != WLR_SCENE_NODE_SURFACE) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct wlr_scene_surface *scene_surface = wlr_scene_surface_from_node(node);
 | 
			
		||||
	surface_update_outputs(scene_surface->surface, scene, lx, ly, enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void scene_node_update_surface_outputs(struct wlr_scene_node *node) {
 | 
			
		||||
	struct wlr_scene *scene = scene_node_get_root(node);
 | 
			
		||||
 | 
			
		||||
	int lx, ly;
 | 
			
		||||
	wlr_scene_node_coords(node, &lx, &ly);
 | 
			
		||||
 | 
			
		||||
	_scene_node_update_surface_outputs(node, scene, lx, ly, node->state.enabled);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void scene_surface_handle_surface_commit(struct wl_listener *listener,
 | 
			
		||||
		void *data) {
 | 
			
		||||
	struct wlr_scene_surface *scene_surface =
 | 
			
		||||
| 
						 | 
				
			
			@ -158,6 +218,15 @@ static void scene_surface_handle_surface_commit(struct wl_listener *listener,
 | 
			
		|||
		wlr_output_damage_add(scene_output->damage, &damage);
 | 
			
		||||
		pixman_region32_fini(&damage);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (surface->current.width != scene_surface->prev_width ||
 | 
			
		||||
			surface->current.height != scene_surface->prev_height) {
 | 
			
		||||
		// TODO: figure out if any parent is disabled
 | 
			
		||||
		surface_update_outputs(scene_surface->surface, scene, lx, ly,
 | 
			
		||||
			scene_surface->node.state.enabled);
 | 
			
		||||
		scene_surface->prev_width = surface->current.width;
 | 
			
		||||
		scene_surface->prev_height = surface->current.height;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent,
 | 
			
		||||
| 
						 | 
				
			
			@ -178,6 +247,7 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_node *parent
 | 
			
		|||
	wl_signal_add(&surface->events.commit, &scene_surface->surface_commit);
 | 
			
		||||
 | 
			
		||||
	scene_node_damage_whole(&scene_surface->node);
 | 
			
		||||
	scene_node_update_surface_outputs(&scene_surface->node);
 | 
			
		||||
 | 
			
		||||
	return scene_surface;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -298,6 +368,7 @@ void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) {
 | 
			
		|||
	scene_node_damage_whole(node);
 | 
			
		||||
	node->state.enabled = enabled;
 | 
			
		||||
	scene_node_damage_whole(node);
 | 
			
		||||
	scene_node_update_surface_outputs(node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) {
 | 
			
		||||
| 
						 | 
				
			
			@ -309,6 +380,7 @@ void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) {
 | 
			
		|||
	node->state.x = x;
 | 
			
		||||
	node->state.y = y;
 | 
			
		||||
	scene_node_damage_whole(node);
 | 
			
		||||
	scene_node_update_surface_outputs(node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_scene_node_place_above(struct wlr_scene_node *node,
 | 
			
		||||
| 
						 | 
				
			
			@ -646,11 +718,13 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene,
 | 
			
		|||
	wl_list_insert(&scene->outputs, &scene_output->link);
 | 
			
		||||
 | 
			
		||||
	wlr_output_damage_add_whole(scene_output->damage);
 | 
			
		||||
	scene_node_update_surface_outputs(&scene->node);
 | 
			
		||||
 | 
			
		||||
	return scene_output;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) {
 | 
			
		||||
	// TODO: consider leaving all surfaces
 | 
			
		||||
	wlr_addon_finish(&scene_output->addon);
 | 
			
		||||
	wl_list_remove(&scene_output->link);
 | 
			
		||||
	free(scene_output);
 | 
			
		||||
| 
						 | 
				
			
			@ -665,6 +739,7 @@ void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
 | 
			
		|||
	scene_output->x = lx;
 | 
			
		||||
	scene_output->y = ly;
 | 
			
		||||
	wlr_output_damage_add_whole(scene_output->damage);
 | 
			
		||||
	scene_node_update_surface_outputs(&scene_output->scene->node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool wlr_scene_output_commit(struct wlr_scene_output *scene_output) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue