fix: freezing caused by dynamically hidden printer edit button (#14010)

* fix: freezing caused by dynamically hidden printer edit button

* track hover state of individual widgets
This commit is contained in:
spr0u
2026-06-06 07:39:40 -05:00
committed by GitHub
parent ec9da2e218
commit 602ec0b2ce

View File

@@ -1796,39 +1796,35 @@ Sidebar::Sidebar(Plater *parent)
});
*/
// ORCA use Show/Hide to gain text area instead using blank icon. also manages hover effect for border
auto printer_preset_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_printer_preset, p->btn_edit_printer, p->image_printer, p->combo_printer}) {
w->Bind(wxEVT_ENTER_WINDOW, [this, panel_color](wxMouseEvent &e) {
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, printer_preset_hovered](wxMouseEvent &e) {
printer_preset_hovered->insert(w);
if(!p->combo_printer->HasFocus())
p->panel_printer_preset->SetBorderColor(panel_color.bd_hover);
if(!p->btn_edit_printer->IsShown()){
p->btn_edit_printer->Show();
p->panel_printer_preset->Layout();
}
e.Skip();
});
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
// Orca: if the edit button is already hidden the handler has no
// state to change, so skip the expensive wxFindWindowAtPoint tree
// walk. Without this guard, when the parent window is on an
// inactive Hyprland/Wayland workspace, GTK keeps delivering
// synthetic leave events and the Hide()+Layout() below re-enters
// the same handler in a feedback loop that pegs a CPU core.
// (IsShownOnScreen() can't be used here — see Plater.cpp:9304.)
if (!p->btn_edit_printer->IsShown()) { e.Skip(); return; }
// Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!next_w || !p->panel_printer_preset->IsDescendant(next_w)){
if(!p->combo_printer->HasFocus())
p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
p->btn_edit_printer->Hide();
p->panel_printer_preset->Layout();
}
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, printer_preset_hovered](wxMouseEvent &e) {
printer_preset_hovered->erase(w);
if (printer_preset_hovered->empty() && !p->combo_printer->HasFocus())
p->panel_printer_preset->SetBorderColor(panel_color.bd_normal);
e.Skip();
});
}
// Perform show/hide in wxEVT_IDLE after enter/leave events have settled.
// This prevents the extraneous enter/leave events generated by the
// layout change itself from causing a feedback loop.
Bind(wxEVT_IDLE, [this, printer_preset_hovered](wxIdleEvent &e) {
auto hovered = !printer_preset_hovered->empty();
if (p->btn_edit_printer->IsShown() != hovered) {
if (hovered) {
p->btn_edit_printer->Show();
} else {
p->btn_edit_printer->Hide();
}
p->panel_printer_preset->Layout();
}
});
// ORCA unified Nozzle diameter selection
p->panel_nozzle_dia = new StaticBox(p->m_panel_printer_content);
@@ -1874,19 +1870,17 @@ Sidebar::Sidebar(Plater *parent)
p->label_nozzle_type->SetMaxSize(FromDIP(wxSize(56, -1)));
// highlight border on hover
auto nozzle_dia_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_nozzle_dia, p->label_nozzle_title, p->label_nozzle_type, p->combo_nozzle_dia}) {
w->Bind(wxEVT_ENTER_WINDOW, [this, panel_color](wxMouseEvent &e) {
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, nozzle_dia_hovered](wxMouseEvent &e) {
nozzle_dia_hovered->insert(w);
if(!p->combo_nozzle_dia->HasFocus())
p->panel_nozzle_dia->SetBorderColor(panel_color.bd_hover);
e.Skip();
});
w->Bind(wxEVT_LEAVE_WINDOW, [this, panel_color](wxMouseEvent &e) {
// Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!p->combo_nozzle_dia->HasFocus() && (!next_w || !p->panel_nozzle_dia->IsDescendant(next_w)))
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, nozzle_dia_hovered](wxMouseEvent &e) {
nozzle_dia_hovered->erase(w);
if (nozzle_dia_hovered->empty() && !p->combo_nozzle_dia->HasFocus())
p->panel_nozzle_dia->SetBorderColor(panel_color.bd_normal);
e.Skip();
});
@@ -1946,21 +1940,19 @@ Sidebar::Sidebar(Plater *parent)
p->combo_printer_bed->Bind(wxEVT_KILL_FOCUS, [this, bed_focus_bg](auto& e) {bed_focus_bg(false); e.Skip();});
// highlight border on hover
auto printer_bed_hovered = std::make_shared<std::unordered_set<wxWindow*>>();
for (wxWindow *w : std::initializer_list<wxWindow *>{p->panel_printer_bed, p->image_printer_bed, p->combo_printer_bed}) {
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color](wxMouseEvent &e) {
w->Bind(wxEVT_ENTER_WINDOW, [this, w, panel_color, printer_bed_hovered](wxMouseEvent &e) {
printer_bed_hovered->insert(w);
if(!p->combo_printer_bed->HasFocus())
p->panel_printer_bed->SetBorderColor(panel_color.bd_hover);
if(w == p->image_printer_bed && !p->combo_printer_bed->is_drop_down()) // dont trigger while combo open
on_enter_image_printer_bed(e);
e.Skip();
});
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color](wxMouseEvent &e) {
// Use event-relative coords instead of wxGetMousePosition() which
// returns (0,0) on Wayland for global screen coordinates.
wxWindow* evtObj = dynamic_cast<wxWindow*>(e.GetEventObject());
wxPoint screenPos = evtObj ? evtObj->ClientToScreen(e.GetPosition()) : wxGetMousePosition();
wxWindow* next_w = wxFindWindowAtPoint(screenPos);
if (!p->combo_printer_bed->HasFocus() && (!next_w || !p->panel_printer_bed->IsDescendant(next_w)))
w->Bind(wxEVT_LEAVE_WINDOW, [this, w, panel_color, printer_bed_hovered](wxMouseEvent &e) {
printer_bed_hovered->erase(w);
if (printer_bed_hovered->empty() && !p->combo_printer_bed->HasFocus())
p->panel_printer_bed->SetBorderColor(panel_color.bd_normal);
if(w == p->image_printer_bed)
on_leave_image_printer_bed(e);