mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-09 18:27:00 +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)
|
void GradientCurveEditor::set_points(const PointList& pts)
|
||||||
{
|
{
|
||||||
m_points = pts;
|
m_points = pts;
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ public:
|
|||||||
const wxColour& color_low = wxColour(217, 217, 217),
|
const wxColour& color_low = wxColour(217, 217, 217),
|
||||||
const wxColour& color_high = 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],
|
// 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
|
// 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).
|
// preserved as-is (NaN entries continue to use PCHIP defaults).
|
||||||
|
|||||||
@@ -154,6 +154,18 @@ MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
|
|||||||
m_preview_bmp_three = wxBitmap(img);
|
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,
|
MixedFilamentDialog::MixedFilamentDialog(wxWindow* parent,
|
||||||
const MixedFilamentResult& existing,
|
const MixedFilamentResult& existing,
|
||||||
const std::vector<std::string>& physical_colors,
|
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) {
|
m_ratio_bar->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent& e) {
|
||||||
if (m_ratio_editor_panel && m_ratio_editor_panel->IsShown())
|
if (m_ratio_editor_panel && m_ratio_editor_panel->IsShown())
|
||||||
commit_ratio_editor(true);
|
commit_ratio_editor(true);
|
||||||
m_dragging = true;
|
m_ratio_dragging = true;
|
||||||
m_ratio_bar->CaptureMouse();
|
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);
|
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)));
|
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) {
|
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);
|
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)));
|
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&) {
|
m_ratio_bar->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent&) {
|
||||||
if (m_dragging) {
|
m_ratio_dragging = false;
|
||||||
m_dragging = false;
|
if (m_ratio_bar->HasCapture())
|
||||||
if (m_ratio_bar->HasCapture())
|
m_ratio_bar->ReleaseMouse();
|
||||||
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);
|
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.
|
// clicks outside the triangle must not change the mix ratio.
|
||||||
if (!tri_contains(p, v0, v1, v2))
|
if (!tri_contains(p, v0, v1, v2))
|
||||||
return;
|
return;
|
||||||
m_dragging = true;
|
m_tri_dragging = true;
|
||||||
m_triangle_panel->CaptureMouse();
|
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);
|
TriPoint clamped = tri_clamp(p, v0, v1, v2);
|
||||||
tri_barycentric(clamped, v0, v1, v2, m_tri_wx, m_tri_wy, m_tri_wz);
|
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);
|
handle_mouse(e, true);
|
||||||
});
|
});
|
||||||
m_triangle_panel->Bind(wxEVT_MOTION, [this, handle_mouse](wxMouseEvent& e) {
|
m_triangle_panel->Bind(wxEVT_MOTION, [this, handle_mouse](wxMouseEvent& e) {
|
||||||
if (m_dragging)
|
if (m_tri_dragging)
|
||||||
handle_mouse(e, false);
|
handle_mouse(e, false);
|
||||||
});
|
});
|
||||||
m_triangle_panel->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent&) {
|
m_triangle_panel->Bind(wxEVT_LEFT_UP, [this](wxMouseEvent&) {
|
||||||
if (m_dragging) {
|
m_tri_dragging = false;
|
||||||
m_dragging = false;
|
if (m_triangle_panel->HasCapture())
|
||||||
if (m_triangle_panel->HasCapture())
|
m_triangle_panel->ReleaseMouse();
|
||||||
m_triangle_panel->ReleaseMouse();
|
});
|
||||||
}
|
m_triangle_panel->Bind(wxEVT_MOUSE_CAPTURE_LOST, [this](wxMouseCaptureLostEvent&) {
|
||||||
|
m_tri_dragging = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
sizer->Add(m_triangle_panel, 0);
|
sizer->Add(m_triangle_panel, 0);
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ public:
|
|||||||
const std::vector<std::string>& physical_names,
|
const std::vector<std::string>& physical_names,
|
||||||
const std::vector<std::string>& physical_types = {});
|
const std::vector<std::string>& physical_types = {});
|
||||||
|
|
||||||
|
~MixedFilamentDialog();
|
||||||
|
|
||||||
MixedFilamentResult get_result() const { return m_result; }
|
MixedFilamentResult get_result() const { return m_result; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -160,8 +162,11 @@ private:
|
|||||||
wxBitmap m_preview_bmp_two;
|
wxBitmap m_preview_bmp_two;
|
||||||
wxBitmap m_preview_bmp_three;
|
wxBitmap m_preview_bmp_three;
|
||||||
|
|
||||||
// Drag state
|
// Drag state. The ratio bar and the triangle picker capture the mouse
|
||||||
bool m_dragging{false};
|
// 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;
|
std::vector<size_t> m_ratio_manual_order;
|
||||||
size_t m_ratio_editor_idx{0};
|
size_t m_ratio_editor_idx{0};
|
||||||
bool m_ratio_editor_committing{false};
|
bool m_ratio_editor_committing{false};
|
||||||
|
|||||||
@@ -184,6 +184,7 @@ public:
|
|||||||
GreenSlider(wxWindow* parent, int value, int minVal, int maxVal,
|
GreenSlider(wxWindow* parent, int value, int minVal, int maxVal,
|
||||||
const wxPoint& pos = wxDefaultPosition,
|
const wxPoint& pos = wxDefaultPosition,
|
||||||
const wxSize& size = wxDefaultSize);
|
const wxSize& size = wxDefaultSize);
|
||||||
|
~GreenSlider() override;
|
||||||
int GetValue() const;
|
int GetValue() const;
|
||||||
void SetValue(int val);
|
void SetValue(int val);
|
||||||
bool Enable(bool enable = true) override;
|
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_DOWN, &GreenSlider::OnMouse, this);
|
||||||
Bind(wxEVT_LEFT_UP, &GreenSlider::OnMouse, this);
|
Bind(wxEVT_LEFT_UP, &GreenSlider::OnMouse, this);
|
||||||
Bind(wxEVT_MOTION, &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; }
|
int GreenSlider::GetValue() const { return m_value; }
|
||||||
@@ -302,7 +312,7 @@ void GreenSlider::OnMouse(wxMouseEvent& evt)
|
|||||||
|
|
||||||
if (evt.LeftDown()) {
|
if (evt.LeftDown()) {
|
||||||
m_dragging = true;
|
m_dragging = true;
|
||||||
CaptureMouse();
|
if (!HasCapture()) CaptureMouse();
|
||||||
update(evt.GetX());
|
update(evt.GetX());
|
||||||
} else if (evt.LeftUp()) {
|
} else if (evt.LeftUp()) {
|
||||||
m_dragging = false;
|
m_dragging = false;
|
||||||
@@ -1019,11 +1029,20 @@ TexturePreviewCanvas::TexturePreviewCanvas(wxWindow* parent, const wxGLAttribute
|
|||||||
Bind(wxEVT_MIDDLE_DOWN, &TexturePreviewCanvas::on_mouse, this);
|
Bind(wxEVT_MIDDLE_DOWN, &TexturePreviewCanvas::on_mouse, this);
|
||||||
Bind(wxEVT_MIDDLE_UP, &TexturePreviewCanvas::on_mouse, this);
|
Bind(wxEVT_MIDDLE_UP, &TexturePreviewCanvas::on_mouse, this);
|
||||||
Bind(wxEVT_MOTION, &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);
|
Bind(wxEVT_LEAVE_WINDOW, &TexturePreviewCanvas::on_mouse, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
TexturePreviewCanvas::~TexturePreviewCanvas()
|
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) {
|
if (m_context) {
|
||||||
SetCurrent(*m_context);
|
SetCurrent(*m_context);
|
||||||
if (m_tex_id)
|
if (m_tex_id)
|
||||||
|
|||||||
Reference in New Issue
Block a user