Add wlr_subcompositor
This commit is contained in:
		
							parent
							
								
									fa84b267e0
								
							
						
					
					
						commit
						bfcd3f3707
					
				|  | @ -6,7 +6,10 @@ | ||||||
| 
 | 
 | ||||||
| struct wlr_surface; | struct wlr_surface; | ||||||
| 
 | 
 | ||||||
| // TODO: expose subcompositor
 | struct wlr_subcompositor { | ||||||
|  | 	struct wl_global *wl_global; | ||||||
|  | 	struct wl_list wl_resources; | ||||||
|  | }; | ||||||
| 
 | 
 | ||||||
| struct wlr_compositor { | struct wlr_compositor { | ||||||
| 	struct wl_global *wl_global; | 	struct wl_global *wl_global; | ||||||
|  | @ -14,6 +17,8 @@ struct wlr_compositor { | ||||||
| 	struct wlr_renderer *renderer; | 	struct wlr_renderer *renderer; | ||||||
| 	struct wl_list surfaces; | 	struct wl_list surfaces; | ||||||
| 
 | 
 | ||||||
|  | 	struct wlr_subcompositor subcompositor; | ||||||
|  | 
 | ||||||
| 	struct wl_listener display_destroy; | 	struct wl_listener display_destroy; | ||||||
| 
 | 
 | ||||||
| 	struct { | 	struct { | ||||||
|  |  | ||||||
|  | @ -10,7 +10,8 @@ | ||||||
| static const char *subsurface_role = "wl_subsurface"; | static const char *subsurface_role = "wl_subsurface"; | ||||||
| 
 | 
 | ||||||
| bool wlr_surface_is_subsurface(struct wlr_surface *surface) { | bool wlr_surface_is_subsurface(struct wlr_surface *surface) { | ||||||
| 	return strcmp(surface->role, subsurface_role) == 0; | 	return surface->role != NULL && | ||||||
|  | 		strcmp(surface->role, subsurface_role) == 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| struct wlr_subsurface *wlr_subsurface_from_surface( | struct wlr_subsurface *wlr_subsurface_from_surface( | ||||||
|  | @ -19,9 +20,96 @@ struct wlr_subsurface *wlr_subsurface_from_surface( | ||||||
| 	return (struct wlr_subsurface *)surface->role_data; | 	return (struct wlr_subsurface *)surface->role_data; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void subcompositor_handle_destroy(struct wl_client *client, | ||||||
|  | 		struct wl_resource *resource) { | ||||||
|  | 	wl_resource_destroy(resource); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subcompositor_handle_get_subsurface(struct wl_client *client, | ||||||
|  | 		struct wl_resource *resource, uint32_t id, | ||||||
|  | 		struct wl_resource *surface_resource, | ||||||
|  | 		struct wl_resource *parent_resource) { | ||||||
|  | 	struct wlr_surface *surface = wlr_surface_from_resource(surface_resource); | ||||||
|  | 	struct wlr_surface *parent = wlr_surface_from_resource(parent_resource); | ||||||
|  | 
 | ||||||
|  | 	static const char msg[] = "get_subsurface: wl_subsurface@"; | ||||||
|  | 
 | ||||||
|  | 	if (surface == parent) { | ||||||
|  | 		wl_resource_post_error(resource, | ||||||
|  | 			WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, | ||||||
|  | 			"%s%d: wl_surface@%d cannot be its own parent", | ||||||
|  | 			msg, id, wl_resource_get_id(surface_resource)); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (wlr_surface_is_subsurface(surface)) { | ||||||
|  | 		wl_resource_post_error(resource, | ||||||
|  | 			WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, | ||||||
|  | 			"%s%d: wl_surface@%d is already a sub-surface", | ||||||
|  | 			msg, id, wl_resource_get_id(surface_resource)); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (wlr_surface_get_root_surface(parent) == surface) { | ||||||
|  | 		wl_resource_post_error(resource, | ||||||
|  | 			WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, | ||||||
|  | 			"%s%d: wl_surface@%d is an ancestor of parent", | ||||||
|  | 			msg, id, wl_resource_get_id(surface_resource)); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (wlr_surface_set_role(surface, subsurface_role, resource, | ||||||
|  | 				WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0) { | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wlr_surface_make_subsurface(surface, parent, id); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static const struct wl_subcompositor_interface subcompositor_interface = { | ||||||
|  | 	.destroy = subcompositor_handle_destroy, | ||||||
|  | 	.get_subsurface = subcompositor_handle_get_subsurface, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static void subcompositor_bind(struct wl_client *client, void *data, | ||||||
|  | 		uint32_t version, uint32_t id) { | ||||||
|  | 	struct wlr_subcompositor *subcompositor = data; | ||||||
|  | 	struct wl_resource *resource = | ||||||
|  | 		wl_resource_create(client, &wl_subcompositor_interface, 1, id); | ||||||
|  | 	if (resource == NULL) { | ||||||
|  | 		wl_client_post_no_memory(client); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	wl_resource_set_implementation(resource, &subcompositor_interface, | ||||||
|  | 		subcompositor, NULL); | ||||||
|  | 	wl_list_insert(&subcompositor->wl_resources, wl_resource_get_link(resource)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subcompositor_init(struct wlr_subcompositor *subcompositor, | ||||||
|  | 		struct wl_display *display) { | ||||||
|  | 	subcompositor->wl_global = wl_global_create(display, | ||||||
|  | 		&wl_subcompositor_interface, 1, subcompositor, subcompositor_bind); | ||||||
|  | 	if (subcompositor->wl_global == NULL) { | ||||||
|  | 		wlr_log_errno(L_ERROR, "Could not allocate subcompositor global"); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	wl_list_init(&subcompositor->wl_resources); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void subcompositor_finish(struct wlr_subcompositor *subcompositor) { | ||||||
|  | 	wl_global_destroy(subcompositor->wl_global); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| static const struct wl_compositor_interface wl_compositor_impl; | static const struct wl_compositor_interface wl_compositor_impl; | ||||||
| 
 | 
 | ||||||
| static struct wlr_compositor *compositor_from_resource(struct wl_resource *resource) { | static struct wlr_compositor *compositor_from_resource( | ||||||
|  | 		struct wl_resource *resource) { | ||||||
| 	assert(wl_resource_instance_of(resource, &wl_compositor_interface, | 	assert(wl_resource_instance_of(resource, &wl_compositor_interface, | ||||||
| 		&wl_compositor_impl)); | 		&wl_compositor_impl)); | ||||||
| 	return wl_resource_get_user_data(resource); | 	return wl_resource_get_user_data(resource); | ||||||
|  | @ -86,16 +174,15 @@ static void wl_compositor_bind(struct wl_client *wl_client, void *data, | ||||||
| 	struct wlr_compositor *compositor = data; | 	struct wlr_compositor *compositor = data; | ||||||
| 	assert(wl_client && compositor); | 	assert(wl_client && compositor); | ||||||
| 
 | 
 | ||||||
| 	struct wl_resource *wl_resource = | 	struct wl_resource *resource = | ||||||
| 		wl_resource_create(wl_client, &wl_compositor_interface, version, id); | 		wl_resource_create(wl_client, &wl_compositor_interface, version, id); | ||||||
| 	if (wl_resource == NULL) { | 	if (resource == NULL) { | ||||||
| 		wl_client_post_no_memory(wl_client); | 		wl_client_post_no_memory(wl_client); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	wl_resource_set_implementation(wl_resource, &wl_compositor_impl, | 	wl_resource_set_implementation(resource, &wl_compositor_impl, | ||||||
| 		compositor, wl_compositor_destroy); | 		compositor, wl_compositor_destroy); | ||||||
| 	wl_list_insert(&compositor->wl_resources, | 	wl_list_insert(&compositor->wl_resources, wl_resource_get_link(resource)); | ||||||
| 		wl_resource_get_link(wl_resource)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void wlr_compositor_destroy(struct wlr_compositor *compositor) { | void wlr_compositor_destroy(struct wlr_compositor *compositor) { | ||||||
|  | @ -103,76 +190,12 @@ void wlr_compositor_destroy(struct wlr_compositor *compositor) { | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 	wlr_signal_emit_safe(&compositor->events.destroy, compositor); | 	wlr_signal_emit_safe(&compositor->events.destroy, compositor); | ||||||
|  | 	subcompositor_finish(&compositor->subcompositor); | ||||||
| 	wl_list_remove(&compositor->display_destroy.link); | 	wl_list_remove(&compositor->display_destroy.link); | ||||||
| 	wl_global_destroy(compositor->wl_global); | 	wl_global_destroy(compositor->wl_global); | ||||||
| 	free(compositor); | 	free(compositor); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void subcompositor_destroy(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource) { |  | ||||||
| 	wl_resource_destroy(resource); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void subcompositor_get_subsurface(struct wl_client *client, |  | ||||||
| 		struct wl_resource *resource, uint32_t id, |  | ||||||
| 		struct wl_resource *surface_resource, |  | ||||||
| 		struct wl_resource *parent_resource) { |  | ||||||
| 	struct wlr_surface *surface = wlr_surface_from_resource(surface_resource); |  | ||||||
| 	struct wlr_surface *parent = wlr_surface_from_resource(parent_resource); |  | ||||||
| 
 |  | ||||||
| 	static const char msg[] = "get_subsurface: wl_subsurface@"; |  | ||||||
| 
 |  | ||||||
| 	if (surface == parent) { |  | ||||||
| 		wl_resource_post_error(resource, |  | ||||||
| 			WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, |  | ||||||
| 			"%s%d: wl_surface@%d cannot be its own parent", |  | ||||||
| 			msg, id, wl_resource_get_id(surface_resource)); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (wlr_surface_is_subsurface(surface)) { |  | ||||||
| 		wl_resource_post_error(resource, |  | ||||||
| 			WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, |  | ||||||
| 			"%s%d: wl_surface@%d is already a sub-surface", |  | ||||||
| 			msg, id, wl_resource_get_id(surface_resource)); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (wlr_surface_get_root_surface(parent) == surface) { |  | ||||||
| 		wl_resource_post_error(resource, |  | ||||||
| 			WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE, |  | ||||||
| 			"%s%d: wl_surface@%d is an ancestor of parent", |  | ||||||
| 			msg, id, wl_resource_get_id(surface_resource)); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if (wlr_surface_set_role(surface, subsurface_role, resource, |  | ||||||
| 				WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0) { |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	wlr_surface_make_subsurface(surface, parent, id); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| static const struct wl_subcompositor_interface subcompositor_interface = { |  | ||||||
| 	.destroy = subcompositor_destroy, |  | ||||||
| 	.get_subsurface = subcompositor_get_subsurface, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| static void subcompositor_bind(struct wl_client *client, void *data, |  | ||||||
| 		uint32_t version, uint32_t id) { |  | ||||||
| 	struct wlr_compositor *compositor = data; |  | ||||||
| 	struct wl_resource *resource = |  | ||||||
| 		wl_resource_create(client, &wl_subcompositor_interface, 1, id); |  | ||||||
| 	if (resource == NULL) { |  | ||||||
| 		wl_client_post_no_memory(client); |  | ||||||
| 		return; |  | ||||||
| 	} |  | ||||||
| 	wl_resource_set_implementation(resource, &subcompositor_interface, |  | ||||||
| 		compositor, NULL); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void handle_display_destroy(struct wl_listener *listener, void *data) { | static void handle_display_destroy(struct wl_listener *listener, void *data) { | ||||||
| 	struct wlr_compositor *compositor = | 	struct wlr_compositor *compositor = | ||||||
| 		wl_container_of(listener, compositor, display_destroy); | 		wl_container_of(listener, compositor, display_destroy); | ||||||
|  | @ -198,14 +221,13 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display, | ||||||
| 	compositor->wl_global = compositor_global; | 	compositor->wl_global = compositor_global; | ||||||
| 	compositor->renderer = renderer; | 	compositor->renderer = renderer; | ||||||
| 
 | 
 | ||||||
| 	wl_global_create(display, &wl_subcompositor_interface, 1, compositor, |  | ||||||
| 		subcompositor_bind); |  | ||||||
| 
 |  | ||||||
| 	wl_list_init(&compositor->wl_resources); | 	wl_list_init(&compositor->wl_resources); | ||||||
| 	wl_list_init(&compositor->surfaces); | 	wl_list_init(&compositor->surfaces); | ||||||
| 	wl_signal_init(&compositor->events.new_surface); | 	wl_signal_init(&compositor->events.new_surface); | ||||||
| 	wl_signal_init(&compositor->events.destroy); | 	wl_signal_init(&compositor->events.destroy); | ||||||
| 
 | 
 | ||||||
|  | 	subcompositor_init(&compositor->subcompositor, display); | ||||||
|  | 
 | ||||||
| 	compositor->display_destroy.notify = handle_display_destroy; | 	compositor->display_destroy.notify = handle_display_destroy; | ||||||
| 	wl_display_add_destroy_listener(display, &compositor->display_destroy); | 	wl_display_add_destroy_listener(display, &compositor->display_destroy); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue