diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index b81b7a3b..29ced596 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -485,6 +485,24 @@ struct wlr_surface *wlr_xdg_surface_popup_surface_at( */ struct wlr_xdg_surface *wlr_xdg_surface_try_from_wlr_surface(struct wlr_surface *surface); +/** + * Get a struct wlr_xdg_toplevel from a struct wlr_surface. + * + * Returns NULL if the surface doesn't have the xdg_surface role, the + * xdg_surface is not a toplevel, or the xdg_surface/xdg_toplevel objects have + * been destroyed. + */ +struct wlr_xdg_toplevel *wlr_xdg_toplevel_try_from_wlr_surface(struct wlr_surface *surface); + +/** + * Get a struct wlr_xdg_popup from a struct wlr_surface. + * + * Returns NULL if the surface doesn't have the xdg_surface role, the + * xdg_surface is not a popup, or the xdg_surface/xdg_popup objects have + * been destroyed. + */ +struct wlr_xdg_popup *wlr_xdg_popup_try_from_wlr_surface(struct wlr_surface *surface); + /** * Get the surface geometry. * diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index 64339c43..e8035878 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -261,6 +261,14 @@ struct wlr_xdg_popup *wlr_xdg_popup_from_resource( return wl_resource_get_user_data(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) { + return NULL; + } + return xdg_surface->popup; +} + static void xdg_popup_handle_grab(struct wl_client *client, struct wl_resource *resource, struct wl_resource *seat_resource, uint32_t serial) { diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 6b163599..fef9b21c 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -158,6 +158,14 @@ struct wlr_xdg_toplevel *wlr_xdg_toplevel_from_resource( return wl_resource_get_user_data(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) { + return NULL; + } + return xdg_surface->toplevel; +} + static void handle_parent_unmap(struct wl_listener *listener, void *data) { struct wlr_xdg_toplevel *toplevel = wl_container_of(listener, toplevel, parent_unmap);