mirror of
				https://gitlab.freedesktop.org/wayland/wayland.git
				synced 2025-10-29 05:40:16 -04:00 
			
		
		
		
	server: add wl_global_remove
This commit adds a new wl_global_remove function that just sends a global remove event without destroying it. See [1] for details. Removing a global is racy, because clients have no way to acknowledge they received the removal event. It's possible to mitigate the issue by sending the removal event, waiting a little and then destructing the global for real. The "wait a little" part is compositor policy. [1]: https://gitlab.freedesktop.org/wayland/wayland/issues/10 Signed-off-by: Simon Ser <contact@emersion.fr>
This commit is contained in:
		
							parent
							
								
									11623e8fdd
								
							
						
					
					
						commit
						39852f1146
					
				
					 2 changed files with 43 additions and 2 deletions
				
			
		|  | @ -25,6 +25,7 @@ | |||
| 
 | ||||
| #define _GNU_SOURCE | ||||
| 
 | ||||
| #include <stdbool.h> | ||||
| #include <stdlib.h> | ||||
| #include <stdint.h> | ||||
| #include <stddef.h> | ||||
|  | @ -112,6 +113,7 @@ struct wl_global { | |||
| 	void *data; | ||||
| 	wl_global_bind_func_t bind; | ||||
| 	struct wl_list link; | ||||
| 	bool removed; | ||||
| }; | ||||
| 
 | ||||
| struct wl_resource { | ||||
|  | @ -992,7 +994,7 @@ display_get_registry(struct wl_client *client, | |||
| 		       ®istry_resource->link); | ||||
| 
 | ||||
| 	wl_list_for_each(global, &display->global_list, link) | ||||
| 		if (wl_global_is_visible(client, global)) | ||||
| 		if (wl_global_is_visible(client, global) && !global->removed) | ||||
| 			wl_resource_post_event(registry_resource, | ||||
| 					       WL_REGISTRY_GLOBAL, | ||||
| 					       global->name, | ||||
|  | @ -1208,6 +1210,7 @@ wl_global_create(struct wl_display *display, | |||
| 	global->version = version; | ||||
| 	global->data = data; | ||||
| 	global->bind = bind; | ||||
| 	global->removed = false; | ||||
| 	wl_list_insert(display->global_list.prev, &global->link); | ||||
| 
 | ||||
| 	wl_list_for_each(resource, &display->registry_resource_list, link) | ||||
|  | @ -1220,15 +1223,50 @@ wl_global_create(struct wl_display *display, | |||
| 	return global; | ||||
| } | ||||
| 
 | ||||
| /** Remove the global
 | ||||
|  * | ||||
|  * \param global The Wayland global. | ||||
|  * | ||||
|  * Broadcast a global remove event to all clients without destroying the | ||||
|  * global. This function can only be called once per global. | ||||
|  * | ||||
|  * wl_global_destroy() removes the global and immediately destroys it. On | ||||
|  * the other end, this function only removes the global, allowing clients | ||||
|  * that have not yet received the global remove event to continue to bind to | ||||
|  * it. | ||||
|  * | ||||
|  * This can be used by compositors to mitigate clients being disconnected | ||||
|  * because a global has been added and removed too quickly. Compositors can call | ||||
|  * wl_global_remove(), then wait an implementation-defined amount of time, then | ||||
|  * call wl_global_destroy(). Note that the destruction of a global is still | ||||
|  * racy, since clients have no way to acknowledge that they received the remove | ||||
|  * event. | ||||
|  * | ||||
|  * \since 1.17.90 | ||||
|  */ | ||||
| WL_EXPORT void | ||||
| wl_global_destroy(struct wl_global *global) | ||||
| wl_global_remove(struct wl_global *global) | ||||
| { | ||||
| 	struct wl_display *display = global->display; | ||||
| 	struct wl_resource *resource; | ||||
| 
 | ||||
| 	if (global->removed) | ||||
| 		wl_abort("wl_global_remove: called twice on the same " | ||||
| 			 "global '%s@%"PRIu32"'", global->interface->name, | ||||
| 			 global->name); | ||||
| 
 | ||||
| 	wl_list_for_each(resource, &display->registry_resource_list, link) | ||||
| 		wl_resource_post_event(resource, WL_REGISTRY_GLOBAL_REMOVE, | ||||
| 				       global->name); | ||||
| 
 | ||||
| 	global->removed = true; | ||||
| } | ||||
| 
 | ||||
| WL_EXPORT void | ||||
| wl_global_destroy(struct wl_global *global) | ||||
| { | ||||
| 	if (!global->removed) | ||||
| 		wl_global_remove(global); | ||||
| 	wl_list_remove(&global->link); | ||||
| 	free(global); | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Simon Ser
						Simon Ser