wlr_xdg_toplevel: reparent on parent unmap
From the xdg-shell specification: If the parent is unmapped then its children are managed as though the parent of the now-unmapped parent has become the parent of this surface. If no parent exists for the now-unmapped parent then the children are managed as though they have no parent surface.
This commit is contained in:
		
							parent
							
								
									8d2ea9544b
								
							
						
					
					
						commit
						9914784594
					
				|  | @ -117,9 +117,11 @@ struct wlr_xdg_toplevel_state { | |||
| struct wlr_xdg_toplevel { | ||||
| 	struct wl_resource *resource; | ||||
| 	struct wlr_xdg_surface *base; | ||||
| 	struct wlr_xdg_surface *parent; | ||||
| 	bool added; | ||||
| 
 | ||||
| 	struct wlr_xdg_surface *parent; | ||||
| 	struct wl_listener parent_unmap; | ||||
| 
 | ||||
| 	struct wlr_xdg_toplevel_state client_pending; | ||||
| 	struct wlr_xdg_toplevel_state server_pending; | ||||
| 	struct wlr_xdg_toplevel_state current; | ||||
|  |  | |||
|  | @ -41,6 +41,10 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) { | |||
| 
 | ||||
| 	switch (surface->role) { | ||||
| 	case WLR_XDG_SURFACE_ROLE_TOPLEVEL: | ||||
| 		if (surface->toplevel->parent) { | ||||
| 			wl_list_remove(&surface->toplevel->parent_unmap.link); | ||||
| 			surface->toplevel->parent = NULL; | ||||
| 		} | ||||
| 		free(surface->toplevel->title); | ||||
| 		surface->toplevel->title = NULL; | ||||
| 		free(surface->toplevel->app_id); | ||||
|  |  | |||
|  | @ -207,6 +207,34 @@ struct wlr_xdg_surface *wlr_xdg_surface_from_toplevel_resource( | |||
| 	return wl_resource_get_user_data(resource); | ||||
| } | ||||
| 
 | ||||
| static void set_parent(struct wlr_xdg_surface *surface, | ||||
| 		struct wlr_xdg_surface *parent); | ||||
| 
 | ||||
| static void handle_parent_unmap(struct wl_listener *listener, void *data) { | ||||
| 	struct wlr_xdg_toplevel *toplevel = | ||||
| 		wl_container_of(listener, toplevel, parent_unmap); | ||||
| 	set_parent(toplevel->base, toplevel->parent->toplevel->parent); | ||||
| } | ||||
| 
 | ||||
| static void set_parent(struct wlr_xdg_surface *surface, | ||||
| 		struct wlr_xdg_surface *parent) { | ||||
| 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); | ||||
| 	assert(!parent || parent->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); | ||||
| 
 | ||||
| 	if (surface->toplevel->parent) { | ||||
| 		wl_list_remove(&surface->toplevel->parent_unmap.link); | ||||
| 	} | ||||
| 
 | ||||
| 	surface->toplevel->parent = parent; | ||||
| 	if (surface->toplevel->parent) { | ||||
| 		surface->toplevel->parent_unmap.notify = handle_parent_unmap; | ||||
| 		wl_signal_add(&surface->toplevel->parent->events.unmap, | ||||
| 				&surface->toplevel->parent_unmap); | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_signal_emit_safe(&surface->toplevel->events.set_parent, surface); | ||||
| } | ||||
| 
 | ||||
| static void xdg_toplevel_handle_set_parent(struct wl_client *client, | ||||
| 		struct wl_resource *resource, struct wl_resource *parent_resource) { | ||||
| 	struct wlr_xdg_surface *surface = | ||||
|  | @ -217,8 +245,7 @@ static void xdg_toplevel_handle_set_parent(struct wl_client *client, | |||
| 		parent = wlr_xdg_surface_from_toplevel_resource(parent_resource); | ||||
| 	} | ||||
| 
 | ||||
| 	surface->toplevel->parent = parent; | ||||
| 	wlr_signal_emit_safe(&surface->toplevel->events.set_parent, surface); | ||||
| 	set_parent(surface, parent); | ||||
| } | ||||
| 
 | ||||
| static void xdg_toplevel_handle_set_title(struct wl_client *client, | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue