diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index d54c5366b..c34a29b20 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -514,6 +514,15 @@ struct wlr_xdg_surface *wlr_xdg_surface_try_from_wlr_surface(struct wlr_surface */ struct wlr_xdg_toplevel *wlr_xdg_toplevel_try_from_wlr_surface(struct wlr_surface *surface); +/** + * Get a struct wlr_xdg_toplevel from a struct wlr_xdg_surface. + * + * Returns NULL if the xdg_surface doesn't have the xdg_toplevel role or if the + * xdg_toplevel has been destroyed. + */ +struct wlr_xdg_toplevel *wlr_xdg_toplevel_try_from_wlr_xdg_surface( + struct wlr_xdg_surface *xdg_surface); + /** * Get a struct wlr_xdg_popup from a struct wlr_surface. * @@ -523,6 +532,15 @@ struct wlr_xdg_toplevel *wlr_xdg_toplevel_try_from_wlr_surface(struct wlr_surfac */ struct wlr_xdg_popup *wlr_xdg_popup_try_from_wlr_surface(struct wlr_surface *surface); +/** + * Get a struct wlr_xdg_popup from a struct wlr_xdg_surface. + * + * Returns NULL if the xdg_surface doesn't have the xdg_popup role or if the + * xdg_popup has been destroyed. + */ +struct wlr_xdg_popup *wlr_xdg_popup_try_from_wlr_xdg_surface( + struct wlr_xdg_surface *xdg_surface); + /** * Get the surface geometry. * diff --git a/types/scene/xdg_shell.c b/types/scene/xdg_shell.c index ed792633d..7ac270eb8 100644 --- a/types/scene/xdg_shell.c +++ b/types/scene/xdg_shell.c @@ -39,12 +39,10 @@ static void scene_xdg_surface_update_position( wlr_scene_node_set_position(&scene_xdg_surface->surface_tree->node, -geo.x, -geo.y); - if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { - struct wlr_xdg_popup *popup = xdg_surface->popup; - if (popup != NULL) { - wlr_scene_node_set_position(&scene_xdg_surface->tree->node, - popup->current.geometry.x, popup->current.geometry.y); - } + struct wlr_xdg_popup *popup = wlr_xdg_popup_try_from_wlr_xdg_surface(xdg_surface); + if (popup != NULL) { + wlr_scene_node_set_position(&scene_xdg_surface->tree->node, + popup->current.geometry.x, popup->current.geometry.y); } } diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index a718b4528..f0d266c93 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -248,8 +248,7 @@ void handle_xdg_popup_client_commit(struct wlr_xdg_popup *popup) { static const struct xdg_popup_interface xdg_popup_implementation; -struct wlr_xdg_popup *wlr_xdg_popup_from_resource( - struct wl_resource *resource) { +struct wlr_xdg_popup *wlr_xdg_popup_from_resource(struct wl_resource *resource) { assert(wl_resource_instance_of(resource, &xdg_popup_interface, &xdg_popup_implementation)); return wl_resource_get_user_data(resource); @@ -257,10 +256,18 @@ struct wlr_xdg_popup *wlr_xdg_popup_from_resource( struct wlr_xdg_popup *wlr_xdg_popup_try_from_wlr_surface(struct wlr_surface *surface) { struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface); - if (xdg_surface == NULL || xdg_surface->role != WLR_XDG_SURFACE_ROLE_POPUP) { + if (xdg_surface == NULL) { return NULL; } - return xdg_surface->popup; + return wlr_xdg_popup_try_from_wlr_xdg_surface(xdg_surface); +} + +struct wlr_xdg_popup *wlr_xdg_popup_try_from_wlr_xdg_surface( + struct wlr_xdg_surface *xdg_surface) { + if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_POPUP) { + return NULL; + } + return wlr_xdg_popup_from_resource(xdg_surface->role_resource); } static void xdg_popup_handle_grab(struct wl_client *client, @@ -402,8 +409,6 @@ void create_xdg_popup(struct wlr_xdg_surface *surface, struct wlr_xdg_surface *p wl_resource_set_implementation(surface->popup->resource, &xdg_popup_implementation, surface->popup, NULL); - surface->role = WLR_XDG_SURFACE_ROLE_POPUP; - wlr_xdg_positioner_rules_get_geometry( &positioner->rules, &surface->popup->scheduled.geometry); surface->popup->scheduled.rules = positioner->rules; @@ -491,15 +496,17 @@ void wlr_xdg_popup_destroy(struct wlr_xdg_popup *popup) { void wlr_xdg_popup_get_toplevel_coords(struct wlr_xdg_popup *popup, int popup_sx, int popup_sy, int *toplevel_sx, int *toplevel_sy) { struct wlr_surface *parent = popup->parent; - struct wlr_xdg_surface *xdg_surface; - while ((xdg_surface = wlr_xdg_surface_try_from_wlr_surface(parent))) { - if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP && xdg_surface->popup != NULL) { - popup_sx += xdg_surface->popup->current.geometry.x; - popup_sy += xdg_surface->popup->current.geometry.y; - parent = xdg_surface->popup->parent; + struct wlr_xdg_surface *parent_xdg_surface; + while ((parent_xdg_surface = wlr_xdg_surface_try_from_wlr_surface(parent))) { + struct wlr_xdg_popup *parent_popup = + wlr_xdg_popup_try_from_wlr_xdg_surface(parent_xdg_surface); + if (parent_popup != NULL) { + popup_sx += parent_popup->current.geometry.x; + popup_sy += parent_popup->current.geometry.y; + parent = parent_popup->parent; } else { - popup_sx += xdg_surface->current.geometry.x; - popup_sy += xdg_surface->current.geometry.y; + popup_sx += parent_xdg_surface->current.geometry.x; + popup_sy += parent_xdg_surface->current.geometry.y; break; } } diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 1c4fa30c4..92b4597c7 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -141,10 +141,18 @@ struct wlr_xdg_toplevel *wlr_xdg_toplevel_from_resource( struct wlr_xdg_toplevel *wlr_xdg_toplevel_try_from_wlr_surface(struct wlr_surface *surface) { struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(surface); - if (xdg_surface == NULL || xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) { + if (xdg_surface == NULL) { return NULL; } - return xdg_surface->toplevel; + return wlr_xdg_toplevel_try_from_wlr_xdg_surface(xdg_surface); +} + +struct wlr_xdg_toplevel *wlr_xdg_toplevel_try_from_wlr_xdg_surface( + struct wlr_xdg_surface *xdg_surface) { + if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) { + return NULL; + } + return wlr_xdg_toplevel_from_resource(xdg_surface->role_resource); } static void handle_parent_unmap(struct wl_listener *listener, void *data) {