diff options
author | Brian Ashworth <bosrsf04@gmail.com> | 2019-08-14 20:36:08 -0400 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2019-08-15 11:19:06 +0300 |
commit | 9914784594713f184c58e37def1d136c6af394a9 (patch) | |
tree | 66fccc7615f45a2ccec11d1f351e6209bd515ee6 | |
parent | 8d2ea9544b527b7a1e31bf559d2182782bc6107e (diff) |
wlr_xdg_toplevel: reparent on parent unmap
From the xdg-shell specification:
If the parent is unmapped then its children are managed as
though the parent of the now-unmapped parent has become the
parent of this surface. If no parent exists for the now-unmapped
parent then the children are managed as though they have no
parent surface.
-rw-r--r-- | include/wlr/types/wlr_xdg_shell.h | 4 | ||||
-rw-r--r-- | types/xdg_shell/wlr_xdg_surface.c | 4 | ||||
-rw-r--r-- | types/xdg_shell/wlr_xdg_toplevel.c | 31 |
3 files changed, 36 insertions, 3 deletions
diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index e8c12ae9..70572bf5 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -117,9 +117,11 @@ struct wlr_xdg_toplevel_state { struct wlr_xdg_toplevel { struct wl_resource *resource; struct wlr_xdg_surface *base; - struct wlr_xdg_surface *parent; bool added; + struct wlr_xdg_surface *parent; + struct wl_listener parent_unmap; + struct wlr_xdg_toplevel_state client_pending; struct wlr_xdg_toplevel_state server_pending; struct wlr_xdg_toplevel_state current; diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index e3f13e0e..fcd3e0c9 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -41,6 +41,10 @@ void unmap_xdg_surface(struct wlr_xdg_surface *surface) { switch (surface->role) { case WLR_XDG_SURFACE_ROLE_TOPLEVEL: + if (surface->toplevel->parent) { + wl_list_remove(&surface->toplevel->parent_unmap.link); + surface->toplevel->parent = NULL; + } free(surface->toplevel->title); surface->toplevel->title = NULL; free(surface->toplevel->app_id); diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 96bb0537..3524bd34 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -207,6 +207,34 @@ struct wlr_xdg_surface *wlr_xdg_surface_from_toplevel_resource( return wl_resource_get_user_data(resource); } +static void set_parent(struct wlr_xdg_surface *surface, + struct wlr_xdg_surface *parent); + +static void handle_parent_unmap(struct wl_listener *listener, void *data) { + struct wlr_xdg_toplevel *toplevel = + wl_container_of(listener, toplevel, parent_unmap); + set_parent(toplevel->base, toplevel->parent->toplevel->parent); +} + +static void set_parent(struct wlr_xdg_surface *surface, + struct wlr_xdg_surface *parent) { + assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); + assert(!parent || parent->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL); + + if (surface->toplevel->parent) { + wl_list_remove(&surface->toplevel->parent_unmap.link); + } + + surface->toplevel->parent = parent; + if (surface->toplevel->parent) { + surface->toplevel->parent_unmap.notify = handle_parent_unmap; + wl_signal_add(&surface->toplevel->parent->events.unmap, + &surface->toplevel->parent_unmap); + } + + wlr_signal_emit_safe(&surface->toplevel->events.set_parent, surface); +} + static void xdg_toplevel_handle_set_parent(struct wl_client *client, struct wl_resource *resource, struct wl_resource *parent_resource) { struct wlr_xdg_surface *surface = @@ -217,8 +245,7 @@ static void xdg_toplevel_handle_set_parent(struct wl_client *client, parent = wlr_xdg_surface_from_toplevel_resource(parent_resource); } - surface->toplevel->parent = parent; - wlr_signal_emit_safe(&surface->toplevel->events.set_parent, surface); + set_parent(surface, parent); } static void xdg_toplevel_handle_set_title(struct wl_client *client, |