mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 21:05:58 +01:00
xdg-shell-v6: don't destroy role resources on unmap
The motivation for this is: - `get_popup` and `get_toplevel` allocate role-specific resources. - On the first non-null commit, the surface gets mapped. - On a null commit, the surface gets unmapped. It can be mapped again with a non-null commit. - When the role object (xdg-toplevel or xdg-popup) is destroyed, the surface is unmapped and role-specific resources are destroyed. The client can call `get_popup` or `get_toplevel` again on that surface. - When the xdg-surface object is destroyed, the surface is unmapped, role-specific resources are destroyed and the surface itself is destroyed.
This commit is contained in:
parent
891610081f
commit
5233801530
3 changed files with 53 additions and 28 deletions
|
@ -106,6 +106,7 @@ struct wlr_xdg_surface {
|
|||
uint32_t configure_next_serial;
|
||||
struct wl_list configure_list;
|
||||
|
||||
// Only for toplevel
|
||||
char *title;
|
||||
char *app_id;
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ struct wlr_xdg_surface_v6 {
|
|||
uint32_t configure_next_serial;
|
||||
struct wl_list configure_list;
|
||||
|
||||
// Only for toplevel
|
||||
char *title;
|
||||
char *app_id;
|
||||
|
||||
|
|
|
@ -198,16 +198,8 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
|
|||
wlr_signal_emit_safe(&surface->events.unmap, surface);
|
||||
}
|
||||
|
||||
if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
|
||||
wl_resource_set_user_data(surface->toplevel->resource, NULL);
|
||||
free(surface->toplevel);
|
||||
surface->toplevel = NULL;
|
||||
}
|
||||
|
||||
if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
|
||||
wl_resource_set_user_data(surface->popup->resource, NULL);
|
||||
|
||||
if (surface->popup->seat) {
|
||||
if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP &&
|
||||
surface->popup->seat != NULL) {
|
||||
struct wlr_xdg_popup_grab_v6 *grab =
|
||||
xdg_shell_popup_grab_from_seat(surface->client->shell,
|
||||
surface->popup->seat);
|
||||
|
@ -222,11 +214,8 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
|
|||
wlr_seat_keyboard_end_grab(grab->seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wl_list_remove(&surface->popup->link);
|
||||
free(surface->popup);
|
||||
surface->popup = NULL;
|
||||
surface->popup->seat = NULL;
|
||||
}
|
||||
|
||||
struct wlr_xdg_surface_v6_configure *configure, *tmp;
|
||||
|
@ -234,13 +223,12 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
|
|||
xdg_surface_configure_destroy(configure);
|
||||
}
|
||||
|
||||
surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE;
|
||||
free(surface->title);
|
||||
surface->title = NULL;
|
||||
free(surface->app_id);
|
||||
surface->app_id = NULL;
|
||||
|
||||
surface->added = surface->configured = surface->mapped = false;
|
||||
surface->configured = surface->mapped = false;
|
||||
surface->configure_serial = 0;
|
||||
if (surface->configure_idle) {
|
||||
wl_event_source_remove(surface->configure_idle);
|
||||
|
@ -253,6 +241,29 @@ static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
|
|||
memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
|
||||
}
|
||||
|
||||
static void xdg_toplevel_destroy(struct wlr_xdg_surface_v6 *surface) {
|
||||
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
|
||||
xdg_surface_unmap(surface);
|
||||
|
||||
wl_resource_set_user_data(surface->toplevel->resource, NULL);
|
||||
free(surface->toplevel);
|
||||
surface->toplevel = NULL;
|
||||
|
||||
surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE;
|
||||
}
|
||||
|
||||
static void xdg_popup_destroy(struct wlr_xdg_surface_v6 *surface) {
|
||||
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP);
|
||||
xdg_surface_unmap(surface);
|
||||
|
||||
wl_resource_set_user_data(surface->popup->resource, NULL);
|
||||
wl_list_remove(&surface->popup->link);
|
||||
free(surface->popup);
|
||||
surface->popup = NULL;
|
||||
|
||||
surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE;
|
||||
}
|
||||
|
||||
static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
|
||||
if (surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE) {
|
||||
xdg_surface_unmap(surface);
|
||||
|
@ -260,6 +271,18 @@ static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
|
|||
|
||||
wlr_signal_emit_safe(&surface->events.destroy, surface);
|
||||
|
||||
switch (surface->role) {
|
||||
case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL:
|
||||
xdg_toplevel_destroy(surface);
|
||||
break;
|
||||
case WLR_XDG_SURFACE_V6_ROLE_POPUP:
|
||||
xdg_popup_destroy(surface);
|
||||
break;
|
||||
case WLR_XDG_SURFACE_V6_ROLE_NONE:
|
||||
// This space is intentionally left blank
|
||||
break;
|
||||
}
|
||||
|
||||
wl_resource_set_user_data(surface->resource, NULL);
|
||||
wl_list_remove(&surface->link);
|
||||
wl_list_remove(&surface->surface_destroy_listener.link);
|
||||
|
@ -545,7 +568,7 @@ static void xdg_popup_resource_destroy(struct wl_resource *resource) {
|
|||
struct wlr_xdg_surface_v6 *surface =
|
||||
xdg_surface_from_xdg_popup_resource(resource);
|
||||
if (surface != NULL) {
|
||||
xdg_surface_unmap(surface);
|
||||
xdg_popup_destroy(surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -856,7 +879,7 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) {
|
|||
struct wlr_xdg_surface_v6 *surface =
|
||||
xdg_surface_from_xdg_toplevel_resource(resource);
|
||||
if (surface != NULL) {
|
||||
xdg_surface_unmap(surface);
|
||||
xdg_toplevel_destroy(surface);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue