From 38398e2d77d57dc06b67ec88a54091c897915602 Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Sat, 23 Jun 2018 16:24:11 +1000 Subject: Implement atomic layout updates for tree operations This implements atomic layout updates for when views map, reparent or unmap. --- sway/tree/view.c | 76 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) (limited to 'sway/tree/view.c') diff --git a/sway/tree/view.c b/sway/tree/view.c index 658a94e8..cb36f123 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -25,47 +25,60 @@ void view_init(struct sway_view *view, enum sway_view_type type, view->impl = impl; view->executed_criteria = create_list(); view->marks = create_list(); - view->instructions = create_list(); wl_signal_init(&view->events.unmap); } -void view_destroy(struct sway_view *view) { - if (view == NULL) { +void view_free(struct sway_view *view) { + if (!sway_assert(view->surface == NULL, "Tried to free mapped view")) { return; } - - if (view->surface != NULL) { - view_unmap(view); + if (!sway_assert(view->destroying, + "Tried to free view which wasn't marked as destroying")) { + return; } - - if (!sway_assert(view->instructions->length == 0, - "Tried to destroy view with pending instructions")) { + if (!sway_assert(view->swayc == NULL, + "Tried to free view which still has a swayc " + "(might have a pending transaction?)")) { return; } - list_free(view->executed_criteria); - for (int i = 0; i < view->marks->length; ++i) { - free(view->marks->items[i]); - } + list_foreach(view->marks, free); list_free(view->marks); - list_free(view->instructions); - wlr_texture_destroy(view->marks_focused); wlr_texture_destroy(view->marks_focused_inactive); wlr_texture_destroy(view->marks_unfocused); wlr_texture_destroy(view->marks_urgent); - container_destroy(view->swayc); - - if (view->impl->destroy) { - view->impl->destroy(view); + if (view->impl->free) { + view->impl->free(view); } else { free(view); } } +/** + * The view may or may not be involved in a transaction. For example, a view may + * unmap then attempt to destroy itself before we've applied the new layout. If + * an unmapping view is still involved in a transaction then it'll still have a + * swayc. + * + * If there's no transaction we can simply free the view. Otherwise the + * destroying flag will make the view get freed when the transaction is + * finished. + */ +void view_destroy(struct sway_view *view) { + if (!sway_assert(view->surface == NULL, "Tried to destroy a mapped view")) { + return; + } + view->destroying = true; + + if (!view->swayc) { + view_free(view); + } +} + const char *view_get_title(struct sway_view *view) { if (view->impl->get_string_prop) { return view->impl->get_string_prop(view, VIEW_PROP_TITLE); @@ -356,6 +369,9 @@ static void view_get_layout_box(struct sway_view *view, struct wlr_box *box) { void view_for_each_surface(struct sway_view *view, wlr_surface_iterator_func_t iterator, void *user_data) { + if (!view->surface) { + return; + } if (view->impl->for_each_surface) { view->impl->for_each_surface(view, iterator, user_data); } else { @@ -523,11 +539,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { view_handle_container_reparent(&view->container_reparent, NULL); } -void view_unmap(struct sway_view *view) { - if (!sway_assert(view->surface != NULL, "cannot unmap unmapped view")) { - return; - } - +struct sway_container *view_unmap(struct sway_view *view) { wl_signal_emit(&view->events.unmap, view); if (view->is_fullscreen) { @@ -535,22 +547,10 @@ void view_unmap(struct sway_view *view) { ws->sway_workspace->fullscreen = NULL; } - container_damage_whole(view->swayc); - wl_list_remove(&view->surface_new_subsurface.link); wl_list_remove(&view->container_reparent.link); - struct sway_container *parent = container_destroy(view->swayc); - - view->swayc = NULL; - view->surface = NULL; - - if (view->title_format) { - free(view->title_format); - view->title_format = NULL; - } - - arrange_and_commit(parent); + return container_destroy(view->swayc); } void view_update_position(struct sway_view *view, double lx, double ly) { @@ -924,7 +924,7 @@ void view_update_marks_textures(struct sway_view *view) { } bool view_is_visible(struct sway_view *view) { - if (!view->swayc) { + if (!view->swayc || view->swayc->destroying) { return false; } struct sway_container *workspace = -- cgit v1.2.3-54-g00ecf