mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-27 02:41:17 +00:00
The Design tab's MCP socket must not wait for someone to click the tab
Building the Design tab on first use (1750c52211) leaves m_design_panel null
until a human selects the tab. McpControl::handle_on_main refused every verb
while it was null, so start_mcp_control_if_enabled() opened the socket and
then answered "Design panel not ready" to everything — for the whole session
if nobody clicked. That is precisely the headless case the socket exists for:
the click-test rig drives this app over it with no window manager and no user.
MainFrame::ensure_design_panel() now builds the panel on demand and returns
it; the tab activation and the MCP dispatcher both go through it, so there is
one construction site rather than two. Safe to build wx controls there: that
handler is dispatched on the main thread by CallAfter, as its own comment
says.
The startup saving is untouched — a launch that never opens the tab and never
speaks MCP still builds nothing.
Verified: libslic3r_gui builds clean 745/745; fork parity green with snaporca,
which carries the same fix (McpControl.cpp is a byte-identical shared source).
This commit is contained in:
@@ -1990,9 +1990,12 @@ json action_set_feature_expr(DesignPanel* panel, const json& params)
|
|||||||
std::string handle_on_main(const std::string& method, const json& params, const json& id)
|
std::string handle_on_main(const std::string& method, const json& params, const json& id)
|
||||||
{
|
{
|
||||||
MainFrame* mf = wxGetApp().mainframe;
|
MainFrame* mf = wxGetApp().mainframe;
|
||||||
if (!mf || !mf->m_design_panel)
|
// The panel is built on first use, and in a headless session nobody clicks the tab that
|
||||||
|
// would build it -- so build it here rather than refusing. Safe: this runs on the main
|
||||||
|
// thread (see the CallAfter that dispatches us).
|
||||||
|
DesignPanel* panel = mf ? mf->ensure_design_panel() : nullptr;
|
||||||
|
if (!panel)
|
||||||
return rpc_error(id, -32001, "Design panel not ready");
|
return rpc_error(id, -32001, "Design panel not ready");
|
||||||
DesignPanel* panel = mf->m_design_panel;
|
|
||||||
|
|
||||||
// Stale-id guard, checked here rather than in each handler.
|
// Stale-id guard, checked here rather than in each handler.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1245,6 +1245,19 @@ void MainFrame::show_option(bool show)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SLIC3R_CAD
|
||||||
|
DesignPanel* MainFrame::ensure_design_panel()
|
||||||
|
{
|
||||||
|
if (m_design_panel == nullptr && m_design_page != nullptr) {
|
||||||
|
wxBusyCursor busy;
|
||||||
|
m_design_panel = new DesignPanel(m_design_page);
|
||||||
|
m_design_page->GetSizer()->Add(m_design_panel, 1, wxEXPAND);
|
||||||
|
m_design_page->Layout();
|
||||||
|
}
|
||||||
|
return m_design_panel;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void MainFrame::init_tabpanel() {
|
void MainFrame::init_tabpanel() {
|
||||||
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on
|
// wxNB_NOPAGETHEME: Disable Windows Vista theme for the Notebook background. The theme performance is terrible on
|
||||||
// Windows 10 with multiple high resolution displays connected.
|
// Windows 10 with multiple high resolution displays connected.
|
||||||
@@ -1290,12 +1303,7 @@ void MainFrame::init_tabpanel() {
|
|||||||
// Built on first activation, never at startup: the panel creates several hundred
|
// Built on first activation, never at startup: the panel creates several hundred
|
||||||
// controls and its own GL canvas, which a user who does not open the tab should
|
// controls and its own GL canvas, which a user who does not open the tab should
|
||||||
// not pay for.
|
// not pay for.
|
||||||
if (m_design_panel == nullptr) {
|
ensure_design_panel();
|
||||||
wxBusyCursor busy;
|
|
||||||
m_design_panel = new DesignPanel(m_design_page);
|
|
||||||
m_design_page->GetSizer()->Add(m_design_panel, 1, wxEXPAND);
|
|
||||||
m_design_page->Layout();
|
|
||||||
}
|
|
||||||
// Re-sync the Design bed to the active printer: the panel is built before the
|
// Re-sync the Design bed to the active printer: the panel is built before the
|
||||||
// printer profile is fully applied, so its bed must refresh on activation or the
|
// printer profile is fully applied, so its bed must refresh on activation or the
|
||||||
// grid (true bed) spills past the stale default bed quad.
|
// grid (true bed) spills past the stale default bed quad.
|
||||||
|
|||||||
@@ -391,6 +391,11 @@ public:
|
|||||||
// selected, so everything the Design panel builds stays off the startup path.
|
// selected, so everything the Design panel builds stays off the startup path.
|
||||||
wxPanel* m_design_page { nullptr };
|
wxPanel* m_design_page { nullptr };
|
||||||
DesignPanel* m_design_panel { nullptr };
|
DesignPanel* m_design_panel { nullptr };
|
||||||
|
// Builds the Design panel if it does not exist yet and returns it (null only before the
|
||||||
|
// placeholder page itself exists). Main thread only -- it creates wx controls. Both the
|
||||||
|
// tab activation and the MCP socket go through this: the socket is driven headlessly,
|
||||||
|
// with nobody to click the tab, and without this every verb would answer "not ready".
|
||||||
|
DesignPanel* ensure_design_panel();
|
||||||
#endif
|
#endif
|
||||||
//BBS: GUI refactor
|
//BBS: GUI refactor
|
||||||
MonitorPanel* m_monitor{ nullptr };
|
MonitorPanel* m_monitor{ nullptr };
|
||||||
|
|||||||
Reference in New Issue
Block a user