sway_view_child: add listener for view unmap

Since not all child views's have an unmap event, it is possible for it
to still be mapped (default state) in the destruction handler. When
the destruction handler is called, the corresponding view may have
already been freed and the memory location reallocated. This adds a
listener for the view unmapping and removes the mapped status. This
ensures that the child view is damaged due to destruction while the
view still exists and not after.
This commit is contained in:
Brian Ashworth 2019-03-09 02:23:20 -05:00 committed by emersion
parent 20c4d242f6
commit 017a7c4da1
2 changed files with 13 additions and 0 deletions

View File

@ -202,6 +202,7 @@ struct sway_view_child {
struct wl_listener surface_map;
struct wl_listener surface_unmap;
struct wl_listener surface_destroy;
struct wl_listener view_unmap;
};
struct sway_subsurface {

View File

@ -820,6 +820,14 @@ static void view_child_handle_surface_unmap(struct wl_listener *listener,
child->mapped = false;
}
static void view_child_handle_view_unmap(struct wl_listener *listener,
void *data) {
struct sway_view_child *child =
wl_container_of(listener, child, view_unmap);
view_child_damage(child, true);
child->mapped = false;
}
void view_child_init(struct sway_view_child *child,
const struct sway_view_child_impl *impl, struct sway_view *view,
struct wlr_surface *surface) {
@ -840,6 +848,9 @@ void view_child_init(struct sway_view_child *child,
child->surface_map.notify = view_child_handle_surface_map;
child->surface_unmap.notify = view_child_handle_surface_unmap;
wl_signal_add(&view->events.unmap, &child->view_unmap);
child->view_unmap.notify = view_child_handle_view_unmap;
struct sway_output *output = child->view->container->workspace->output;
wlr_surface_send_enter(child->surface, output->wlr_output);
@ -853,6 +864,7 @@ void view_child_destroy(struct sway_view_child *child) {
wl_list_remove(&child->surface_commit.link);
wl_list_remove(&child->surface_destroy.link);
wl_list_remove(&child->view_unmap.link);
if (child->impl && child->impl->destroy) {
child->impl->destroy(child);