diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index ad0a626f..a5fa093b 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -53,6 +53,7 @@ struct wlr_xdg_popup_grab { struct wlr_seat *seat; struct wl_list popups; struct wl_list link; // wlr_xdg_shell::popup_grabs + struct wl_listener seat_destroy; }; enum wlr_xdg_surface_role { diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index d8503d28..a1bdac1b 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -53,6 +53,7 @@ struct wlr_xdg_popup_grab_v6 { struct wlr_seat *seat; struct wl_list popups; struct wl_list link; // wlr_xdg_shell_v6::popup_grabs + struct wl_listener seat_destroy; }; enum wlr_xdg_surface_v6_role { diff --git a/types/wlr_xdg_shell.c b/types/wlr_xdg_shell.c index 5b02088d..f01d81a5 100644 --- a/types/wlr_xdg_shell.c +++ b/types/wlr_xdg_shell.c @@ -131,6 +131,24 @@ static const struct wlr_keyboard_grab_interface xdg_keyboard_grab_impl = { .cancel = xdg_keyboard_grab_cancel, }; +static void xdg_surface_destroy(struct wlr_xdg_surface *surface); + +static void wlr_xdg_popup_grab_handle_seat_destroy( + struct wl_listener *listener, void *data) { + struct wlr_xdg_popup_grab *xdg_grab = + wl_container_of(listener, xdg_grab, seat_destroy); + + wl_list_remove(&xdg_grab->seat_destroy.link); + + struct wlr_xdg_popup *popup, *next; + wl_list_for_each_safe(popup, next, &xdg_grab->popups, grab_link) { + xdg_surface_destroy(popup->base); + } + + wl_list_remove(&xdg_grab->link); + free(xdg_grab); +} + static struct wlr_xdg_popup_grab *xdg_shell_popup_grab_from_seat( struct wlr_xdg_shell *shell, struct wlr_seat *seat) { struct wlr_xdg_popup_grab *xdg_grab; @@ -155,6 +173,9 @@ static struct wlr_xdg_popup_grab *xdg_shell_popup_grab_from_seat( wl_list_insert(&shell->popup_grabs, &xdg_grab->link); xdg_grab->seat = seat; + xdg_grab->seat_destroy.notify = wlr_xdg_popup_grab_handle_seat_destroy; + wl_signal_add(&seat->events.destroy, &xdg_grab->seat_destroy); + return xdg_grab; } diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c index a0c74e6f..2aaa607b 100644 --- a/types/wlr_xdg_shell_v6.c +++ b/types/wlr_xdg_shell_v6.c @@ -131,6 +131,24 @@ static const struct wlr_keyboard_grab_interface xdg_keyboard_grab_impl = { .cancel = xdg_keyboard_grab_cancel, }; +static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface); + +static void wlr_xdg_popup_grab_handle_seat_destroy( + struct wl_listener *listener, void *data) { + struct wlr_xdg_popup_grab_v6 *xdg_grab = + wl_container_of(listener, xdg_grab, seat_destroy); + + wl_list_remove(&xdg_grab->seat_destroy.link); + + struct wlr_xdg_popup_v6 *popup, *next; + wl_list_for_each_safe(popup, next, &xdg_grab->popups, grab_link) { + xdg_surface_destroy(popup->base); + } + + wl_list_remove(&xdg_grab->link); + free(xdg_grab); +} + static struct wlr_xdg_popup_grab_v6 *xdg_shell_popup_grab_from_seat( struct wlr_xdg_shell_v6 *shell, struct wlr_seat *seat) { struct wlr_xdg_popup_grab_v6 *xdg_grab; @@ -155,6 +173,9 @@ static struct wlr_xdg_popup_grab_v6 *xdg_shell_popup_grab_from_seat( wl_list_insert(&shell->popup_grabs, &xdg_grab->link); xdg_grab->seat = seat; + xdg_grab->seat_destroy.notify = wlr_xdg_popup_grab_handle_seat_destroy; + wl_signal_add(&seat->events.destroy, &xdg_grab->seat_destroy); + return xdg_grab; }