mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-24 18:37:39 +00:00
Fix UI hanging on Mac
This commit is contained in:
@@ -85,6 +85,14 @@ GradientCurveEditor::GradientCurveEditor(wxWindow* parent,
|
||||
});
|
||||
}
|
||||
|
||||
GradientCurveEditor::~GradientCurveEditor()
|
||||
{
|
||||
// See MixedFilamentDialog::~MixedFilamentDialog: a widget destroyed while it
|
||||
// still holds the capture wedges mouse input for the whole application.
|
||||
if (HasCapture())
|
||||
ReleaseMouse();
|
||||
}
|
||||
|
||||
void GradientCurveEditor::set_points(const PointList& pts)
|
||||
{
|
||||
m_points = pts;
|
||||
|
||||
@@ -36,6 +36,8 @@ public:
|
||||
const wxColour& color_low = wxColour(217, 217, 217),
|
||||
const wxColour& color_high = wxColour(217, 217, 217));
|
||||
|
||||
~GradientCurveEditor() override;
|
||||
|
||||
// Replace the entire point list. The widget enforces x in [0,1], y in [0,1],
|
||||
// sorts by x, and clamps the first / last x to 0 / 1. Tangent overrides are
|
||||
// preserved as-is (NaN entries continue to use PCHIP defaults).
|
||||
|
||||
@@ -154,6 +154,18 @@ MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
|
||||
m_preview_bmp_three = wxBitmap(img);
|
||||
}
|
||||
|
||||
MixedFilamentDialog::~MixedFilamentDialog()
|
||||
{
|
||||
// Backstop: a child must never be destroyed while it still holds the mouse
|
||||
// capture. wxWidgets only asserts about this (compiled out in release), and
|
||||
// the macOS port never unwinds its capture stack, so the stale entry would
|
||||
// make wxNSWindow::sendEvent swallow every mouse event in the application.
|
||||
if (m_ratio_bar && m_ratio_bar->HasCapture())
|
||||
m_ratio_bar->ReleaseMouse();
|
||||
if (m_triangle_panel && m_triangle_panel->HasCapture())
|
||||
m_triangle_panel->ReleaseMouse();
|
||||
}
|
||||
|
||||
MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
|
||||
const MixedFilamentResult& existing,
|
||||
const std::vector<std::string>& physical_colors,
|
||||
@@ -892,24 +904,30 @@ wxBoxSizer* MixedFilamentDialog::create_ratio_slider()
|
||||
m_ratio_bar->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||
if (m_ratio_editor_panel && m_ratio_editor_panel->IsShown())
|
||||
commit_ratio_editor(true);
|
||||
m_dragging = true;
|
||||
m_ratio_bar->CaptureMouse();
|
||||
m_ratio_dragging = true;
|
||||
if (!m_ratio_bar->HasCapture())
|
||||
m_ratio_bar->CaptureMouse();
|
||||
int new_ratio = 100 - (int)(e.GetX() * 100.0 / m_ratio_bar->GetClientSize().GetWidth() + 0.5);
|
||||
on_ratio_changed(std::max(MIN_COMPONENT_RATIO, std::min(100 - MIN_COMPONENT_RATIO, new_ratio)));
|
||||
});
|
||||
|
||||
m_ratio_bar->Bind(wxEVT_MOTION, [this](wxMouseEvent& e) {
|
||||
if (!m_dragging) return;
|
||||
if (!m_ratio_dragging) return;
|
||||
int new_ratio = 100 - (int)(e.GetX() * 100.0 / m_ratio_bar->GetClientSize().GetWidth() + 0.5);
|
||||
on_ratio_changed(std::max(MIN_COMPONENT_RATIO, std::min(100 - MIN_COMPONENT_RATIO, new_ratio)));
|
||||
});
|
||||
|
||||
// Release whenever the capture is held, not only when the drag flag is set:
|
||||
// the flag can be cleared behind our back, and a capture that outlives the
|
||||
// widget wedges mouse input for the whole application.
|
||||
m_ratio_bar->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent&) {
|
||||
if (m_dragging) {
|
||||
m_dragging = false;
|
||||
if (m_ratio_bar->HasCapture())
|
||||
m_ratio_bar->ReleaseMouse();
|
||||
}
|
||||
m_ratio_dragging = false;
|
||||
if (m_ratio_bar->HasCapture())
|
||||
m_ratio_bar->ReleaseMouse();
|
||||
});
|
||||
|
||||
m_ratio_bar->Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) {
|
||||
m_ratio_dragging = false;
|
||||
});
|
||||
|
||||
sizer->Add(m_ratio_bar, 0, wxEXPAND);
|
||||
@@ -1122,11 +1140,12 @@ wxBoxSizer* MixedFilamentDialog::create_triangle_picker()
|
||||
// clicks outside the triangle must not change the mix ratio.
|
||||
if (!tri_contains(p, v0, v1, v2))
|
||||
return;
|
||||
m_dragging = true;
|
||||
m_triangle_panel->CaptureMouse();
|
||||
m_tri_dragging = true;
|
||||
if (!m_triangle_panel->HasCapture())
|
||||
m_triangle_panel->CaptureMouse();
|
||||
}
|
||||
|
||||
if (!m_dragging) return;
|
||||
if (!m_tri_dragging) return;
|
||||
|
||||
TriPoint clamped = tri_clamp(p, v0, v1, v2);
|
||||
tri_barycentric(clamped, v0, v1, v2, m_tri_wx, m_tri_wy, m_tri_wz);
|
||||
@@ -1161,15 +1180,16 @@ wxBoxSizer* MixedFilamentDialog::create_triangle_picker()
|
||||
handle_mouse(e, true);
|
||||
});
|
||||
m_triangle_panel->Bind(wxEVT_MOTION, [this, handle_mouse](wxMouseEvent& e) {
|
||||
if (m_dragging)
|
||||
if (m_tri_dragging)
|
||||
handle_mouse(e, false);
|
||||
});
|
||||
m_triangle_panel->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent&) {
|
||||
if (m_dragging) {
|
||||
m_dragging = false;
|
||||
if (m_triangle_panel->HasCapture())
|
||||
m_triangle_panel->ReleaseMouse();
|
||||
}
|
||||
m_tri_dragging = false;
|
||||
if (m_triangle_panel->HasCapture())
|
||||
m_triangle_panel->ReleaseMouse();
|
||||
});
|
||||
m_triangle_panel->Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) {
|
||||
m_tri_dragging = false;
|
||||
});
|
||||
|
||||
sizer->Add(m_triangle_panel, 0);
|
||||
|
||||
@@ -53,6 +53,8 @@ public:
|
||||
const std::vector<std::string>& physical_names,
|
||||
const std::vector<std::string>& physical_types = {});
|
||||
|
||||
~MixedFilamentDialog();
|
||||
|
||||
MixedFilamentResult get_result() const { return m_result; }
|
||||
|
||||
protected:
|
||||
@@ -160,8 +162,11 @@ private:
|
||||
wxBitmap m_preview_bmp_two;
|
||||
wxBitmap m_preview_bmp_three;
|
||||
|
||||
// Drag state
|
||||
bool m_dragging{false};
|
||||
// Drag state. The ratio bar and the triangle picker capture the mouse
|
||||
// independently, so they must not share a flag: a mouse-up on one would
|
||||
// otherwise clear the other's flag and skip its ReleaseMouse().
|
||||
bool m_ratio_dragging{false};
|
||||
bool m_tri_dragging{false};
|
||||
std::vector<size_t> m_ratio_manual_order;
|
||||
size_t m_ratio_editor_idx{0};
|
||||
bool m_ratio_editor_committing{false};
|
||||
|
||||
@@ -184,6 +184,7 @@ public:
|
||||
GreenSlider(wxWindow* parent, int value, int minVal, int maxVal,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize);
|
||||
~GreenSlider() override;
|
||||
int GetValue() const;
|
||||
void SetValue(int val);
|
||||
bool Enable(bool enable = true) override;
|
||||
@@ -213,6 +214,15 @@ GreenSlider::GreenSlider(wxWindow* parent, int value, int minVal, int maxVal,
|
||||
Bind(wxEVT_LEFT_DOWN, &GreenSlider::OnMouse, this);
|
||||
Bind(wxEVT_LEFT_UP, &GreenSlider::OnMouse, this);
|
||||
Bind(wxEVT_MOTION, &GreenSlider::OnMouse, this);
|
||||
Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) { m_dragging = false; });
|
||||
}
|
||||
|
||||
GreenSlider::~GreenSlider()
|
||||
{
|
||||
// See MixedFilamentDialog::~MixedFilamentDialog: a widget destroyed while it
|
||||
// still holds the capture wedges mouse input for the whole application.
|
||||
if (HasCapture())
|
||||
ReleaseMouse();
|
||||
}
|
||||
|
||||
int GreenSlider::GetValue() const { return m_value; }
|
||||
@@ -302,7 +312,7 @@ void GreenSlider::OnMouse(wxMouseEvent& evt)
|
||||
|
||||
if (evt.LeftDown()) {
|
||||
m_dragging = true;
|
||||
CaptureMouse();
|
||||
if (!HasCapture()) CaptureMouse();
|
||||
update(evt.GetX());
|
||||
} else if (evt.LeftUp()) {
|
||||
m_dragging = false;
|
||||
@@ -1019,11 +1029,20 @@ TexturePreviewCanvas::TexturePreviewCanvas(wxWindow* parent, const wxGLAttribute
|
||||
Bind(wxEVT_MIDDLE_DOWN, &TexturePreviewCanvas::on_mouse, this);
|
||||
Bind(wxEVT_MIDDLE_UP, &TexturePreviewCanvas::on_mouse, this);
|
||||
Bind(wxEVT_MOTION, &TexturePreviewCanvas::on_mouse, this);
|
||||
Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) {
|
||||
m_drag_mode = DragMode::None;
|
||||
m_reset_overlay_pressed = false;
|
||||
});
|
||||
Bind(wxEVT_LEAVE_WINDOW, &TexturePreviewCanvas::on_mouse, this);
|
||||
}
|
||||
|
||||
TexturePreviewCanvas::~TexturePreviewCanvas()
|
||||
{
|
||||
// See MixedFilamentDialog::~MixedFilamentDialog: a widget destroyed while it
|
||||
// still holds the capture wedges mouse input for the whole application.
|
||||
if (HasCapture())
|
||||
ReleaseMouse();
|
||||
|
||||
if (m_context) {
|
||||
SetCurrent(*m_context);
|
||||
if (m_tex_id)
|
||||
|
||||
Reference in New Issue
Block a user