From b0e0f2c8417126631e9cdcdf8e90c66fb7288c42 Mon Sep 17 00:00:00 2001 From: Marius Vlad Date: Fri, 18 Oct 2024 10:44:17 +0300 Subject: [PATCH] libweston/desktop: Don't destroy the xdg_surface Upon xdg_toplevel::destroy we seem to be calling xdg_surface::destroy destroy handler. Protocol states that we should umap the surface with client having the posibility to getting another toplevel role for the same xdg_surface and re-map the window. This also adds a guard for an unlikely invalid resource. Fixes: #774 Signed-off-by: Marius Vlad (cherry picked from commit 8b5bb588dff9e0a73081c65fea0d709efd7e5b14) --- libweston/desktop/xdg-shell-v6.c | 32 +++++++++++++++++++++------- libweston/desktop/xdg-shell.c | 36 ++++++++++++++++++++++++-------- 2 files changed, 51 insertions(+), 17 deletions(-) diff --git a/libweston/desktop/xdg-shell-v6.c b/libweston/desktop/xdg-shell-v6.c index 08aef859e..f16d40c42 100644 --- a/libweston/desktop/xdg-shell-v6.c +++ b/libweston/desktop/xdg-shell-v6.c @@ -781,8 +781,16 @@ weston_desktop_xdg_toplevel_resource_destroy(struct wl_resource *resource) struct weston_desktop_surface *dsurface = wl_resource_get_user_data(resource); - if (dsurface != NULL) - weston_desktop_surface_resource_destroy(resource); + if (dsurface) { + struct weston_desktop_xdg_toplevel *toplevel = + weston_desktop_surface_get_implementation_data(dsurface); + struct weston_surface *wsurface = + weston_desktop_surface_get_surface(dsurface); + + weston_surface_unmap(wsurface); + wl_list_remove(wl_resource_get_link(resource)); + toplevel->resource = NULL; + } } static const struct zxdg_toplevel_v6_interface weston_desktop_xdg_toplevel_implementation = { @@ -1072,12 +1080,20 @@ weston_desktop_xdg_surface_protocol_get_toplevel(struct wl_client *wl_client, struct wl_resource *resource, uint32_t id) { - struct weston_desktop_surface *dsurface = - wl_resource_get_user_data(resource); - struct weston_surface *wsurface = - weston_desktop_surface_get_surface(dsurface); - struct weston_desktop_xdg_toplevel *toplevel = - weston_desktop_surface_get_implementation_data(dsurface); + struct weston_desktop_surface *dsurface = NULL; + struct weston_surface *wsurface = NULL; + struct weston_desktop_xdg_toplevel *toplevel = NULL; + + dsurface = wl_resource_get_user_data(resource); + if (!dsurface) { + wl_resource_post_error(resource, + ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED, + "xdg surface destroyed"); + return; + } + + wsurface = weston_desktop_surface_get_surface(dsurface); + toplevel = weston_desktop_surface_get_implementation_data(dsurface); if (weston_surface_set_role(wsurface, weston_desktop_xdg_toplevel_role, resource, ZXDG_SHELL_V6_ERROR_ROLE) < 0) diff --git a/libweston/desktop/xdg-shell.c b/libweston/desktop/xdg-shell.c index 4be965c81..999676c91 100644 --- a/libweston/desktop/xdg-shell.c +++ b/libweston/desktop/xdg-shell.c @@ -887,8 +887,17 @@ weston_desktop_xdg_toplevel_resource_destroy(struct wl_resource *resource) struct weston_desktop_surface *dsurface = wl_resource_get_user_data(resource); - if (dsurface != NULL) - weston_desktop_surface_resource_destroy(resource); + if (dsurface) { + struct weston_desktop_xdg_toplevel *toplevel = + weston_desktop_surface_get_implementation_data(dsurface); + struct weston_surface *wsurface = + weston_desktop_surface_get_surface(dsurface); + + weston_surface_unmap(wsurface); + wl_list_remove(wl_resource_get_link(resource)); + toplevel->resource = NULL; + } + } static const struct xdg_toplevel_interface weston_desktop_xdg_toplevel_implementation = { @@ -1246,13 +1255,22 @@ weston_desktop_xdg_surface_protocol_get_toplevel(struct wl_client *wl_client, struct wl_resource *resource, uint32_t id) { - struct weston_desktop_surface *dsurface = - wl_resource_get_user_data(resource); - struct weston_surface *wsurface = - weston_desktop_surface_get_surface(dsurface); - struct weston_desktop_xdg_toplevel *toplevel = - weston_desktop_surface_get_implementation_data(dsurface); - struct weston_desktop *desktop = toplevel->base.desktop; + struct weston_desktop_surface *dsurface = NULL; + struct weston_surface *wsurface = NULL; + struct weston_desktop_xdg_toplevel *toplevel = NULL; + struct weston_desktop *desktop = NULL; + + dsurface = wl_resource_get_user_data(resource); + if (!dsurface) { + wl_resource_post_error(resource, + XDG_SURFACE_ERROR_DEFUNCT_ROLE_OBJECT, + "xdg surface destroyed"); + return; + } + + wsurface = weston_desktop_surface_get_surface(dsurface); + toplevel = weston_desktop_surface_get_implementation_data(dsurface); + desktop = toplevel->base.desktop; if (weston_surface_set_role(wsurface, weston_desktop_xdg_toplevel_role, resource, XDG_WM_BASE_ERROR_ROLE) < 0)