mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Merge pull request #1373 from emersion/fix-teardown-segfaults
xdg-shell: don't destroy xdg role state on role destroy
This commit is contained in:
		
						commit
						4aff85cc8e
					
				
					 3 changed files with 71 additions and 41 deletions
				
			
		| 
						 | 
					@ -234,11 +234,21 @@ void create_xdg_popup(struct wlr_xdg_surface *xdg_surface,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_NONE) {
 | 
				
			||||||
 | 
							wl_resource_post_error(xdg_surface->resource,
 | 
				
			||||||
 | 
								XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED,
 | 
				
			||||||
 | 
								"xdg-surface has already been constructed");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (xdg_surface->popup == NULL) {
 | 
				
			||||||
		xdg_surface->popup = calloc(1, sizeof(struct wlr_xdg_popup));
 | 
							xdg_surface->popup = calloc(1, sizeof(struct wlr_xdg_popup));
 | 
				
			||||||
		if (!xdg_surface->popup) {
 | 
							if (!xdg_surface->popup) {
 | 
				
			||||||
			wl_resource_post_no_memory(xdg_surface->resource);
 | 
								wl_resource_post_no_memory(xdg_surface->resource);
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							xdg_surface->popup->base = xdg_surface;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xdg_surface->popup->resource = wl_resource_create(
 | 
						xdg_surface->popup->resource = wl_resource_create(
 | 
				
			||||||
		xdg_surface->client->client, &xdg_popup_interface,
 | 
							xdg_surface->client->client, &xdg_popup_interface,
 | 
				
			||||||
| 
						 | 
					@ -253,7 +263,6 @@ void create_xdg_popup(struct wlr_xdg_surface *xdg_surface,
 | 
				
			||||||
		xdg_popup_handle_resource_destroy);
 | 
							xdg_popup_handle_resource_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xdg_surface->role = WLR_XDG_SURFACE_ROLE_POPUP;
 | 
						xdg_surface->role = WLR_XDG_SURFACE_ROLE_POPUP;
 | 
				
			||||||
	xdg_surface->popup->base = xdg_surface;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// positioner properties
 | 
						// positioner properties
 | 
				
			||||||
	memcpy(&xdg_surface->popup->positioner, &positioner->attrs,
 | 
						memcpy(&xdg_surface->popup->positioner, &positioner->attrs,
 | 
				
			||||||
| 
						 | 
					@ -265,19 +274,24 @@ void create_xdg_popup(struct wlr_xdg_surface *xdg_surface,
 | 
				
			||||||
		xdg_surface->popup->parent = parent->surface;
 | 
							xdg_surface->popup->parent = parent->surface;
 | 
				
			||||||
		wl_list_insert(&parent->popups, &xdg_surface->popup->link);
 | 
							wl_list_insert(&parent->popups, &xdg_surface->popup->link);
 | 
				
			||||||
		wlr_signal_emit_safe(&parent->events.new_popup, xdg_surface->popup);
 | 
							wlr_signal_emit_safe(&parent->events.new_popup, xdg_surface->popup);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							wl_list_init(&xdg_surface->popup->link);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void destroy_xdg_popup(struct wlr_xdg_surface *surface) {
 | 
					void destroy_xdg_popup(struct wlr_xdg_surface *xdg_surface) {
 | 
				
			||||||
	assert(surface->role == WLR_XDG_SURFACE_ROLE_POPUP);
 | 
						assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP);
 | 
				
			||||||
	unmap_xdg_surface(surface);
 | 
						unmap_xdg_surface(xdg_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_resource_set_user_data(surface->popup->resource, NULL);
 | 
						// Don't destroy the popup state yet, the compositor might have some
 | 
				
			||||||
	wl_list_remove(&surface->popup->link);
 | 
						// listeners set up. Anyway the client can only re-create another xdg-popup
 | 
				
			||||||
	free(surface->popup);
 | 
						// with this xdg-surface because of role restrictions.
 | 
				
			||||||
	surface->popup = NULL;
 | 
						wl_resource_set_user_data(xdg_surface->popup->resource, NULL);
 | 
				
			||||||
 | 
						xdg_surface->toplevel->resource = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	surface->role = WLR_XDG_SURFACE_ROLE_NONE;
 | 
						wl_list_remove(&xdg_surface->popup->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xdg_surface->role = WLR_XDG_SURFACE_ROLE_NONE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_xdg_popup_get_anchor_point(struct wlr_xdg_popup *popup,
 | 
					void wlr_xdg_popup_get_anchor_point(struct wlr_xdg_popup *popup,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,18 +83,6 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) {
 | 
				
			||||||
	memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
 | 
						memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void destroy_xdg_toplevel(struct wlr_xdg_surface *surface) {
 | 
					 | 
				
			||||||
	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
 | 
					 | 
				
			||||||
	unmap_xdg_surface(surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_resource_set_user_data(surface->toplevel->resource, NULL);
 | 
					 | 
				
			||||||
	free(surface->toplevel);
 | 
					 | 
				
			||||||
	surface->toplevel = NULL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	surface->role = WLR_XDG_SURFACE_ROLE_NONE;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xdg_surface_handle_ack_configure(struct wl_client *client,
 | 
					static void xdg_surface_handle_ack_configure(struct wl_client *client,
 | 
				
			||||||
		struct wl_resource *resource, uint32_t serial) {
 | 
							struct wl_resource *resource, uint32_t serial) {
 | 
				
			||||||
| 
						 | 
					@ -476,6 +464,12 @@ void destroy_xdg_surface(struct wlr_xdg_surface *surface) {
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (surface->surface->role == &xdg_toplevel_surface_role) {
 | 
				
			||||||
 | 
							free(surface->toplevel);
 | 
				
			||||||
 | 
						} else if (surface->surface->role == &xdg_popup_surface_role) {
 | 
				
			||||||
 | 
							free(surface->popup);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_resource_set_user_data(surface->resource, NULL);
 | 
						wl_resource_set_user_data(surface->resource, NULL);
 | 
				
			||||||
	surface->surface->role_data = NULL;
 | 
						surface->surface->role_data = NULL;
 | 
				
			||||||
	wl_list_remove(&surface->link);
 | 
						wl_list_remove(&surface->link);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -462,6 +462,14 @@ void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_NONE) {
 | 
				
			||||||
 | 
							wl_resource_post_error(xdg_surface->resource,
 | 
				
			||||||
 | 
								XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED,
 | 
				
			||||||
 | 
								"xdg-surface has already been constructed");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (xdg_surface->toplevel == NULL) {
 | 
				
			||||||
		xdg_surface->toplevel = calloc(1, sizeof(struct wlr_xdg_toplevel));
 | 
							xdg_surface->toplevel = calloc(1, sizeof(struct wlr_xdg_toplevel));
 | 
				
			||||||
		if (xdg_surface->toplevel == NULL) {
 | 
							if (xdg_surface->toplevel == NULL) {
 | 
				
			||||||
			wl_resource_post_no_memory(xdg_surface->resource);
 | 
								wl_resource_post_no_memory(xdg_surface->resource);
 | 
				
			||||||
| 
						 | 
					@ -477,22 +485,36 @@ void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface,
 | 
				
			||||||
		wl_signal_init(&xdg_surface->toplevel->events.set_title);
 | 
							wl_signal_init(&xdg_surface->toplevel->events.set_title);
 | 
				
			||||||
		wl_signal_init(&xdg_surface->toplevel->events.set_app_id);
 | 
							wl_signal_init(&xdg_surface->toplevel->events.set_app_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xdg_surface->role = WLR_XDG_SURFACE_ROLE_TOPLEVEL;
 | 
					 | 
				
			||||||
		xdg_surface->toplevel->base = xdg_surface;
 | 
							xdg_surface->toplevel->base = xdg_surface;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_resource *toplevel_resource = wl_resource_create(
 | 
						xdg_surface->role = WLR_XDG_SURFACE_ROLE_TOPLEVEL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert(xdg_surface->toplevel->resource == NULL);
 | 
				
			||||||
 | 
						xdg_surface->toplevel->resource = wl_resource_create(
 | 
				
			||||||
		xdg_surface->client->client, &xdg_toplevel_interface,
 | 
							xdg_surface->client->client, &xdg_toplevel_interface,
 | 
				
			||||||
		wl_resource_get_version(xdg_surface->resource), id);
 | 
							wl_resource_get_version(xdg_surface->resource), id);
 | 
				
			||||||
	if (toplevel_resource == NULL) {
 | 
						if (xdg_surface->toplevel->resource == NULL) {
 | 
				
			||||||
		free(xdg_surface->toplevel);
 | 
							free(xdg_surface->toplevel);
 | 
				
			||||||
		wl_resource_post_no_memory(xdg_surface->resource);
 | 
							wl_resource_post_no_memory(xdg_surface->resource);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wl_resource_set_implementation(toplevel_resource,
 | 
						wl_resource_set_implementation(xdg_surface->toplevel->resource,
 | 
				
			||||||
		&xdg_toplevel_implementation, xdg_surface,
 | 
							&xdg_toplevel_implementation, xdg_surface,
 | 
				
			||||||
		xdg_toplevel_handle_resource_destroy);
 | 
							xdg_toplevel_handle_resource_destroy);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xdg_surface->toplevel->resource = toplevel_resource;
 | 
					void destroy_xdg_toplevel(struct wlr_xdg_surface *xdg_surface) {
 | 
				
			||||||
 | 
						assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
 | 
				
			||||||
 | 
						unmap_xdg_surface(xdg_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Don't destroy the toplevel state yet, the compositor might have some
 | 
				
			||||||
 | 
						// listeners set up. Anyway the client can only re-create another
 | 
				
			||||||
 | 
						// xdg-toplevel with this xdg-surface because of role restrictions.
 | 
				
			||||||
 | 
						wl_resource_set_user_data(xdg_surface->toplevel->resource, NULL);
 | 
				
			||||||
 | 
						xdg_surface->toplevel->resource = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xdg_surface->role = WLR_XDG_SURFACE_ROLE_NONE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t wlr_xdg_toplevel_set_size(struct wlr_xdg_surface *surface,
 | 
					uint32_t wlr_xdg_toplevel_set_size(struct wlr_xdg_surface *surface,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue