From f2ccbfc8b5fae02bf1788687d9ce2cdcd7326531 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Thu, 16 Jul 2026 21:25:30 +0800 Subject: [PATCH] Open the plugin terminal off the webview callback stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit open_terminal_dialog is reached from the plugins dialog's webview command, and TerminalDialog hosts a webview of its own — same class as the plugin-window crash. Defer the window work via CallAfter, guard the re-front Show() per #13657, and drop the redundant Raise() on creation. --- src/slic3r/GUI/GUI_App.cpp | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 901b653a5a..ed990c3ec6 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -8255,22 +8255,32 @@ void GUI_App::open_plugins_dialog(size_t open_on_tab, const std::string& highlig void GUI_App::open_terminal_dialog() { - if (m_terminal_dlg) { + // Reached from the plugins dialog's webview ("open_terminal" command), i.e. from + // inside the webview script-message callback, which GTK/macOS deliver synchronously + // (see ui_create_window in PluginHostUi.cpp). TerminalDialog hosts a webview of its + // own, so creating or presenting it on that stack is the same class as the Linux + // gtk_window_present crash — defer all window work to a clean main-loop iteration. + CallAfter([this]() { + if (m_terminal_dlg) { + // Re-front the existing window; guard Show() per #13657 (GTK re-enters + // layout when showing an already-visible window). + if (!m_terminal_dlg->IsShown()) + m_terminal_dlg->Show(); + m_terminal_dlg->Raise(); + return; + } + + m_terminal_dlg = new TerminalDialog(mainframe, wxID_ANY, _L("Plugin Terminal"), + wxDefaultPosition, wxSize(820, 600)); + m_terminal_dlg->Bind(wxEVT_DESTROY, [this](wxWindowDestroyEvent& event) { + if (event.GetEventObject() == m_terminal_dlg) + m_terminal_dlg = nullptr; + event.Skip(); + }); + + // Show() alone activates and fronts a freshly created window on every platform. m_terminal_dlg->Show(); - m_terminal_dlg->Raise(); - return; - } - - m_terminal_dlg = new TerminalDialog(mainframe, wxID_ANY, _L("Plugin Terminal"), - wxDefaultPosition, wxSize(820, 600)); - m_terminal_dlg->Bind(wxEVT_DESTROY, [this](wxWindowDestroyEvent& event) { - if (event.GetEventObject() == m_terminal_dlg) - m_terminal_dlg = nullptr; - event.Skip(); }); - - m_terminal_dlg->Show(); - m_terminal_dlg->Raise(); } void GUI_App::open_exportpresetbundledialog(size_t open_on_tab, const std::string& highlight_option)