From ba421e45f7b97c5e7ba28efe4f148fb3ba87a22c Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 13 May 2016 20:32:53 +0100 Subject: [PATCH] Delay window deletion until we get back to main loop Avoid WinResize hooks while redrawing, ensure window resize only take place while handling user input. Fixes #672 --- src/buffer_manager.cc | 1 + src/client.cc | 2 +- src/client_manager.cc | 9 +++++++++ src/client_manager.hh | 4 +++- src/main.cc | 1 + src/window.cc | 11 ++++------- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/buffer_manager.cc b/src/buffer_manager.cc index bb9f79028..82b17037a 100644 --- a/src/buffer_manager.cc +++ b/src/buffer_manager.cc @@ -109,6 +109,7 @@ void BufferManager::clear_buffer_trash() // Do that again, to be tolerant in some corner cases, where a buffer is // deleted during its creation ClientManager::instance().ensure_no_client_uses_buffer(*buffer); + ClientManager::instance().clear_window_trash(); delete buffer; } diff --git a/src/client.cc b/src/client.cc index 6d875c39e..b91a2254b 100644 --- a/src/client.cc +++ b/src/client.cc @@ -85,7 +85,7 @@ void Client::handle_available_input(EventMode mode) else if (*key == Key::FocusOut) context().hooks().run_hook("FocusOut", context().name(), context()); else if (key->modifiers == Key::Modifiers::Resize) - force_redraw(); + m_window->set_dimensions(m_ui->dimensions()); else m_input_handler.handle_key(*key); } diff --git a/src/client_manager.cc b/src/client_manager.cc index aff88d93c..961655380 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -143,9 +143,18 @@ void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer) auto end = std::remove_if(m_free_windows.begin(), m_free_windows.end(), [&buffer](const WindowAndSelections& ws) { return &ws.window->buffer() == &buffer; }); + + for (auto it = end; it != m_free_windows.end(); ++it) + m_window_trash.push_back(std::move(it->window)); + m_free_windows.erase(end, m_free_windows.end()); } +void ClientManager::clear_window_trash() +{ + m_window_trash.clear(); +} + bool ClientManager::validate_client_name(StringView name) const { return const_cast(this)->get_client_ifp(name) == nullptr; diff --git a/src/client_manager.hh b/src/client_manager.hh index c6ba1c356..7f2b603c9 100644 --- a/src/client_manager.hh +++ b/src/client_manager.hh @@ -35,7 +35,7 @@ public: void clear(); - void ensure_no_client_uses_buffer(Buffer& buffer); + void ensure_no_client_uses_buffer(Buffer& buffer); WindowAndSelections get_free_window(Buffer& buffer); void add_free_window(std::unique_ptr&& window, SelectionList selections); @@ -57,11 +57,13 @@ public: CandidateList complete_client_name(StringView name, ByteCount cursor_pos = -1) const; + void clear_window_trash(); private: String generate_name() const; ClientList m_clients; Vector m_free_windows; + Vector> m_window_trash; }; } diff --git a/src/main.cc b/src/main.cc index 994edeeef..f3d8b41f3 100644 --- a/src/main.cc +++ b/src/main.cc @@ -580,6 +580,7 @@ int run_server(StringView session, StringView init_command, client_manager.redraw_clients(); event_manager.handle_next_events(EventMode::Normal); client_manager.handle_pending_inputs(); + client_manager.clear_window_trash(); buffer_manager.clear_buffer_trash(); string_registry.purge_unused(); diff --git a/src/window.cc b/src/window.cc index 0e7c3b96f..de3f4ea46 100644 --- a/src/window.cc +++ b/src/window.cc @@ -80,8 +80,7 @@ Window::Setup Window::build_setup(const Context& context) const for (auto& sel : context.selections()) selections.push_back({sel.cursor(), sel.anchor()}); - return { m_position, - context.client().dimensions(), + return { m_position, m_dimensions, context.buffer().timestamp(), context.selections().main_index(), std::move(selections) }; @@ -92,7 +91,7 @@ bool Window::needs_redraw(const Context& context) const auto& selections = context.selections(); if (m_position != m_last_setup.position or - context.client().dimensions() != m_last_setup.dimensions or + m_dimensions != m_last_setup.dimensions or context.buffer().timestamp() != m_last_setup.timestamp or selections.main_index() != m_last_setup.main_selection or selections.size() != m_last_setup.selections.size()) @@ -120,7 +119,6 @@ const DisplayBuffer& Window::update_display_buffer(const Context& context) DisplayBuffer::LineList& lines = m_display_buffer.lines(); lines.clear(); - set_dimensions(context.client().dimensions()); if (m_dimensions == CharCoord{0,0}) return m_display_buffer; @@ -365,9 +363,8 @@ void Window::clear_display_buffer() void Window::on_option_changed(const Option& option) { - run_hook_in_own_context("WinSetOption", - format("{}={}", option.name(), option.get_as_string())); - + run_hook_in_own_context("WinSetOption", format("{}={}", option.name(), + option.get_as_string())); // an highlighter might depend on the option, so we need to redraw force_redraw(); }