From 88b4a63228d21edc6685c56904a317bfa32ace28 Mon Sep 17 00:00:00 2001 From: SoftFever Date: Tue, 19 May 2026 01:01:53 +0800 Subject: [PATCH] Fix Linux data-view dropdown popup parenting (#13721) Delay opening the object-list filament dropdown on wxGTK until the editor window is mapped, avoiding popup creation without a valid native toplevel. Also set the GTK transient parent for dropdown popups created from data-view cell editors. --- src/slic3r/GUI/ExtraRenderers.cpp | 12 ++++++++++-- src/slic3r/GUI/Widgets/DropDown.cpp | 24 ++++++++++++++++++++++++ src/slic3r/GUI/Widgets/DropDown.hpp | 2 ++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/ExtraRenderers.cpp b/src/slic3r/GUI/ExtraRenderers.cpp index 28837dbdad..18811ef241 100644 --- a/src/slic3r/GUI/ExtraRenderers.cpp +++ b/src/slic3r/GUI/ExtraRenderers.cpp @@ -324,9 +324,18 @@ wxWindow* BitmapChoiceRenderer::CreateEditorCtrl(wxWindow* parent, wxRect labelR else c_editor->SetSelection(atoi(data.GetText().c_str()) - 1); - // Open the dropdown immediately when the editor is focused. c_editor->Bind(wxEVT_SET_FOCUS, [c_editor](wxFocusEvent& evt) { +#ifdef __WXGTK__ + // On wxGTK the data-view editor may receive focus before its native + // window is mapped. Opening the popup one event later avoids creating + // the GTK popup without a valid toplevel parent. + c_editor->CallAfter([c_editor]() { + if (c_editor->IsShownOnScreen()) + c_editor->ForceDropdownOpen(); + }); +#else c_editor->ForceDropdownOpen(); +#endif evt.Skip(); }); @@ -392,4 +401,3 @@ wxSize TextRenderer::GetSize() const return GetTextExtent(m_value); } - diff --git a/src/slic3r/GUI/Widgets/DropDown.cpp b/src/slic3r/GUI/Widgets/DropDown.cpp index f33fd04800..973113d0ac 100644 --- a/src/slic3r/GUI/Widgets/DropDown.cpp +++ b/src/slic3r/GUI/Widgets/DropDown.cpp @@ -167,6 +167,30 @@ bool DropDown::HasDismissLongTime() (now - dismissTime).total_milliseconds() >= 20; } +void DropDown::Popup(wxWindow *focus) +{ +#ifdef __WXGTK__ + if (!mainDropDown && m_widget) { + // Data-view cell editors can receive focus before wxGTK infers a + // native popup parent, so provide the current toplevel explicitly. + GtkWindow *transient_parent = nullptr; + for (wxWindow *win = GetParent(); win; win = win->GetParent()) { + GtkWidget *widget = static_cast(win->GetHandle()); + if (!widget) + continue; + GtkWidget *top = gtk_widget_get_toplevel(widget); + if (GTK_IS_WINDOW(top)) { + transient_parent = GTK_WINDOW(top); + break; + } + } + if (transient_parent) + gtk_window_set_transient_for(GTK_WINDOW(m_widget), transient_parent); + } +#endif + PopupWindow::Popup(focus); +} + void DropDown::paintEvent(wxPaintEvent& evt) { // depending on your system you may need to look at double-buffered dcs diff --git a/src/slic3r/GUI/Widgets/DropDown.hpp b/src/slic3r/GUI/Widgets/DropDown.hpp index 639a13e526..09041e3dc0 100644 --- a/src/slic3r/GUI/Widgets/DropDown.hpp +++ b/src/slic3r/GUI/Widgets/DropDown.hpp @@ -105,6 +105,8 @@ public: bool HasDismissLongTime(); + void Popup(wxWindow *focus = nullptr) override; + protected: void Dismiss() override;