mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	subsurface stacking requests
This commit is contained in:
		
							parent
							
								
									2e8543cac0
								
							
						
					
					
						commit
						93f79378f7
					
				
					 2 changed files with 96 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -48,8 +48,10 @@ struct wlr_subsurface {
 | 
			
		|||
	bool has_cache;
 | 
			
		||||
 | 
			
		||||
	bool synchronized;
 | 
			
		||||
	bool reordered;
 | 
			
		||||
 | 
			
		||||
	struct wl_list parent_link;
 | 
			
		||||
	struct wl_list parent_pending_link;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct wlr_surface {
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +78,8 @@ struct wlr_surface {
 | 
			
		|||
	struct wlr_subsurface *subsurface;
 | 
			
		||||
	struct wl_list subsurface_list; // wlr_subsurface::parent_link
 | 
			
		||||
 | 
			
		||||
	// wlr_subsurface::parent_pending_link
 | 
			
		||||
	struct wl_list subsurface_pending_list;
 | 
			
		||||
	void *data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -290,12 +290,44 @@ static void wlr_surface_move_state(struct wlr_surface *surface, struct wlr_surfa
 | 
			
		|||
	next->invalid = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void wlr_surface_damage_subsurfaces(struct wlr_subsurface *subsurface) {
 | 
			
		||||
	// XXX: This is probably the wrong way to do it, because this damage should
 | 
			
		||||
	// come from the client, but weston doesn't do it correctly either and it
 | 
			
		||||
	// seems to work ok. See the comment on weston_surface_damage for more info
 | 
			
		||||
	// about a better approach.
 | 
			
		||||
	struct wlr_surface *surface = subsurface->surface;
 | 
			
		||||
	pixman_region32_union_rect(&surface->current->surface_damage,
 | 
			
		||||
		&surface->current->surface_damage,
 | 
			
		||||
		0, 0, surface->current->width,
 | 
			
		||||
		surface->current->height);
 | 
			
		||||
 | 
			
		||||
	subsurface->reordered = false;
 | 
			
		||||
 | 
			
		||||
	struct wlr_subsurface *child;
 | 
			
		||||
	wl_list_for_each(child, &subsurface->surface->subsurface_list, parent_link) {
 | 
			
		||||
		wlr_surface_damage_subsurfaces(child);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void wlr_surface_commit_pending(struct wlr_surface *surface) {
 | 
			
		||||
	int32_t oldw = surface->current->buffer_width;
 | 
			
		||||
	int32_t oldh = surface->current->buffer_height;
 | 
			
		||||
 | 
			
		||||
	wlr_surface_move_state(surface, surface->pending, surface->current);
 | 
			
		||||
 | 
			
		||||
	// commit subsurface order
 | 
			
		||||
	struct wlr_subsurface *subsurface;
 | 
			
		||||
	wl_list_for_each_reverse(subsurface, &surface->subsurface_pending_list,
 | 
			
		||||
		parent_pending_link) {
 | 
			
		||||
		wl_list_remove(&subsurface->parent_link);
 | 
			
		||||
		wl_list_insert(&surface->subsurface_list, &subsurface->parent_link);
 | 
			
		||||
 | 
			
		||||
		if (subsurface->reordered) {
 | 
			
		||||
			// TODO: damage all the subsurfaces
 | 
			
		||||
			wlr_surface_damage_subsurfaces(subsurface);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	surface->reupload_buffer = oldw != surface->current->buffer_width ||
 | 
			
		||||
		oldh != surface->current->buffer_height;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -546,6 +578,7 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
 | 
			
		|||
	wl_signal_init(&surface->signals.commit);
 | 
			
		||||
	wl_signal_init(&surface->signals.destroy);
 | 
			
		||||
	wl_list_init(&surface->subsurface_list);
 | 
			
		||||
	wl_list_init(&surface->subsurface_pending_list);
 | 
			
		||||
	wl_resource_set_implementation(res, &surface_interface,
 | 
			
		||||
		surface, destroy_surface);
 | 
			
		||||
	return surface;
 | 
			
		||||
| 
						 | 
				
			
			@ -612,14 +645,69 @@ static void subsurface_set_position(struct wl_client *client,
 | 
			
		|||
	surface->pending->subsurface_position.y = y;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct wlr_subsurface *subsurface_find_sibling(
 | 
			
		||||
		struct wlr_subsurface *subsurface, struct wlr_surface *surface) {
 | 
			
		||||
	struct wlr_surface *parent = subsurface->parent;
 | 
			
		||||
 | 
			
		||||
	struct wlr_subsurface *sibling;
 | 
			
		||||
	wl_list_for_each(sibling, &parent->subsurface_list, parent_link) {
 | 
			
		||||
		if (sibling->surface == surface && sibling != subsurface)
 | 
			
		||||
			return sibling;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void subsurface_place_above(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *resource, struct wl_resource *sibling) {
 | 
			
		||||
	wlr_log(L_DEBUG, "TODO: subsurface place above");
 | 
			
		||||
		struct wl_resource *resource, struct wl_resource *sibling_resource) {
 | 
			
		||||
	struct wlr_subsurface *subsurface = wl_resource_get_user_data(resource);
 | 
			
		||||
 | 
			
		||||
	if (!subsurface) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct wlr_surface *sibling_surface =
 | 
			
		||||
		wl_resource_get_user_data(sibling_resource);
 | 
			
		||||
	struct wlr_subsurface *sibling =
 | 
			
		||||
		subsurface_find_sibling(subsurface, sibling_surface);
 | 
			
		||||
 | 
			
		||||
	if (!sibling) {
 | 
			
		||||
		wl_resource_post_error(subsurface->resource,
 | 
			
		||||
			WL_SUBSURFACE_ERROR_BAD_SURFACE,
 | 
			
		||||
			"%s: wl_surface@%d is not a parent or sibling",
 | 
			
		||||
			"place_above", wl_resource_get_id(sibling_surface->resource));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_list_remove(&subsurface->parent_pending_link);
 | 
			
		||||
	wl_list_insert(sibling->parent_pending_link.prev,
 | 
			
		||||
		&subsurface->parent_pending_link);
 | 
			
		||||
 | 
			
		||||
	subsurface->reordered = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void subsurface_place_below(struct wl_client *client,
 | 
			
		||||
		struct wl_resource *resource, struct wl_resource *sibling) {
 | 
			
		||||
	wlr_log(L_DEBUG, "TODO: subsurface place below");
 | 
			
		||||
		struct wl_resource *resource, struct wl_resource *sibling_resource) {
 | 
			
		||||
	struct wlr_subsurface *subsurface = wl_resource_get_user_data(resource);
 | 
			
		||||
 | 
			
		||||
	struct wlr_surface *sibling_surface =
 | 
			
		||||
		wl_resource_get_user_data(sibling_resource);
 | 
			
		||||
	struct wlr_subsurface *sibling =
 | 
			
		||||
		subsurface_find_sibling(subsurface, sibling_surface);
 | 
			
		||||
 | 
			
		||||
	if (!sibling) {
 | 
			
		||||
		wl_resource_post_error(subsurface->resource,
 | 
			
		||||
			WL_SUBSURFACE_ERROR_BAD_SURFACE,
 | 
			
		||||
			"%s: wl_surface@%d is not a parent or sibling",
 | 
			
		||||
			"place_below", wl_resource_get_id(sibling_surface->resource));
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_list_remove(&subsurface->parent_pending_link);
 | 
			
		||||
	wl_list_insert(&sibling->parent_pending_link,
 | 
			
		||||
		&subsurface->parent_pending_link);
 | 
			
		||||
 | 
			
		||||
	subsurface->reordered = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void subsurface_set_sync(struct wl_client *client,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue